尝试创建计时器时出现NullPointerException异常。显然,TimerService尚未设置,但是我的问题是,为什么?据我所知,我正在遵循确实起作用的应用程序中另一个类使用的确切模式。
注意:我是EJB的新手,所以说明很有帮助
@Stateless
public class MyClass implements SomeInterface
{
private static final Logger ourLogger = new Logger(MyClass.class);
private volatile Timer timer = null;
private volatile static MyClass instance = null;
@javax.annotation.Resource
TimerService timerService;
@Override
public synchronized void myMethod()
{
resetTimer();
//do other stuff
}
/**
* Creates the timer.
*/
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private synchronized void resetTimer()
{
if (timer != null)
{
timer.cancel();
timer = null;
}
//NullPointerException on next line:
timer = timerService.createTimer(30000, "My Note");
}
public static MyClass getInstance()
{//MDB calls this, then runs instance.myMethod
if (instance == null)
{
instance = new MyClass ();
}
return instance;
}
@Timeout
public synchronized void timeout()
{
//Do some stuff
instance = null;
}
}
最佳答案
您发布的其他代码使此代码在错误的事情列表中又增加了一件事(我在对您的问题的第一个评论中就开始了。)
您正在尝试在SLSB中实现Singleton设计模式。这在许多层面上都是错误的。
如果需要单例-只需使用@Singleton
EJB。如果您按照发布的方式进行操作,则基本上不是在实例化EJB,而是实例化一些常规Java类。难怪为什么不发生注入-容器对您在方法中创建的实例一无所知。
如果要拥有EJB,只需为其提供默认构造函数,然后通过Mcc中的@EJB
使用它。然后,容器将实例化它并赋予它EJB性质(具有所有那些管理生命周期,池化,依赖项注入等)。
总结一下,您可以在已发布的代码中找到错误的事情的列表:
您正在无状态EJB中保持状态,
您正在将单例模式实施到按规范池的EJB中,
您正在同步已经是线程安全的(也是按规范的)EJB,
您要将@TransactionAttribute
添加到私有方法中;我什至不确定这是否有意义。 @TransactionAttribute
表示您正在定义业务方法。同时,此方法是私有的,这意味着它不能成为业务接口的一部分,因此它不是业务方法。
希望对你有帮助!