问题
I just read the very nice explanation of the various managed beans and their relations on Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean and as i face a annoying problem in my application i want to know if it is possible to control or influence the way how and when beans are started.
In my Java EE application I use EJB, CDI and JSF2 as view technology. Via SPI a service from a third party is booted and it configures a job executor which starts jobs and handles other timer relevant stuff. One job is immediately executed when the job executor finished its bootstrapping. This job uses CDI inject to get access to some beans and one of these beans make use of an EJB.
The problem is now that most of the time the Java EE 6 server (JBoss 7.1.1) starts the EJB is still not available then the job tries to access it. An exceptions is thrown and the job fails and the service is build to deactivate that failed job. Well, deactivating a faild job seems to be not too bad. The only solution for the job to get up and running again is to undeploy it and to redeploy it again. Which is a manual task unfortunately and it can not be done programmatically.
And, to make things bad: in rare cases this does not happen.
So, my question now is: can i somehow control the initialisation and deployment of the EJB and CDI beans so that i can ensure that all EJB beans are initialzed before the CDI beans are initialized?
I have set initialize-in-order to true in the EARs application.xml and set the sequence of the EJBs so that they get initialized they way i need them (EJB core, then EJB business, then WAR), but the CDI based service is placed as JAR in the lib folder.
回答1:
Excerpt from Java EE 6 Tutorial with some modifications:
@Singleton
@Startup
public class BeanA { ... }
@Qualifier
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface EjbStarted {}
@Singleton
@Startup
@DependsOn("BeanA", "BeanB", "BeanC")
public class LastBean {
@Inject @EjbStarted Event<String> event;
@PostConstruct
public void startService() {
// At this moment PrimaryBean is ready for use
event.fire("LastBean");
}
}
public class CDIService {
public void start(@Observes @EjbStarted String name) {
if("LastBean".equals(name)) {
startService();
}
}
}
UPDATE: While thinking about the problem, I somehow forgot that you want the initialization order in CDI beans, so the answer is somewhat out of context, sorry about that :)
UPDATE 2: Added how to make a CDI service start after EJBs
来源:https://stackoverflow.com/questions/12235464/java-ee-6-controlling-startup-of-managed-beans-with-dependencies-cdi-ejb