/*
* Copyright 2015 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.
*
* 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;
import org.drools.core.command.SingleSessionCommandService;
import org.drools.core.command.impl.AbstractInterceptor;
import org.drools.core.command.impl.ExecutableCommand;
import org.drools.core.command.runtime.process.AbortProcessInstanceCommand;
import org.drools.core.command.runtime.process.AbortWorkItemCommand;
import org.drools.core.command.runtime.process.CompleteWorkItemCommand;
import org.drools.core.command.runtime.process.CreateCorrelatedProcessInstanceCommand;
import org.drools.core.command.runtime.process.CreateProcessInstanceCommand;
import org.drools.core.command.runtime.process.SignalEventCommand;
import org.drools.core.command.runtime.process.StartProcessCommand;
import org.drools.core.command.runtime.process.StartProcessInstanceCommand;
import org.drools.core.command.runtime.rule.FireAllRulesCommand;
import org.drools.core.fluent.impl.InternalExecutable;
import org.drools.persistence.PersistableRunner;
import org.jbpm.persistence.api.ProcessPersistenceContext;
import org.jbpm.persistence.api.ProcessPersistenceContextManager;
import org.jbpm.persistence.processinstance.ProcessInstanceInfo;
import org.jbpm.process.instance.ProcessInstance;
import org.kie.api.command.Command;
import org.kie.api.runtime.Context;
import org.kie.api.runtime.Executable;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.RequestContext;
import java.util.Collection;
public class ManualPersistProcessInterceptor extends AbstractInterceptor {
private final SingleSessionCommandService interceptedService;
public ManualPersistProcessInterceptor(SingleSessionCommandService interceptedService) {
this.interceptedService = interceptedService;
}
@Override
public RequestContext execute( Executable executable, RequestContext ctx ) {
RuntimeException error = null;
try {
executeNext(executable,ctx);
} catch (RuntimeException e) {
//still try to save
error = e;
}
KieSession ksession = interceptedService.getKieSession();
try {
java.lang.reflect.Field jpmField = PersistableRunner.class.getDeclaredField( "jpm" );
jpmField.setAccessible(true);
Object jpm = jpmField.get(interceptedService);
if (error == null && isValidCommand( ( (InternalExecutable) executable ).getBatches().get(0).getCommands().get(0))) {
executeNext(new SingleCommandExecutable( new PersistProcessCommand(jpm, ksession) ), ctx);
}
} catch (Exception e) {
throw new RuntimeException("Couldn't force persistence of process instance infos", e);
}
if (error != null) {
throw error;
}
return ctx;
}
protected boolean isValidCommand(Command<?> command) {
return (command instanceof StartProcessCommand) ||
(command instanceof CreateProcessInstanceCommand) ||
(command instanceof CreateCorrelatedProcessInstanceCommand) ||
(command instanceof StartProcessInstanceCommand) ||
(command instanceof SignalEventCommand) ||
(command instanceof CompleteWorkItemCommand) ||
(command instanceof AbortWorkItemCommand) ||
(command instanceof AbortProcessInstanceCommand) ||
(command instanceof FireAllRulesCommand);
}
public static class PersistProcessCommand implements ExecutableCommand<Void> {
private final ProcessPersistenceContext persistenceContext;
private final KieSession ksession;
public PersistProcessCommand(Object jpm, KieSession ksession) {
this.persistenceContext = ((ProcessPersistenceContextManager) jpm).getProcessPersistenceContext();
this.ksession = ksession;
}
@Override
public Void execute(Context context ) {
Collection<?> processInstances = ksession.getProcessInstances();
for (Object obj : processInstances) {
ProcessInstance instance = (ProcessInstance) obj;
boolean notCompeted = instance.getState() != ProcessInstance.STATE_COMPLETED;
boolean notAborted = instance.getState() != ProcessInstance.STATE_ABORTED;
boolean hasId = instance.getId() > 0;
if (hasId && notCompeted && notAborted) {
ProcessInstanceInfo info = new ProcessInstanceInfo(instance, ksession.getEnvironment());
info.setId(instance.getId());
info.transform();
persistenceContext.persist(info);
}
}
return null;
}
}
public SingleSessionCommandService getInterceptedService() {
return interceptedService;
}
}