Skip to content

Commit

Permalink
[BZ-1119695] implement incremental compilation for jbpm processes
Browse files Browse the repository at this point in the history
  • Loading branch information
mariofusco committed Sep 25, 2014
1 parent 0dcd8e5 commit 4f2e3a5
Show file tree
Hide file tree
Showing 2 changed files with 230 additions and 16 deletions.
Expand Up @@ -15,15 +15,6 @@
*/
package org.jbpm.compiler;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.FactoryConfigurationError;

import org.drools.compiler.compiler.BaseKnowledgeBuilderResultImpl;
import org.drools.compiler.compiler.Dialect;
import org.drools.compiler.compiler.DialectCompiletimeRegistry;
Expand All @@ -38,7 +29,6 @@
import org.drools.compiler.lang.descr.ProcessDescr;
import org.drools.compiler.rule.builder.dialect.java.JavaDialect;
import org.drools.core.RuntimeDroolsException;
import org.drools.core.io.internal.InternalResource;
import org.jbpm.compiler.xml.ProcessSemanticModule;
import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.compiler.xml.processes.RuleFlowMigrator;
Expand All @@ -56,7 +46,6 @@
import org.jbpm.process.core.validation.ProcessValidationError;
import org.jbpm.process.core.validation.ProcessValidator;
import org.jbpm.process.core.validation.ProcessValidatorRegistry;
import org.jbpm.process.instance.ProcessRuntimeImpl;
import org.jbpm.workflow.core.Constraint;
import org.jbpm.workflow.core.impl.ConnectionRef;
import org.jbpm.workflow.core.impl.DroolsConsequenceAction;
Expand All @@ -80,6 +69,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.parsers.FactoryConfigurationError;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* A ProcessBuilder can be used to build processes based on XML files
* containing a process definition.
Expand Down Expand Up @@ -108,7 +105,7 @@ public List<BaseKnowledgeBuilderResultImpl> getErrors() {
}

