/*
* Copyright 2011 Red Hat 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.persistence.session;
import static org.drools.persistence.util.PersistenceUtil.DROOLS_PERSISTENCE_UNIT_NAME;
import static org.drools.persistence.util.PersistenceUtil.createEnvironment;
import static org.junit.Assert.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import javax.naming.InitialContext;
import javax.transaction.UserTransaction;
import org.drools.Address;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.Person;
import org.drools.SessionConfiguration;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.command.CommandFactory;
import org.drools.command.impl.CommandBasedStatefulKnowledgeSession;
import org.drools.command.impl.FireAllRulesInterceptor;
import org.drools.command.impl.LoggingInterceptor;
import org.drools.definition.type.Position;
import org.drools.factmodel.traits.Traitable;
import org.drools.conf.EventProcessingOption;
import org.drools.io.ResourceFactory;
import org.drools.persistence.SingleSessionCommandService;
import org.drools.persistence.jpa.JPAKnowledgeService;
import org.drools.persistence.util.PersistenceUtil;
import org.drools.runtime.Environment;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.runtime.rule.FactHandle;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JpaPersistentStatefulSessionTest {
private static Logger logger = LoggerFactory.getLogger(JpaPersistentStatefulSessionTest.class);
private HashMap<String, Object> context;
private Environment env;
@Before
public void setUp() throws Exception {
context = PersistenceUtil.setupWithPoolingDataSource(DROOLS_PERSISTENCE_UNIT_NAME);
env = createEnvironment(context);
}
@After
public void tearDown() throws Exception {
PersistenceUtil.tearDown(context);
}
@Test
public void testFactHandleSerialization() {
String str = "";
str += "package org.drools.test\n";
str += "import java.util.concurrent.atomic.AtomicInteger\n";
str += "global java.util.List list\n";
str += "rule rule1\n";
str += "when\n";
str += " $i: AtomicInteger(intValue > 0)\n";
str += "then\n";
str += " list.add( $i );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
List<?> list = new ArrayList<Object>();
ksession.setGlobal( "list",
list );
AtomicInteger value = new AtomicInteger(4);
FactHandle atomicFH = ksession.insert( value );
ksession.fireAllRules();
assertEquals( 1,
list.size() );
value.addAndGet(1);
ksession.update(atomicFH, value);
ksession.fireAllRules();
assertEquals( 2,
list.size() );
String externalForm = atomicFH.toExternalForm();
ksession = JPAKnowledgeService.loadStatefulKnowledgeSession(ksession.getId(), kbase, null, env);
atomicFH = ksession.execute(CommandFactory.fromExternalFactHandleCommand(externalForm));
value.addAndGet(1);
ksession.update(atomicFH, value);
ksession.fireAllRules();
list = (List<?>) ksession.getGlobal("list");
assertEquals( 3,
list.size() );
}
@Test
public void testLocalTransactionPerStatement() {
String str = "";
str += "package org.drools.test\n";
str += "global java.util.List list\n";
str += "rule rule1\n";
str += "when\n";
str += " Integer(intValue > 0)\n";
str += "then\n";
str += " list.add( 1 );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
List<?> list = new ArrayList<Object>();
ksession.setGlobal( "list",
list );
ksession.insert( 1 );
ksession.insert( 2 );
ksession.insert( 3 );
ksession.fireAllRules();
assertEquals( 3,
list.size() );
}
@Test
public void testUserTransactions() throws Exception {
String str = "";
str += "package org.drools.test\n";
str += "global java.util.List list\n";
str += "rule rule1\n";
str += "when\n";
str += " $i : Integer(intValue > 0)\n";
str += "then\n";
str += " list.add( $i );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
UserTransaction ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
ut.commit();
List<?> list = new ArrayList<Object>();
// insert and commit
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.setGlobal( "list",
list );
ksession.insert( 1 );
ksession.insert( 2 );
ksession.fireAllRules();
ut.commit();
// insert and rollback
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.insert( 3 );
ut.rollback();
// check we rolled back the state changes from the 3rd insert
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.fireAllRules();
ut.commit();
assertEquals( 2,
list.size() );
// insert and commit
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.insert( 3 );
ksession.insert( 4 );
ut.commit();
// rollback again, this is testing that we can do consecutive rollbacks and commits without issue
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.insert( 5 );
ksession.insert( 6 );
ut.rollback();
ksession.fireAllRules();
assertEquals( 4,
list.size() );
// now load the ksession
ksession = JPAKnowledgeService.loadStatefulKnowledgeSession( ksession.getId(), kbase, null, env );
ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" );
ut.begin();
ksession.insert( 7 );
ksession.insert( 8 );
ut.commit();
ksession.fireAllRules();
assertEquals( 6,
list.size() );
}
@Test
public void testInterceptor() {
String str = "";
str += "package org.drools.test\n";
str += "global java.util.List list\n";
str += "rule rule1\n";
str += "when\n";
str += " Integer(intValue > 0)\n";
str += "then\n";
str += " list.add( 1 );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
SingleSessionCommandService sscs = (SingleSessionCommandService)
((CommandBasedStatefulKnowledgeSession) ksession).getCommandService();
sscs.addInterceptor(new LoggingInterceptor());
sscs.addInterceptor(new FireAllRulesInterceptor());
sscs.addInterceptor(new LoggingInterceptor());
List<?> list = new ArrayList<Object>();
ksession.setGlobal("list", list);
ksession.insert(1);
ksession.insert(2);
ksession.insert(3);
ksession.getWorkItemManager().completeWorkItem(0, null);
assertEquals( 3, list.size() );
}
@Test
public void testSetFocus() {
String str = "";
str += "package org.drools.test\n";
str += "global java.util.List list\n";
str += "rule rule1\n";
str += "agenda-group \"badfocus\"";
str += "when\n";
str += " Integer(intValue > 0)\n";
str += "then\n";
str += " list.add( 1 );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
List<?> list = new ArrayList<Object>();
ksession.setGlobal("list",
list);
ksession.insert( 1 );
ksession.insert( 2 );
ksession.insert(3);
ksession.getAgenda().getAgendaGroup("badfocus").setFocus();
ksession.fireAllRules();
assertEquals( 3,
list.size() );
}
@Test
public void testSharedReferences() {
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
Person x = new Person( "test" );
List test = new ArrayList();
List test2 = new ArrayList();
test.add( x );
test2.add( x );
assertSame( test.get( 0 ), test2.get( 0 ) );
ksession.insert( test );
ksession.insert( test2 );
ksession.fireAllRules();
StatefulKnowledgeSession ksession2 = JPAKnowledgeService.loadStatefulKnowledgeSession(ksession.getId(), kbase, null, env);
Iterator c = ksession2.getObjects().iterator();
List ref1 = (List) c.next();
List ref2 = (List) c.next();
assertSame( ref1.get( 0 ), ref2.get( 0 ) );
}
@Test
public void testMergeConfig() {
// JBRULES-3155
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
Properties properties = new Properties();
properties.put("drools.processInstanceManagerFactory", "com.example.CustomJPAProcessInstanceManagerFactory");
KnowledgeSessionConfiguration config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(properties);
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, config, env );
SessionConfiguration sessionConfig = (SessionConfiguration)ksession.getSessionConfiguration();
assertEquals("com.example.CustomJPAProcessInstanceManagerFactory", sessionConfig.getProcessInstanceManagerFactory());
}
@Test
public void testTraitsSerialization() throws Exception {
String drl = "package org.drools.persistence.kie.persistence.session\n" +
"\n" +
"import java.util.List\n" +
"\n" +
"import org.drools.persistence.session.JpaPersistentStatefulSessionTest.Door\n" +
"\n" +
"declare trait WoodenDoor\n" +
" from : String\n" +
" to : String\n" +
" wood : String\n" +
"end\n" +
"\n" +
"rule \"wooden door\"\n" +
" no-loop\n" +
" when\n" +
" $door : Door()\n" +
" then\n" +
" WoodenDoor woodenDoor = don( $door, WoodenDoor.class );\n" +
"end";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newByteArrayResource( drl.getBytes() ),
ResourceType.DRL );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
ksession.insert(new Door());
ksession.fireAllRules();
}
@Traitable
public static class Door implements Serializable {
private static final long serialVersionUID = 4173662501120948262L;
@Position(0)
private String fromLocation;
@Position(1)
private String toLocation;
public Door() {
this(null, null);
}
public Door(String fromLocation, String toLocation) {
this.fromLocation = fromLocation;
this.toLocation = toLocation;
}
public String getFromLocation() {
return fromLocation;
}
public void setFromLocation(String fromLocation) {
this.fromLocation = fromLocation;
}
public String getToLocation() {
return toLocation;
}
public void setToLocation(String toLocation) {
this.toLocation = toLocation;
}
}
@Test
public void testFromNodeWithModifiedCollection() {
// DROOLS-376
String str = "";
str += "package org.drools.test\n";
str += "import org.drools.Person\n";
str += "import org.drools.Address\n";
str += "rule rule1\n";
str += "when\n";
str += " $p: Person($list : addresses)\n";
str += " $a: Address(street == \"y\") from $list\n";
str += "then\n";
str += " $list.add( new Address(\"z\") );\n";
str += " $list.add( new Address(\"w\") );\n";
str += "end\n";
str += "\n";
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newByteArrayResource(str.getBytes()),
ResourceType.DRL);
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
if ( kbuilder.hasErrors() ) {
fail( kbuilder.getErrors().toString() );
}
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
ksession.insert(new Door());
ksession.fireAllRules();
}
}