我通过 @EJB 注释使用无状态 EJB...大多数时候一切都正常工作,但似乎有时应该注入的内容会解析为 NULL,从而导致空指针异常。
什么可能导致这个间歇性问题?
JBoss 4.x 不会自动将 EJB 注入 Servlet/JSP/POJO。但它也不会抱怨注释,它在运行时根本不起作用,并且对象将保持为 Null。您必须使用 JNDI 查找。
来自 JBoss 文档:
EJB @EJB 注释的查找是 可用于 servlet 和 JSP,但是 不幸的是,我们还没有更新 tomcat支持它。还有,雄猫 使用旧的 XML 格式,因此您 也不能使用XML。所以现在,你 必须通过其全局查找 EJB JNDI 名称。这不符合规定,但是 如果你抽象得足够多,你就会 很好。
示例:
public void init() throws ServletException
{
super.init();
try
{
InitialContext ctx = new InitialContext();
// J2EE 1.5 has not yet defined exact XML <ejb-ref> syntax for EJB3
CalculatorLocal calculator = (CalculatorLocal)ctx.lookup("tutorial/CalculatorBean/local");
setCalculator(calculator);
}
catch (NamingException e)
{
throw new RuntimeException(e);
}
}
请务必使用您的 EAR 名称作为您要查找的名称的第一个部分(上例中的
tutorial
)。
参考资料:
我知道已经晚了,但我们遇到了同样的问题。最重要的信息是,这种情况有时会发生,但我们无法找出原因。
他注意到的第二件事是“父”类中的字段存在问题。我们有课
public abstract class SessionContained {
@EJB
protected SessionStoreLocal sessionStoreEJB;
....
}
@Stateless
public class SomeEJB extends SessionContained {
@EJB
SomeAnotherRemote anotherEJB;
...
}
在调试中,
SomeAnotherRemote anotherEJB;
已正确初始化,但SessionStoreLocal sessionStoreEJB;
为空。
我们找到了一些解决这个问题的方法,首先创建 EjbUtil 类:
public class EjbUtil
{
public static String ejbContextClassName = System.getProperty("ejbContextClass", EJB31Context.class.getName());
public static EjbContext ejbContext;
public static <T> T lookup(Class<T> interfejz)
{
Log log = new Log(EjbUtil.class);
try {
log.trace("EJButil.lookup: {}", interfejz.getName());
return getEJBContext().lookup(interfejz);
}
catch (Exception e) {
log.error("Blad podczas operacji lookup", e.getCause());
}
return null;
}
public static EjbContext getEJBContext()
throws ClassNotFoundException
{
if (ejbContext == null) {
try {
Class<EjbContext> clazz = (Class<EjbContext>)Class.forName(ejbContextClassName);
ejbContext = clazz.getConstructor(new Class[] {}).newInstance((Object[])null);
}
catch (Throwable e) {
Log log = new Log(EjbUtil.class);
log.error("Blad podczas inicjalizacji ejbContext", e.getCause());
}
}
return ejbContext;
}
}
并添加:
public abstract class SessionContained {
@EJB
private SessionStoreLocal sessionStoreEJB;
@NotLogged
public SessionStoreLocal getSessionStoreLocal() {
if (sessionStoreEJB == null) {
log.warn("SessionStoreLocal is null! Trying to retrieve instance.");
sessionStoreEJB = EjbUtil.lookup(SessionStoreLocal.class);
if (sessionStoreEJB == null) {
log.error("SessionStoreLocal is null! Returning null as homenet session.");
return null;
}
}
return sessionStoreEJB;
}
它看起来现在可以工作......也许它会帮助处理这个旧代码的人。