public void buildProcess(final Process process, Resource resource) {
if ( resource != null && ((InternalResource) resource).hasURL()) {
if ( resource != null ) {
((org.jbpm.process.core.Process) process).setResource(resource);
}
boolean hasErrors = false;
Expand Down Expand Up @@ -260,11 +257,12 @@ private void processNodes(
}
}

public List<BaseKnowledgeBuilderResultImpl> addProcessFromXml(final Resource resource) throws IOException {
public List<Process> addProcessFromXml(final Resource resource) throws IOException {
Reader reader = resource.getReader();
PackageBuilderConfiguration configuration = packageBuilder.getPackageBuilderConfiguration();
XmlProcessReader xmlReader = new XmlProcessReader( configuration.getSemanticModules(), packageBuilder.getRootClassLoader() );


List<Process> processes = null;
try {
String portRuleFlow = System.getProperty( "drools.ruleflow.port", "false" );
Reader portedReader = null;
Expand All @@ -273,7 +271,7 @@ public List<BaseKnowledgeBuilderResultImpl> addProcessFromXml(final Resource res
} else {
portedReader = reader;
}
List<Process> processes = xmlReader.read(portedReader);
processes = xmlReader.read(portedReader);
if (processes != null) {
// it is possible an xml file could not be parsed, so we need to
// stop null pointers
Expand All @@ -293,7 +291,7 @@ public List<BaseKnowledgeBuilderResultImpl> addProcessFromXml(final Resource res
reader.close();
}

return this.errors;
return processes;
}


Expand Down
@@ -0,0 +1,216 @@
package org.jbpm.kie.services.test;

import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.core.util.FileManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieScanner;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.scanner.MavenRepository;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.kie.scanner.MavenRepository.getMavenRepository;

@Ignore

This comment has been minimized.

Copy link
@psiroky

psiroky Sep 25, 2014

Contributor

Is there a reason for ignoring the test?

This comment has been minimized.

Copy link
@mariofusco

mariofusco Sep 25, 2014

Author Member

The test case is flagged with @ignore (like the biggest part of other tests related with the KieScanner) only because it needs to install the kjars in the local maven repository and for this reason it could fail when running in the continuous integration environment.

This comment has been minimized.

Copy link
@psiroky

psiroky Sep 25, 2014

Contributor

I see. You mean that multiple CI jobs could interfere with each other (e.g. changing the kjars simultaneously)? This could be I believe mitigated by using local Maven repository that is unique for each CI job (e.g. the repo is located in workspace of the build).

Or is there some other issue?

I think it would be beneficial if these tests were executed as a part of the standard CI runs. I would be glad to help here to make this happen.

The kie-server tests are also deploying the kjars as part of the test execution and the builds seem to be fine so far (dozens of builds were executed).

This comment has been minimized.

Copy link
@psiroky

psiroky Sep 26, 2014

Contributor

As agreed with Mario, I un-ignored one of the KieScanner test classes in Drools repo to see if they start to fail in CI. Once we get those tests reliable running, I will un-ignore also the other KieScanner related tests.

public class KieScannerTest {

private FileManager fileManager;
private File kPom;

private KieServices ks = KieServices.Factory.get();
private ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT");

@Before
public void setUp() throws Exception {
this.fileManager = new FileManager();
this.fileManager.setUp();
kPom = createKPom(fileManager, releaseId);
}

@After
public void tearDown() throws Exception {
this.fileManager.tearDown();
}

@Test
public void testKScanner() throws Exception {
List<String> results = new ArrayList<String>();
Map<String, Object> params = new HashMap<String, Object>();
params.put("results", results);

InternalKieModule kJar1 = createJbpmKieJar("Hello");
KieContainer kieContainer = ks.newKieContainer(releaseId);

MavenRepository repository = getMavenRepository();
repository.deployArtifact(releaseId, kJar1, kPom);

// create a ksesion and check it works as expected
KieSession ksession = kieContainer.newKieSession("KSession1");
ProcessInstance processInstance = ksession.startProcess("Minimal", params);
assertTrue(processInstance.getState() == ProcessInstance.STATE_COMPLETED);
assertEquals(1, results.size());
assertEquals("Hello", results.get(0));
results.clear();

InternalKieModule kJar2 = createJbpmKieJar("Morning");

repository.deployArtifact(releaseId, kJar2, kPom);

KieScanner scanner = ks.newKieScanner(kieContainer);
scanner.scanNow();

// create a ksesion and check it works as expected
KieSession ksession2 = kieContainer.newKieSession("KSession1");
ProcessInstance processInstance2 = ksession2.startProcess("Minimal", params);
assertTrue(processInstance2.getState() == ProcessInstance.STATE_COMPLETED);
assertEquals(1, results.size());
assertEquals("Morning", results.get(0));
results.clear();

ks.getRepository().removeKieModule(releaseId);
}

private InternalKieModule createJbpmKieJar(String message) {
KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
kfs.writePomXML(getPom(releaseId));

String file = "org/test/process.bpmn2";
kfs.write("src/main/resources/KBase1/" + file, createBPMN(message));

KieBuilder kieBuilder = ks.newKieBuilder(kfs);
assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty());

return (InternalKieModule) kieBuilder.getKieModule();
}

private String createBPMN(String message) {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
"<definitions id=\"Definition\"\n" +
" targetNamespace=\"http://www.example.org/MinimalExample\"\n" +
" typeLanguage=\"http://www.java.com/javaTypes\"\n" +
" expressionLanguage=\"http://www.mvel.org/2.0\"\n" +
" xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd\"\n" +
" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\"\n" +
" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\"\n" +
" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\"\n" +
" xmlns:tns=\"http://www.jboss.org/drools\">\n" +
"\n" +
" <process processType=\"Private\" isExecutable=\"true\" id=\"Minimal\" name=\"Minimal Process\" >\n" +
"\n" +
" <!-- process variables -->\n" +
" <dataObject id=\"results\"/>\n" +
"\n" +
" <!-- nodes -->\n" +
" <startEvent id=\"_1\" name=\"StartProcess\" />\n" +
" <scriptTask id=\"_2\" name=\"Hello\" >\n" +
" <script>results.add(\"" + message + "\");</script>\n" +
" </scriptTask>\n" +
" <endEvent id=\"_3\" name=\"EndProcess\" >\n" +
" <terminateEventDefinition/>\n" +
" </endEvent>\n" +
"\n" +
" <!-- connections -->\n" +
" <sequenceFlow id=\"_1-_2\" sourceRef=\"_1\" targetRef=\"_2\" />\n" +
" <sequenceFlow id=\"_2-_3\" sourceRef=\"_2\" targetRef=\"_3\" />\n" +
"\n" +
" </process>\n" +
"\n" +
" <bpmndi:BPMNDiagram>\n" +
" <bpmndi:BPMNPlane bpmnElement=\"Minimal\" >\n" +
" <bpmndi:BPMNShape bpmnElement=\"_1\" >\n" +
" <dc:Bounds x=\"15\" y=\"91\" width=\"48\" height=\"48\" />\n" +
" </bpmndi:BPMNShape>\n" +
" <bpmndi:BPMNShape bpmnElement=\"_2\" >\n" +
" <dc:Bounds x=\"95\" y=\"88\" width=\"83\" height=\"48\" />\n" +
" </bpmndi:BPMNShape>\n" +
" <bpmndi:BPMNShape bpmnElement=\"_3\" >\n" +
" <dc:Bounds x=\"258\" y=\"86\" width=\"48\" height=\"48\" />\n" +
" </bpmndi:BPMNShape>\n" +
" <bpmndi:BPMNEdge bpmnElement=\"_1-_2\" >\n" +
" <di:waypoint x=\"39\" y=\"115\" />\n" +
" <di:waypoint x=\"75\" y=\"46\" />\n" +
" <di:waypoint x=\"136\" y=\"112\" />\n" +
" </bpmndi:BPMNEdge>\n" +
" <bpmndi:BPMNEdge bpmnElement=\"_2-_3\" >\n" +
" <di:waypoint x=\"136\" y=\"112\" />\n" +
" <di:waypoint x=\"240\" y=\"240\" />\n" +
" <di:waypoint x=\"282\" y=\"110\" />\n" +
" </bpmndi:BPMNEdge>\n" +
" </bpmndi:BPMNPlane>\n" +
" </bpmndi:BPMNDiagram>\n" +
"\n" +
"</definitions>";
}

protected String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
String pom =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
"\n" +
" <groupId>" + releaseId.getGroupId() + "</groupId>\n" +
" <artifactId>" + releaseId.getArtifactId() + "</artifactId>\n" +
" <version>" + releaseId.getVersion() + "</version>\n" +
"\n";
if (dependencies != null && dependencies.length > 0) {
pom += "<dependencies>\n";
for (ReleaseId dep : dependencies) {
pom += "<dependency>\n";
pom += " <groupId>" + dep.getGroupId() + "</groupId>\n";
pom += " <artifactId>" + dep.getArtifactId() + "</artifactId>\n";
pom += " <version>" + dep.getVersion() + "</version>\n";
pom += "</dependency>\n";
}
pom += "</dependencies>\n";
}
pom += "</project>";
return pom;
}

protected File createKPom(FileManager fileManager, ReleaseId releaseId, ReleaseId... dependencies) throws IOException {
File pomFile = fileManager.newFile("pom.xml");
fileManager.write(pomFile, getPom(releaseId, dependencies));
return pomFile;
}

protected KieFileSystem createKieFileSystemWithKProject(KieServices ks, boolean isdefault) {
KieModuleModel kproj = ks.newKieModuleModel();

KieBaseModel kieBaseModel1 = kproj.newKieBaseModel("KBase1").setDefault(isdefault)
.setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
.setEventProcessingMode(EventProcessingOption.STREAM);

KieSessionModel ksession1 = kieBaseModel1.newKieSessionModel("KSession1").setDefault(isdefault)
.setType(KieSessionModel.KieSessionType.STATEFUL)
.setClockType(ClockTypeOption.get("realtime"));

KieFileSystem kfs = ks.newKieFileSystem();
kfs.writeKModuleXML(kproj.toXML());
return kfs;
}
}

0 comments on commit 4f2e3a5

Please sign in to comment.