问题
I'm new in here and also new to the CDI world, and the first task I got in my job was to find out a way to controlled CDI uploading.
We are using both EJB 3.1
and CDI 1.0
, and because they are controlled by different containers, we can control when and in what order the EJB Managed Beans will be up by using @Startup
and @Singleton
annotations.
But the @Inject
CDI bean I have declared in my class is coming as null since the CDI Container hasn't started yet.
I have been trying for several days now to look up for solutions and the one I found here did not worked (still came as null).
We are using Java EE 6 and running the application on WebSphere Application Server 8.
Please, if you could help me find a way to control CDI uploading inside and regardless of the EJB?
here is a sample code of it:
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@Singleton
@Startup
public class BaseStartupLoader{
/**
* Default constructor.
*/
@Inject @MyStartup
BaseStartUp myStartup;
private static Logger m_logger = LoggerFactory.getLogger(BaseStartupLoader.class);
public BaseStartupLoader() {
}
@PostConstruct
public void init(){
String applicationName = null;
try {
applicationName = myStartup.getClass().getName();
myStartup.load();
} catch (IllegalAccessException e) {
m_logger.error("Faild to load data into preload system. "+e);
} catch (InstantiationException e) {
m_logger.error("Faild to load data into preload system. "+e);
} catch (ClassNotFoundException e) {
m_logger.error("Faild to load data into preload system - Class "+ applicationName + "Not found. "+e);
}
}
}
Here is the BaseStartup Interface:
public interface BaseStartUp {
public void load() throws IllegalAccessException, InstantiationException, ClassNotFoundException;
}
The Qualifier and Implementation:
@Retention(RetentionPolicy.RUNTIME)
@Target ({ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Qualifier
@Dependent
public @interface MyStartup {
}
@MyStartup
public class MyStartUpLoader implements BaseStartUp {
@Inject
SomeConfigLoader config;
@Override
public void load() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
conifg.init();
}
}
回答1:
After much research I found some help from the guys in IBM, since we are working with WebSphere Application Server I can just add a JVM Property called:
"com.ibm.ws.cdi.immediate.ejb.start" = true
to the WAS in the Admin console, and he will make sure that once I will get to the EJB @PostConstruct method in the @Startup bean I created the CDI Container will already be up and running and already injected.
It Works!!
Here is the link to the Problem and Solution in IBM site:
http://www-01.ibm.com/support/docview.wss?uid=swg1PM62774
回答2:
Maybe double check that CDI is in fact enabled in all places of the application where it needs to be. Try adding this code to BaseStartupLoader
as an experiment:
@Singleton
@Startup
public class BaseStartupLoader {
@Inject @MyStartup
BaseStartUp myStartup;
@Inject
private InjectionTest test;
public static class InjectionTest {}
}
If the test
variable comes up null in the @PostConstruct
, then CDI is likely not enabled in the jar where BaseStartupLoader
is declared.
If say, for example, BaseStartupLoader
is declared in a jar called orange.jar
and MyStartUpLoader
is declared in a jar called yellow.jar
, then both these files must exist:
orange.jar!/META-INF/beans.xml
yellow.jar!/META-INF/beans.xml
If CDI is properly enabled in both jars via a META-INF/beans.xml
, then this is a bug in the container. All @Inject
points are required to be completed (for CDI-enabled jars), prior to @PostConstruct
being called. This is true regardless of if @Startup
is used and one of the beans happens to be an EJB.
回答3:
Take a look at DeltaSpike. There's a CDI Control module that should do what you're looking for now. I believe Java EE 7 should fix this as well.
来源:https://stackoverflow.com/questions/14019030/controlling-cdi-startup-inside-ejb-3-1