/*
* Copyright 2010 JBoss Inc
*
* 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.drools.camel.component;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactoryService;
import org.drools.builder.JaxbConfiguration;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.KnowledgeBuilderFactoryService;
import org.drools.builder.ResourceType;
import org.drools.command.impl.GenericCommand;
import org.drools.command.runtime.BatchExecutionCommandImpl;
import org.drools.command.runtime.process.StartProcessCommand;
import org.drools.command.runtime.rule.FireAllRulesCommand;
import org.drools.command.runtime.rule.GetObjectCommand;
import org.drools.command.runtime.rule.InsertElementsCommand;
import org.drools.command.runtime.rule.InsertObjectCommand;
import org.drools.command.runtime.rule.QueryCommand;
import org.drools.common.DefaultFactHandle;
import org.drools.impl.KnowledgeBaseImpl;
import org.drools.io.ResourceFactory;
import org.drools.pipeline.camel.Person;
import org.drools.reteoo.ReteooRuleBase;
import org.drools.runtime.CommandExecutor;
import org.drools.runtime.ExecutionResults;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.QueryResultsRow;
import org.drools.runtime.rule.impl.FlatQueryResults;
import com.sun.tools.xjc.Language;
import com.sun.tools.xjc.Options;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class CamelEndpointWithJaxbTest extends DroolsCamelTestSupport {
private String handle;
private JAXBContext jaxbContext;
private RouteBuilder routeBuilder;
public void setUp() throws Exception {
super.setUp();
}
@Test
public void testSessionInsert() throws Exception {
BatchExecutionCommandImpl cmd = new BatchExecutionCommandImpl();
cmd.setLookup( "ksession1" );
cmd.getCommands().add( new InsertObjectCommand( new Person( "lucaz",
25 ),
"person1" ) );
cmd.getCommands().add( new InsertObjectCommand( new Person( "hadrian",
25 ),
"person2" ) );
cmd.getCommands().add( new InsertObjectCommand( new Person( "baunax",
21 ),
"person3" ) );
cmd.getCommands().add( new FireAllRulesCommand() );
StringWriter xmlReq = new StringWriter();
Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setProperty( "jaxb.formatted.output",
true );
marshaller.marshal( cmd,
xmlReq );
System.out.println( xmlReq.toString() );
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
xmlReq.toString() );
assertNotNull( xmlResp );
System.out.println( new String( xmlResp ) );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
assertEquals( 3,
resp.getIdentifiers().size() );
assertNotNull( resp.getValue( "person1" ) );
assertNotNull( resp.getValue( "person2" ) );
assertNotNull( resp.getValue( "person3" ) );
assertNotNull( resp.getFactHandle( "person1" ) );
assertNotNull( resp.getFactHandle( "person2" ) );
assertNotNull( resp.getFactHandle( "person3" ) );
}
@Test
public void testSessionGetObject() throws Exception {
BatchExecutionCommandImpl cmd = new BatchExecutionCommandImpl();
cmd.setLookup( "ksession1" );
cmd.getCommands().add( new GetObjectCommand( new DefaultFactHandle( handle ),
"hadrian" ) );
StringWriter xmlReq = new StringWriter();
Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setProperty( "jaxb.formatted.output",
true );
marshaller.marshal( cmd,
xmlReq );
System.out.println( xmlReq.toString() );
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
xmlReq.toString() );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
assertEquals( 1,
resp.getIdentifiers().size() );
assertNotNull( resp.getValue( "hadrian" ) );
}
@Test
public void testSessionModify() throws Exception {
String cmd = "";
cmd += "<batch-execution lookup='ksession1'>\n";
cmd += " <modify fact-handle='" + handle + "'>\n";
cmd += " <setters>";
cmd += " <item accessor='name' value='salaboy' />\n";
cmd += " </setters>\n";
cmd += " </modify>\n";
cmd += "</batch-execution>\n";
String outXml = new String( (byte[]) template.requestBody( "direct:test-with-session",
cmd ) );
String expectedXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
expectedXml += "<execution-results xmlns:ns2=\"http://drools.org/model\">\n";
expectedXml += " <results/>\n";
expectedXml += " <facts/>\n";
expectedXml += "</execution-results>\n";
assertXMLEqual( expectedXml,
outXml );
cmd = "<batch-execution lookup='ksession1'>\n";
cmd += " <get-object out-identifier='rider' fact-handle='" + handle + "'/>\n";
cmd += "</batch-execution>\n";
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
cmd.toString() );
assertNotNull( xmlResp );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
Person person = (Person) resp.getValue( "rider" );
assertEquals( "salaboy",
person.getName() );
}
@Test
public void testSessionRetractObject() throws Exception {
String cmd = "";
cmd += "<batch-execution lookup='ksession1'>\n";
cmd += " <retract fact-handle='" + handle + "' />\n";
cmd += "</batch-execution>";
String outXml = new String( (byte[]) template.requestBody( "direct:test-with-session",
cmd ) );
System.out.println( outXml );
assertNotNull( outXml );
}
@Test
public void testInsertElements() throws Exception {
BatchExecutionCommandImpl cmd = new BatchExecutionCommandImpl();
cmd.setLookup( "ksession1" );
InsertElementsCommand elems = new InsertElementsCommand( "elems" );
elems.getObjects().add( new Person( "lucaz",
25 ) );
elems.getObjects().add( new Person( "hadrian",
25 ) );
elems.getObjects().add( new Person( "baunax",
21 ) );
elems.getObjects().add( "xxx" );
cmd.getCommands().add( elems );
cmd.getCommands().add( new FireAllRulesCommand() );
StringWriter xmlReq = new StringWriter();
Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setProperty( "jaxb.formatted.output",
true );
marshaller.marshal( cmd,
xmlReq );
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
xmlReq.toString() );
assertNotNull( xmlResp );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
assertEquals( 1,
resp.getIdentifiers().size() );
List<Person> list = (List<Person>) resp.getValue( "elems" );
assertEquals( "lucaz",
list.get( 0 ).getName() );
assertEquals( "hadrian",
list.get( 1 ).getName() );
assertEquals( "baunax",
list.get( 2 ).getName() );
}
@Test
public void testQuery() throws Exception {
BatchExecutionCommandImpl cmd = new BatchExecutionCommandImpl();
cmd.setLookup( "ksession1" );
cmd.getCommands().add( new InsertObjectCommand( new Person( "lucaz" ) ) );
cmd.getCommands().add( new InsertObjectCommand( new Person( "hadrian" ) ) );
cmd.getCommands().add( new InsertObjectCommand( new Person( "baunax",
43 ) ) );
cmd.getCommands().add( new InsertObjectCommand( new Person( "baunax",
21 ) ) );
cmd.getCommands().add( new QueryCommand( "persons",
"persons",
null ) );
cmd.getCommands().add( new QueryCommand( "person",
"personWithName",
new String[]{"baunax"} ) );
StringWriter xmlReq = new StringWriter();
Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setProperty( "jaxb.formatted.output",
true );
marshaller.marshal( cmd,
xmlReq );
System.out.println( xmlReq.toString() );
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
xmlReq.toString() );
assertNotNull( xmlResp );
System.out.println( new String( xmlResp ) );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
FlatQueryResults personQuery = (FlatQueryResults) resp.getValue( "person" );
assertEquals( 2,
personQuery.size() );
FlatQueryResults personsQuery = (FlatQueryResults) resp.getValue( "persons" );
assertEquals( 5,
personsQuery.size() );
Iterator<QueryResultsRow> iterator = personQuery.iterator();
QueryResultsRow row = iterator.next();
Person person = (Person) row.get( "$p" );
assertEquals( "baunax",
person.getName() );
}
@Test
public void testProcess() throws Exception {
BatchExecutionCommandImpl cmd = new BatchExecutionCommandImpl();
cmd.setLookup( "ksession1" );
StartProcessCommand start = new StartProcessCommand( "org.drools.actions" , "process-instance-id" );
start.putParameter( "person",
new Person( "lucaz",
25 ) );
start.putParameter( "person2",
new Person( "hadrian",
25 ) );
start.putParameter( "person3",
new Person( "baunax",
21 ) );
cmd.getCommands().add( start );
StringWriter xmlReq = new StringWriter();
Marshaller marshaller = getJaxbContext().createMarshaller();
marshaller.setProperty( "jaxb.formatted.output",
true );
marshaller.marshal( cmd,
xmlReq );
System.out.println( xmlReq.toString() );
byte[] xmlResp = (byte[]) template.requestBody( "direct:test-with-session",
xmlReq.toString() );
assertNotNull( xmlResp );
System.out.println( new String( xmlResp ) );
ExecutionResults resp = (ExecutionResults) getJaxbContext().createUnmarshaller().unmarshal( new ByteArrayInputStream( xmlResp ) );
assertNotNull( resp );
assertNotNull( resp.getValue( "process-instance-id" ) );
}
@Test
public void testProcessInstanceSignalEvent() throws Exception {
String processId = "org.drools.event";
String cmd = "";
cmd += "<batch-execution lookup='ksession1'>\n";
cmd += " <start-process processId='" + processId + "'>\n";
cmd += " </start-process>\n";
cmd += "</batch-execution>\n";
System.out.println( cmd );
String outXml = new String( (byte[]) template.requestBody( "direct:test-with-session",
cmd ) );
assertNotNull( outXml );
int processInstanceId = 1;
cmd = "";
cmd += "<batch-execution lookup='ksession1'>\n";
cmd += " <signal-event process-instance-id= '" + processInstanceId + "' event-type='MyEvent'>";
cmd += " <string>MyValue</string>";
cmd += " </signal-event>";
cmd += "</batch-execution>\n";
outXml = new String( (byte[]) template.requestBody( "direct:test-with-session",
cmd ) );
System.out.println( outXml );
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
routeBuilder = new RouteBuilder() {
public void configure() throws Exception {
JaxbDataFormat def = new JaxbDataFormat();
def.setPrettyPrint(true);
// TODO does not work: def.setContextPath( "org.drools.camel.testdomain:org.drools.pipeline.camel" );
def.setContextPath("org.drools.pipeline.camel");
from("direct:test-with-session").policy(new DroolsPolicy()).unmarshal(def).to("drools:node/ksession1").marshal(def);
from("direct:test-no-session").policy(new DroolsPolicy()).unmarshal(def).to("drools:node").marshal(def);
}
};
return routeBuilder;
}
public JAXBContext getJaxbContext() {
if ( this.jaxbContext == null ) {
JaxbDataFormat def = new JaxbDataFormat();
def.setPrettyPrint( true );
// TODO does not work: def.setContextPath( "org.drools.camel.testdomain:org.drools.pipeline.camel" );
def.setContextPath( "org.drools.pipeline.camel" );
// create a jaxbContext for the test to use outside of Camel.
StatefulKnowledgeSession ksession1 = (StatefulKnowledgeSession) node.get( "ksession1",
CommandExecutor.class );
KnowledgeBase kbase = ksession1.getKnowledgeBase();
ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader( ((ReteooRuleBase) ((KnowledgeBaseImpl) kbase).getRuleBase()).getRootClassLoader() );
def = DroolsPolicy.augmentJaxbDataFormatDefinition( def );
org.apache.camel.converter.jaxb.JaxbDataFormat jaxbDataformat = (org.apache.camel.converter.jaxb.JaxbDataFormat) def.getDataFormat( this.context.getRoutes().get( 0 ).getRouteContext() );
jaxbDataformat.setCamelContext(routeBuilder.getContext());
try {
jaxbDataformat.start();
} catch (Exception e) {
throw new IllegalStateException(e);
}
jaxbContext = jaxbDataformat.getContext();
} finally {
Thread.currentThread().setContextClassLoader( originalCl );
}
}
return jaxbContext;
}
@Override
protected void configureDroolsContext(javax.naming.Context jndiContext) {
Person me = new Person();
me.setName( "Hadrian" );
String rule = "";
rule += "package org.drools.pipeline.camel \n";
rule += "import org.drools.pipeline.camel.Person \n";
rule += "global java.util.List list \n";
rule += "query persons \n";
rule += " $p : Person(name != null) \n";
rule += "end \n";
rule += "query personWithName(String param)\n";
rule += " $p : Person(name == param) \n";
rule += "end \n";
rule += "rule rule1 \n";
rule += " when \n";
rule += " $p : Person() \n";
rule += " \n";
rule += " then \n";
rule += " System.out.println(\"executed\"); \n";
rule += "end\n";
StatefulKnowledgeSession ksession = registerKnowledgeRuntime( "ksession1",
rule );
InsertObjectCommand cmd = new InsertObjectCommand( me );
cmd.setOutIdentifier( "camel-rider" );
cmd.setReturnObject( false );
BatchExecutionCommandImpl script = new BatchExecutionCommandImpl( Arrays.asList( new GenericCommand< ? >[]{cmd} ) );
ExecutionResults results = ksession.execute( script );
handle = ((FactHandle) results.getFactHandle( "camel-rider" )).toExternalForm();
}
@Override
protected StatefulKnowledgeSession registerKnowledgeRuntime(String identifier,
String rule) {
KnowledgeBuilder kbuilder = node.get( KnowledgeBuilderFactoryService.class ).newKnowledgeBuilder();
Options xjcOpts = new Options();
xjcOpts.setSchemaLanguage( Language.XMLSCHEMA );
JaxbConfiguration jaxbConfiguration = KnowledgeBuilderFactory.newJaxbConfiguration( xjcOpts,
"xsd" );
kbuilder.add( ResourceFactory.newClassPathResource( "person.xsd",
getClass() ),
ResourceType.XSD,
jaxbConfiguration );
if ( rule != null && rule.length() > 0 ) {
kbuilder.add( ResourceFactory.newByteArrayResource( rule.getBytes() ),
ResourceType.DRL );
if ( kbuilder.hasErrors() ) {
LOG.info( "Errors while adding rule. ",
kbuilder.getErrors() );
}
}
String process1 = "";
process1 += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
process1 += "<process xmlns=\"http://drools.org/drools-5.0/process\"\n";
process1 += " xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
process1 += " xs:schemaLocation=\"http://drools.org/drools-5.0/process drools-processes-5.0.xsd\"\n";
process1 += " type=\"RuleFlow\" name=\"flow\" id=\"org.drools.actions\" package-name=\"org.drools\" version=\"1\" >\n";
process1 += "\n";
process1 += " <header>\n";
process1 += " <imports>\n";
process1 += " <import name=\"org.drools.camel.testdomain.Person\" />\n";
process1 += " </imports>\n";
process1 += " <globals>\n";
process1 += " <global identifier=\"list\" type=\"java.util.List\" />\n";
process1 += " </globals>\n";
process1 += " <variables>\n";
process1 += " <variable name=\"person\" >\n";
process1 += " <type name=\"org.drools.process.core.datatype.impl.type.ObjectDataType\" className=\"Person\" />\n";
process1 += " </variable>\n";
process1 += " </variables>\n";
process1 += " </header>\n";
process1 += "\n";
process1 += " <nodes>\n";
process1 += " <start id=\"1\" name=\"Start\" />\n";
process1 += " <actionNode id=\"2\" name=\"MyActionNode\" >\n";
process1 += " <action type=\"expression\" dialect=\"mvel\" >System.out.println(\"Triggered\");\n";
// process1 += "list.add(person.name);\n";
process1 += "</action>\n";
process1 += " </actionNode>\n";
process1 += " <end id=\"3\" name=\"End\" />\n";
process1 += " </nodes>\n";
process1 += "\n";
process1 += " <connections>\n";
process1 += " <connection from=\"1\" to=\"2\" />\n";
process1 += " <connection from=\"2\" to=\"3\" />\n";
process1 += " </connections>\n" + "\n";
process1 += "</process>";
kbuilder.add( ResourceFactory.newByteArrayResource( process1.getBytes() ),
ResourceType.DRF );
if ( kbuilder.hasErrors() ) {
System.out.println( "Errors while adding process rule 1. " + kbuilder.getErrors() );
}
assertFalse( kbuilder.hasErrors() );
String process2 = "";
process2 += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
process2 += "<process xmlns=\"http://drools.org/drools-5.0/process\"\n";
process2 += " xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
process2 += " xs:schemaLocation=\"http://drools.org/drools-5.0/process drools-processes-5.0.xsd\"\n";
process2 += " type=\"RuleFlow\" name=\"flow\" id=\"org.drools.event\" package-name=\"org.drools\" version=\"1\" >\n";
process2 += "\n";
process2 += " <header>\n";
process2 += " <variables>\n";
process2 += " <variable name=\"MyVar\" >\n";
process2 += " <type name=\"org.drools.process.core.datatype.impl.type.StringDataType\" />\n";
process2 += " <value>SomeText</value>\n";
process2 += " </variable>\n";
process2 += " </variables>\n";
process2 += " </header>\n";
process2 += "\n";
process2 += " <nodes>\n";
process2 += " <start id=\"1\" name=\"Start\" />\n";
process2 += " <eventNode id=\"2\" name=\"Event\" variableName=\"MyVar\" >\n";
process2 += " <eventFilters>\n";
process2 += " <eventFilter type=\"eventType\" eventType=\"MyEvent\" />\n";
process2 += " </eventFilters>\n";
process2 += " </eventNode>\n";
process2 += " <join id=\"3\" name=\"Join\" type=\"1\" />\n";
process2 += " <end id=\"4\" name=\"End\" />\n";
process2 += " </nodes>\n";
process2 += "\n";
process2 += " <connections>\n";
process2 += " <connection from=\"1\" to=\"3\" />\n";
process2 += " <connection from=\"2\" to=\"3\" />\n";
process2 += " <connection from=\"3\" to=\"4\" />\n";
process2 += " </connections>\n";
process2 += "\n";
process2 += "</process>";
kbuilder.add( ResourceFactory.newByteArrayResource( process2.getBytes() ),
ResourceType.DRF );
if ( kbuilder.hasErrors() ) {
LOG.info( "Errors while adding process rule 2. ",
kbuilder.getErrors() );
}
assertFalse( kbuilder.hasErrors() );
KnowledgeBase kbase = node.get( KnowledgeBaseFactoryService.class ).newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatefulKnowledgeSession session = kbase.newStatefulKnowledgeSession();
node.set( identifier,
session );
return session;
}
}