前几天自己在项目中增加了报表,类型是天报,每天汇总的时候是晚上十二点20,第二天看的时候发现,每一份天报都有两份数据,而且两份数据还不完全一样(第二次的数据正好是第一次的两倍,而且这两份数据是同一个线程中跑的).
经过多次查看代码发现代码中定时器的方法也只有一次,所以不可能是方法重复了,通过看jboss的日志发现,日志中有这么一句话:
ERROR [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-19-thread-2) Error invoking timeout for timer: [id=2d9c88a2-3eee-41a4-8cf3-dc7ce4a11363 timedObjectId=jboss.j2ee:jar=isa-timer-02.02.jar,name=RptStbQmsTimer,service=EJB3 auto-timer?:true persistent?:false timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37b8c66f initialExpiration=Thu Dec 06 00:20:30 CST 2012 intervalDuration(in milli sec)=0 nextExpiration=Sun Dec 09 00:20:30 CST 2012 timerState=IN_TIMEOUT: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
报表中的数据出错了,事务要回滚
再查看日志又发现日志有这样一句话:
[org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-19-thread-2) Timer: [id=2d9c88a2-3eee-41a4-8cf3-dc7ce4a11363 timedObjectId=jboss.j2ee:jar=isa-timer-02.02.jar,name=RptStbQmsTimer,service=EJB3 auto-timer?:true persistent?:false timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37b8c66f initialExpiration=Thu Dec 06 00:20:30 CST 2012 intervalDuration(in milli sec)=0 nextExpiration=Sun Dec 09 00:20:30 CST 2012 timerState=IN_TIMEOUT will be retried
2012-12-08 01:18:47,527 INFO [org.jboss.ejb3.timerservice.mk2.task.TimerTask] (pool-19-thread-2) Retrying timeout for timer: [id=2d9c88a2-3eee-41a4-8cf3-dc7ce4a11363 timedObjectId=jboss.j2ee:jar=isa-timer-02.02.jar,name=RptStbQmsTimer,service=EJB3 auto-timer?:true persistent?:false timerService=org.jboss.ejb3.timerservice.mk2.TimerServiceImpl@37b8c66f initialExpiration=Thu Dec 06 00:20:30 CST 2012 intervalDuration(in milli sec)=0 nextExpiration=Sun Dec 09 00:20:30 CST 2012 timerState=IN_TIMEOUT
看来jboss 要retry这个定时任务了,于是重做了这个出错这个任务方法有所有的任务,所以就有两份数据.
解决的方法是:
在定时器的类的上面声明定时任务不支持事务,即加上这句话@TransactionAttribute(TransactionAttributeType.NEVER)就可以了
至于为什么只有两份而不会是多份,看了log不会一直重跑任务,第一次超时retry后就不再超时了,据说是JBoss6的bug,在JBoss7中修改了,所以超时最多会跑两次,不会一直跑.另外两份数据在同一线程中跑的,数据来源一样,结果不一样这个暂时还没有想通,待去多翻一点资料做更多的了解,再说明情况