我有一个EJB Timer 3.0,这个计时器有一个大约每次调用运行6个小时的方法。我实现的定时器如下:
@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class BatchJobConsumerTimer implements BatchJobConsumerTimerLocal {
@Resource
TimerService timerService;
@EJB
ModelOperationsLocal modelOperations;
private static final long ONE_DAY_IN_MILLISECONDS = 86400000L;
private static final Logger LOG = Logger
.getLogger(BatchJobConsumerTimer.class);
public BatchJobConsumerTimer() {
}
@Timeout
public void timeout(Timer timer) {
LOG.info("Entering timeout method.");
if(TimerRunningChecker.isWorking()){
LOG.warn("A TIMER ALREADY IS RUNNING, SECOND TIMER WANTS TO ENTER TIMEOUT METHOD");
return;
} else {
TimerRunningChecker.setWorking(true);
}
TimerConfiguration timerConfiguration = (TimerConfiguration) timer
.getInfo();
if (timerConfiguration != null) {
Calendar calendar = new GregorianCalendar();
if (isWorkDay(timerConfiguration.getSelectedDays())) {
Date startTime = new Date(System.currentTimeMillis());
Boolean and = timerConfiguration.getAnd();
Integer numberOfJobs = timerConfiguration.getNumberOfJobs();
int jobConsumed = 0;
INFINITE: while (true) {
List<Job> findWaitingJobs = modelOperations
.getLatestUploadedWaitingBatchJobs((numberOfJobs == -1 || numberOfJobs > 100) ? 100
: numberOfJobs);
if (findWaitingJobs != null) {
if(findWaitingJobs.size() == 0){
LOG.warn("There is no jobs to consume.");
break INFINITE;
}
for (Job job : findWaitingJobs) {
++jobConsumed;// means successful and unsuccessful
LOG.info("Job Number: " + (jobConsumed));
if (and) {
if (numberOfJobs != -1) {
if (jobConsumed > numberOfJobs
&& isEqualsAfterEndSchedule(
calendar,
timerConfiguration)) {
LOG.info("jobConsumed > numberOfJobs && isEqualsAfterEndSchedule(calendar) is true");
break INFINITE;
}
} else {
if (isEqualsAfterEndSchedule(calendar,
timerConfiguration)) {
LOG.info("numberOfJobs = infinite && isEqualsAfterEndSchedule(calendar) is true");
break INFINITE;
}
}
} else {
if (numberOfJobs != -1) {
if (jobConsumed > numberOfJobs
|| isEqualsAfterEndSchedule(
calendar,
timerConfiguration)) {
LOG.info("jobConsumed > numberOfJobs || isEqualsAfterEndSchedule(calendar) is true");
break INFINITE;
}
} else {
if (isEqualsAfterEndSchedule(calendar,
timerConfiguration)) {
LOG.info("numberOfJobs = infinite || isEqualsAfterEndSchedule(calendar) is true");
break INFINITE;
}
}
}
try {
LOG.info(job.getServiceNumber()
+ " hizmet numarali is tuketilicek.");
modelOperations.update(job);
} catch (Exception e) {
LOG.error(e, e);
}
}
} else {
// liste bos don method'dan
break INFINITE;
}
}
//send email
Date endTime = new Date(System.currentTimeMillis());
try {
modelOperations.sendBatchOperationMail(startTime, endTime);
} catch (Exception e) {
LOG.error(e, e);
}
} else {
LOG.warn("Today is not the working day.");
}
} else {
LOG.warn("TimerConfiguration is not set.");
}
if(!TimerRunningChecker.isWorking()){
LOG.warn("A TIMER WANTS CHANGE THE STATE OF WORKING TO NOT WORKING STATE, BUT IT IS ALREADY SET NOT WORKING STATE");
return;
} else {
TimerRunningChecker.setWorking(false);
}
LOG.info("Exiting timout method.");
}
@Override
public void createTimer(TimerConfiguration timerConfiguration)
throws Exception {
// stop the other timers.
Collection<Timer> timers = timerService.getTimers();
for (Timer timer : timers) {
timer.cancel();
}
timerService.createTimer(
getRemainingTimeToFirstExpiration(timerConfiguration),
ONE_DAY_IN_MILLISECONDS, timerConfiguration);
}
private long getRemainingTimeToFirstExpiration(
TimerConfiguration timerConfiguration) {
Calendar now = new GregorianCalendar();
Calendar nextStart = new GregorianCalendar();
nextStart.set(Calendar.HOUR_OF_DAY, timerConfiguration.getBeginHour());
nextStart.set(Calendar.MINUTE, timerConfiguration.getBeginMinute());
nextStart.set(Calendar.SECOND, timerConfiguration.getBeginSecond());
long diff = nextStart.getTimeInMillis() - now.getTimeInMillis();
return (diff < 0 ? diff + ONE_DAY_IN_MILLISECONDS : diff);
}
private boolean isEqualsAfterEndSchedule(Calendar calendar,
TimerConfiguration timerConfiguration) {
calendar.setTimeInMillis(System.currentTimeMillis());
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
int currentMinute = calendar.get(Calendar.MINUTE);
int currentSecond = calendar.get(Calendar.SECOND);
if (currentHour > timerConfiguration.getEndHour()) {
return true;
} else if (currentHour == timerConfiguration.getEndHour()) {
if (currentMinute > timerConfiguration.getEndMinute()) {
return true;
} else if (currentMinute == timerConfiguration.getEndMinute()) {
if (currentSecond >= timerConfiguration.getEndSecond()) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
private boolean isWorkDay(String selectedDays) {
if(selectedDays == null){
LOG.error("selectedDays is NULL!");
return false;
}
LOG.info("selectedDays: " + selectedDays);
if (selectedDays.equals("?")) {
return false;
}
if (selectedDays.equals("*")) {
return true;
}
Calendar now = GregorianCalendar.getInstance();
int i = now.get(Calendar.DAY_OF_WEEK);
LOG.info("now.get(Calendar.DAY_OF_WEEK): " + i);
if (selectedDays.contains("" + i)) {
return true;
} else {
return false;
}
}
}
我必须部署此应用程序的应用程序服务器是Weblogic 10.3.4,并且事务超时配置已调整为30秒。
根据我上面提到的事情,超时方法在执行开始30秒后自动回滚,weblogic会不断重试。我试图通过注释类,方法来删除此事务,但没有成功。如何使此方法无事务?谢谢你的兴趣。
顺便说一句,balusC对question的建议是否可以从这个问题中解决?
答案 0 :(得分:1)
在这种情况下,请使用BeanManagement Transaction。否则,bean Timerservice本身将启动一个事务来满足使用XA接口的默认持久存储上的事务(在每种情况下都是WLS上的文件存储)。 此解决方法有助于Weblogic Application Server以及其他应用程序服务器。
@Stateless
@Local(TimerBusinessService.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class TimerBusinessServiceImpl implements TimerBusinessService {
@Resource
private TimerService timerService;
@EJB
private NonTxService nonTxService;
@Override
public void doStartTimer() throws EjpdBusinessException {
long everyDay = 86400000;...
timerService.createTimer(0, everyDay, ...);
}
@Timeout
public void periodicalTimerMethode(Timer timer) throws EjpdBusinessException {
try {
nonTxService.proceedAction ();
} catch (…Exception ex) {
throw new RuntimeException(“..”, ex);
}
}
}