org.jbpm.persistence.timer.GlobalJpaTimerJobInstance Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.persistence.timer;
import java.io.Serializable;
import org.drools.core.time.InternalSchedulerService;
import org.drools.core.time.Job;
import org.drools.core.time.JobContext;
import org.drools.core.time.JobHandle;
import org.drools.core.time.Trigger;
import org.drools.core.time.impl.DefaultJobHandle;
import org.drools.persistence.api.TransactionManager;
import org.drools.persistence.api.TransactionManagerFactory;
import org.drools.persistence.jpa.JDKCallableJobCommand;
import org.drools.persistence.jpa.JpaTimerJobInstance;
import org.jbpm.persistence.jta.ContainerManagedTransactionManager;
import org.jbpm.process.core.async.AsyncExecutionMarker;
import org.jbpm.process.core.timer.TimerServiceRegistry;
import org.jbpm.process.core.timer.impl.GlobalTimerService;
import org.jbpm.process.core.timer.impl.GlobalTimerService.DisposableCommandService;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.EnvironmentName;
import org.kie.api.runtime.ExecutableRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Extension to the regular JpaTimerJobInstance
that makes use of
* GlobalTimerService to allow auto reactivate session.
*
* Important to note is that when timer service created session this job instance
* will dispose that session to leave it in the same state it was before job was executed
* to avoid concurrent usage of the same session by different threads
*
*/
public class GlobalJpaTimerJobInstance extends JpaTimerJobInstance {
private static final Logger logger = LoggerFactory.getLogger(GlobalJpaTimerJobInstance.class);
private static final long serialVersionUID = -5383556604449217342L;
private String timerServiceId;
private String externalTimerId;
private Serializable timerInfo;
public GlobalJpaTimerJobInstance(Job job, JobContext ctx, Trigger trigger,
JobHandle handle, InternalSchedulerService scheduler) {
super(job, ctx, trigger, handle, scheduler);
timerServiceId = ((GlobalTimerService) scheduler).getTimerServiceId();
}
@Override
public Void call() throws Exception {
AsyncExecutionMarker.markAsync();
ExecutableRunner runner = null;
TransactionManager jtaTm = null;
boolean success = false;
try {
JDKCallableJobCommand command = new JDKCallableJobCommand( this );
if (scheduler == null || ((GlobalTimerService) scheduler).getRuntimeManager().isClosed()) {
scheduler = (InternalSchedulerService) TimerServiceRegistry.getInstance().get(timerServiceId);
}
if (scheduler == null) {
throw new RuntimeException("No scheduler found for " + timerServiceId);
}
jtaTm = startTxIfNeeded(((GlobalTimerService) scheduler).getRuntimeManager().getEnvironment().getEnvironment());
runner = ((GlobalTimerService) scheduler).getRunner( getJobContext() );
runner.execute( command );
GlobalJPATimerJobFactoryManager timerService = ((GlobalJPATimerJobFactoryManager)((GlobalTimerService) scheduler).getTimerJobFactoryManager());
timerService.removeTimerJobInstance(((DefaultJobHandle)getJobHandle()).getTimerJobInstance());
success = true;
return null;
} catch( Exception e ) {
e.printStackTrace();
success = false;
throw e;
} finally {
AsyncExecutionMarker.reset();
if (runner != null && runner instanceof DisposableCommandService) {
if (allowedToDispose(((DisposableCommandService) runner).getEnvironment())) {
logger.debug("Allowed to dispose command service from global timer job instance");
((DisposableCommandService) runner).dispose();
}
}
closeTansactionIfNeeded(jtaTm, success);
}
}
public Serializable getTimerInfo() {
return timerInfo;
}
public void setTimerInfo(Serializable timerInfo) {
this.timerInfo = timerInfo;
}
public String getExternalTimerId() {
return externalTimerId;
}
public void setExternalTimerId(String externalTimerId) {
this.externalTimerId = externalTimerId;
}
@Override
public String toString() {
return "GlobalJpaTimerJobInstance [timerServiceId=" + timerServiceId
+ ", getJobHandle()=" + getJobHandle() + "]";
}
protected boolean allowedToDispose(Environment environment) {
if (hasEnvironmentEntry(environment, "IS_JTA_TRANSACTION", false)) {
return true;
}
TransactionManager transactionManager = null;
Object txm = environment.get(EnvironmentName.TRANSACTION_MANAGER);
if (txm != null && txm instanceof TransactionManager) {
transactionManager = (TransactionManager) txm;
} else {
transactionManager = TransactionManagerFactory.get().newTransactionManager();
}
int status = transactionManager.getStatus();
if (status != TransactionManager.STATUS_NO_TRANSACTION
&& status != TransactionManager.STATUS_ROLLEDBACK
&& status != TransactionManager.STATUS_COMMITTED) {
return false;
}
return true;
}
protected boolean hasEnvironmentEntry(Environment environment, String name, Object value) {
Object envEntry = environment.get(name);
if (value == null) {
return envEntry == null;
}
return value.equals(envEntry);
}
protected TransactionManager startTxIfNeeded(Environment environment) {
try {
if (hasEnvironmentEntry(environment, "IS_TIMER_CMT", true)) {
return null;
}
if (environment.get(EnvironmentName.TRANSACTION_MANAGER) instanceof ContainerManagedTransactionManager) {
TransactionManager tm = TransactionManagerFactory.get().newTransactionManager();
if (tm.begin()) {
return tm;
}
}
} catch (Exception e) {
logger.debug("Unable to optionally start transaction due to {}", e.getMessage(), e);
}
return null;
}
protected void closeTansactionIfNeeded(TransactionManager jtaTm, boolean commit) {
if (jtaTm != null) {
if (commit) {
jtaTm.commit(true);
} else {
jtaTm.rollback(true);
}
}
}
}