[jboss-svn-commits] JBL Code SVN: r31039 - in labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src: test/java/org/jboss/internal/soa/esb/services/rules and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Jan 12 15:53:14 EST 2010
Author: kevin.conner at jboss.com
Date: 2010-01-12 15:53:14 -0500 (Tue, 12 Jan 2010)
New Revision: 31039
Added:
labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleBaseState.java
Modified:
labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleService.java
labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/test/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleServiceUnitTest.java
Log:
Introduce a rules execution state and cache sessions: JBESB-3106
Added: labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleBaseState.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleBaseState.java (rev 0)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleBaseState.java 2010-01-12 20:53:14 UTC (rev 31039)
@@ -0,0 +1,390 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.internal.soa.esb.services.rules;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.log4j.Logger;
+import org.drools.RuleBase;
+import org.drools.SessionConfiguration;
+import org.drools.StatefulSession;
+import org.drools.StatelessSession;
+import org.drools.WorkingMemoryEntryPoint;
+import org.drools.common.EventFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.impl.EnvironmentFactory;
+import org.drools.runtime.Environment;
+import org.drools.spi.GlobalResolver;
+import org.jboss.internal.soa.esb.services.rules.util.RulesContext;
+import org.jboss.soa.esb.message.Message;
+import org.jboss.soa.esb.services.rules.StatefulRuleInfo;
+
+/**
+ * Drools rule base state used to execute and cleanup rule bases. Some parts have been extracted from the DroolsRuleService.
+ *
+ * @author <a href='mailto:Kevin.Conner at jboss.com'>Kevin Conner</a>
+ * @author jdelong at redhat.com
+ * @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
+ */
+class DroolsRuleBaseState
+{
+ /**
+ * The logger for this state.
+ */
+ private static Logger LOGGER = Logger.getLogger(DroolsRuleBaseState.class);
+
+ /**
+ * The rule base associated with this state.
+ */
+ private final RuleBase ruleBase ;
+ /**
+ * The disposed flag. If set, stateful sessions are automatically disposed.
+ */
+ private transient boolean disposed ;
+
+ /**
+ * The stateful session.
+ */
+ private StatefulSession statefulSession ;
+ /**
+ * Stateful session configuration.
+ */
+ private SessionConfiguration statefulSessionConfiguration ;
+ /**
+ * Stateful environment
+ */
+ private Environment statefulEnvironment ;
+ /**
+ * The stateful session lock.
+ */
+ private final Lock statefulSessionLock = new ReentrantLock() ;
+ /**
+ * The stateful session count lock.
+ */
+ private final Lock statefulSessionCountLock = new ReentrantLock() ;
+ /**
+ * The number of sessions queued for the stateful session.
+ */
+ private int statefulSessionCount ;
+ /**
+ * The stateless sessions.
+ */
+ private final ConcurrentLinkedQueue<StatelessSession> statelessSessions = new ConcurrentLinkedQueue<StatelessSession>() ;
+
+ /**
+ * Construct the rule base state.
+ * @param ruleBase The associated rule base.
+ */
+ DroolsRuleBaseState(final RuleBase ruleBase)
+ {
+ this.ruleBase = ruleBase ;
+ }
+
+ /**
+ * Get the rule base associated with this state.
+ * @return The rule base.
+ */
+ RuleBase getRuleBase()
+ {
+ return ruleBase ;
+ }
+
+ /**
+ * Execute rules using using the Stateless API
+ *
+ * @param message -
+ * Message that is updated with the results.
+ * @param objectList -
+ * a list with additional objects (typically pulled from the message)
+ * to be inserted into working memory
+ * @param globals -
+ * Map of globals variables that should be set in the working memory
+ *
+ * @return Message -
+ * with updated objects.
+ */
+ Message executeStatelessRules(
+ final Message message,
+ final Map<String,Object> globals,
+ final List<Object> objectList)
+ {
+ final StatelessSession head = statelessSessions.poll() ;
+ final StatelessSession statelessSession = (head != null ? head : ruleBase.newStatelessSession()) ;
+ RulesContext.clearContext() ;
+ try
+ {
+ final List<Object> facts = new ArrayList<Object>() ;
+ facts.add(message) ;
+ if (objectList != null)
+ {
+ facts.addAll(objectList) ;
+ }
+ statelessSession.setGlobalResolver(new StatelessGlobalResolver(globals)) ;
+ try
+ {
+ statelessSession.execute(facts);
+ }
+ finally
+ {
+ statelessSession.setGlobalResolver(null) ;
+ }
+ }
+ finally
+ {
+ RulesContext.clearContext() ;
+ statelessSessions.add(statelessSession) ;
+ }
+ return message;
+ }
+
+ /**
+ * Execute rules using using the Stateful API
+ *
+ * @param dispose -
+ * if true the working memory will be dereferenced.
+ * @param message -
+ * Message that is updated with the results.
+ * @param globals -
+ * Map of globals variables that should be set in the working memory
+ * @param entryPointMap -
+ * a map with additional objects to be inserted into working memory or
+ * into the named WorkingMemoryEntryPoint. Any objects included in the
+ * {@link #DEFAULT_ENTRY_POINT} name will be inserted into the normal
+ * working memory. The rest will lookup the entry point working memory
+ * and insert the objects into the those working memories.
+ * @return Message -
+ * a possibly updated Message object. The message object is available
+ * to Rules and my be updated by them.
+ * @throws RuleServiceException
+ */
+ Message executeStatefulRules(
+ final StatefulRuleInfo ruleInfo,
+ final Message message) throws RuleServiceException
+ {
+ final boolean debugEnabled = LOGGER.isDebugEnabled() ;
+
+ RulesContext.clearContext() ;
+ statefulSessionCountLock.lock() ;
+ statefulSessionCount++ ;
+ statefulSessionCountLock.unlock() ;
+
+ try
+ {
+ statefulSessionLock.lock() ;
+ try
+ {
+ if ((statefulSession != null) && !ruleInfo.continueState())
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Disposing current stateful session, no continue set") ;
+ }
+ final StatefulSession disposedStatefulSession = statefulSession ;
+ statefulSession = null ;
+ disposedStatefulSession.dispose() ;
+ }
+
+ if (statefulSession == null)
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Creating stateful session") ;
+ }
+ if (statefulSessionConfiguration == null)
+ {
+ statefulSessionConfiguration = new SessionConfiguration() ;
+ }
+ if (statefulEnvironment == null)
+ {
+ statefulEnvironment = EnvironmentFactory.newEnvironment() ;
+ }
+ statefulSession = ruleBase.newStatefulSession(statefulSessionConfiguration, statefulEnvironment) ;
+ }
+
+ try
+ {
+ final Map<String, Object> globals = ruleInfo.getGlobals() ;
+ if (globals != null)
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Inserting globals") ;
+ }
+ final Set<Entry<String, Object>> entrySet = globals.entrySet() ;
+ for(Entry<String, Object> entry : entrySet)
+ {
+ statefulSession.setGlobal( entry.getKey(), entry.getValue() );
+ }
+ }
+
+ // Always insert the ESB Message object.
+ InternalFactHandle handle = (InternalFactHandle) statefulSession.insert(message);
+ if (debugEnabled && handle.isEvent())
+ {
+ EventFactHandle ef = (EventFactHandle) handle;
+ LOGGER.debug("Event :" + ef.getObject().getClass().getName() + ", startTimeStamp: " + ef.getStartTimestamp());
+ }
+
+ // Always insert the Default facts
+ final List<Object> defaultFacts = ruleInfo.getDefaultFacts();
+ if (defaultFacts != null)
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Inserting default facts") ;
+ }
+ for(Object object : defaultFacts)
+ {
+ statefulSession.insert(object);
+ }
+ }
+
+ // Insert any object that that did not specify an entry-point into the main working memory.
+ if (ruleInfo.getFacts() != null)
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Inserting facts") ;
+ }
+ for(Entry<String, List<Object>> entry : ruleInfo.getFacts().entrySet())
+ {
+ String entryPointName = entry.getKey();
+ // Insert object that have explicitly specified an entry-point.
+ WorkingMemoryEntryPoint wmep = statefulSession.getWorkingMemoryEntryPoint(entryPointName);
+ if (wmep == null)
+ {
+ throw new RuleServiceException("The entry-point '" + entryPointName + "' was not found in the current stateful session. Please double check your rules source");
+ }
+ for(Object object : entry.getValue())
+ {
+ wmep.insert(object);
+ }
+ }
+ }
+
+ if (debugEnabled)
+ {
+ LOGGER.debug("Firing rules") ;
+ }
+ // Fire rules.
+ statefulSession.fireAllRules();
+ }
+ finally
+ {
+ if ( ruleInfo.dispose() )
+ {
+ if (debugEnabled)
+ {
+ LOGGER.debug("Disposing current stateful session, dispose set") ;
+ }
+ final StatefulSession disposedStatefulSession = statefulSession ;
+ statefulSession = null ;
+ disposedStatefulSession.dispose() ;
+ }
+ }
+ }
+ finally
+ {
+ statefulSessionLock.unlock() ;
+ }
+ }
+ finally
+ {
+ RulesContext.clearContext() ;
+ statefulSessionCountLock.lock() ;
+ statefulSessionCount-- ;
+ if (disposed && (statefulSessionCount == 0))
+ {
+ dispose() ;
+ }
+ statefulSessionCountLock.unlock() ;
+ }
+ return message ;
+ }
+
+ void dispose()
+ {
+ statefulSessionCountLock.lock() ;
+ try
+ {
+ disposed = true ;
+ if ((statefulSessionCount == 0) && (statefulSession != null))
+ {
+ LOGGER.debug("Disposing stateful session") ;
+ final StatefulSession disposedStatefulSession = statefulSession ;
+ statefulSession = null ;
+ disposedStatefulSession.dispose() ;
+ }
+ statelessSessions.clear() ;
+ }
+ finally
+ {
+ statefulSessionCountLock.unlock() ;
+ }
+ }
+
+ /**
+ * Global resolver for stateless execution
+ * @author <a href='kevin.conner at jboss.com'>Kevin Conner</a>
+ */
+ public class StatelessGlobalResolver implements GlobalResolver
+ {
+ /**
+ * The map of globals.
+ */
+ private final Map<String, Object> globals ;
+
+ public StatelessGlobalResolver(Map<String, Object> globals)
+ {
+ this.globals = new HashMap<String, Object>(globals) ;
+ }
+
+ /**
+ * Resolve the global identifier.
+ * @param identifier The identifier.
+ * @return the value or null.
+ */
+ public Object resolveGlobal(final String identifier)
+ {
+ return globals.get(identifier) ;
+ }
+
+ /**
+ * Set the global identifier.
+ * @param identifier The identifier.
+ * @parma value the value.
+ */
+ public void setGlobal(final String identifier, final Object value)
+ {
+ globals.put(identifier, value) ;
+ }
+ }
+}
Property changes on: labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleBaseState.java
___________________________________________________________________
Name: svn:keywords
+ Rev Date
Name: svn:eol-style
+ native
Modified: labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleService.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleService.java 2010-01-12 20:40:46 UTC (rev 31038)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/main/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleService.java 2010-01-12 20:53:14 UTC (rev 31039)
@@ -22,31 +22,22 @@
package org.jboss.internal.soa.esb.services.rules;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.drools.RuleBase;
import org.drools.StatefulSession;
-import org.drools.StatelessSession;
-import org.drools.WorkingMemoryEntryPoint;
import org.drools.agent.RuleAgent;
-import org.drools.common.EventFactHandle;
-import org.drools.common.InternalFactHandle;
import org.drools.compiler.DroolsParserException;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
-import org.jboss.internal.soa.esb.services.rules.util.RulesContext;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.lifecycle.LifecyclePriorities;
import org.jboss.soa.esb.lifecycle.LifecycleResource;
import org.jboss.soa.esb.lifecycle.LifecycleResourceException;
import org.jboss.soa.esb.lifecycle.LifecycleResourceFactory;
-import org.jboss.soa.esb.lifecycle.LifecycleResourceManager;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.services.rules.RuleInfo;
import org.jboss.soa.esb.services.rules.RuleService;
@@ -65,9 +56,9 @@
private static Logger log = Logger.getLogger(DroolsRuleService.class);
/**
- * The lifecycle resource factory for RuleBases.
+ * The lifecycle resource state factory for RuleBases.
*/
- private static final LifecycleResourceFactory<Map<String, RuleBase>> lifecycleRuleBaseFactory = new LifecycleRuleBaseFactory();
+ private static final LifecycleResourceFactory<Map<String, DroolsRuleBaseState>> lifecycleRuleBaseStateFactory = new LifecycleRuleBaseStateFactory();
/**
* The lifecycle resource factory for RuleAgents.
@@ -77,13 +68,13 @@
/**
* The lifecycle resource factory rule sets.
*/
- private static final LifecycleResourceFactory<Map<String, String>> lifecycleRuleSetFactory = new LifecycleRuleSetFactory();
+ private static final LifecycleResourceFactory<ConcurrentHashMap<String, String>> lifecycleRuleSetFactory = new LifecycleRuleSetFactory();
/**
- * The lifecycle resource rule bases.
+ * The lifecycle resource rule base states.
*/
- private static final LifecycleResource<Map<String, RuleBase>> lifecycleRuleBases = new LifecycleResource<Map<String, RuleBase>>(
- lifecycleRuleBaseFactory, LifecyclePriorities.RULE_BASE_PRIORITY);
+ private static final LifecycleResource<Map<String, DroolsRuleBaseState>> lifecycleRuleBaseStates = new LifecycleResource<Map<String, DroolsRuleBaseState>>(
+ lifecycleRuleBaseStateFactory, LifecyclePriorities.RULE_BASE_PRIORITY);
/**
* RuleAgents cache
@@ -94,7 +85,7 @@
/**
* The lifecycle resource for ruleset.
*/
- private static final LifecycleResource<Map<String, String>> lifecycleRuleSets = new LifecycleResource<Map<String, String>>(
+ private static final LifecycleResource<ConcurrentHashMap<String, String>> lifecycleRuleSets = new LifecycleResource<ConcurrentHashMap<String, String>>(
lifecycleRuleSetFactory, LifecyclePriorities.RULE_BASE_PRIORITY);
/**
@@ -131,8 +122,8 @@
{
AssertArgument.isNotNullAndNotEmpty( ruleSet, "ruleSet" );
- RuleBase ruleBase = getRuleBaseForFileBasedRules(ruleSet, dsl, ruleReload);
- return executeStatelessRules(ruleBase, message, globals, objectList);
+ DroolsRuleBaseState ruleBaseState = getRuleBaseStateForFileBasedRules(ruleSet, dsl, ruleReload);
+ return ruleBaseState.executeStatelessRules(message, globals, objectList);
}
/**
@@ -145,8 +136,8 @@
public Message executeStatelessRules(final RuleInfo ruleInfo, final Message message) throws RuleServiceException
{
AssertArgument.isNotNull(ruleInfo, "ruleInfo" );
- final RuleBase ruleBase = getRuleBaseForFileBasedRules(ruleInfo.getRuleSource(), ruleInfo.getDslSource(), ruleInfo.getReload());
- return executeStatelessRules(ruleBase, message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForFileBasedRules(ruleInfo.getRuleSource(), ruleInfo.getDslSource(), ruleInfo.getReload());
+ return ruleBaseState.executeStatelessRules(message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
}
@@ -178,15 +169,15 @@
{
AssertArgument.isNotNullAndNotEmpty( decisionTable, "decisionTable" );
- RuleBase ruleBase = getRuleBaseForDecisionTable( decisionTable, ruleReload );
- return executeStatelessRules( ruleBase, message, globals, objectList );
+ DroolsRuleBaseState ruleBaseState = getRuleBaseStateForDecisionTable( decisionTable, ruleReload );
+ return ruleBaseState.executeStatelessRules( message, globals, objectList );
}
public Message executeStatelessRulesFromDecisionTable(final RuleInfo ruleInfo, final Message message) throws RuleServiceException
{
AssertArgument.isNotNull(ruleInfo, "ruleInfo" );
- RuleBase ruleBase = getRuleBaseForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
- return executeStatelessRules(ruleBase, message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
+ DroolsRuleBaseState ruleBaseState = getRuleBaseStateForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
+ return ruleBaseState.executeStatelessRules(message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
}
@@ -217,8 +208,8 @@
try
{
- final RuleBase ruleBase = getRuleBaseForRuleAgent( ruleAgentProperties ) ;
- return executeStatelessRules(ruleBase, message, globals, objectList);
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForRuleAgent( ruleAgentProperties ) ;
+ return ruleBaseState.executeStatelessRules(message, globals, objectList);
}
catch ( final IOException e)
{
@@ -235,8 +226,8 @@
AssertArgument.isNotNull(ruleInfo, "ruleInfo" );
try
{
- final RuleBase ruleBase = getRuleBaseForRuleAgent(ruleInfo.getRuleSource());
- return executeStatelessRules(ruleBase, message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForRuleAgent(ruleInfo.getRuleSource());
+ return ruleBaseState.executeStatelessRules(message, ruleInfo.getGlobals(), ruleInfo.getDefaultFacts());
}
catch ( final IOException e)
{
@@ -288,8 +279,8 @@
builder.defaultFacts(objectList);
StatefulRuleInfoImpl ruleInfo = new StatefulRuleInfoImpl(builder.build(), false, false);
- RuleBase ruleBase = getRuleBaseForFileBasedRules( ruleInfo.getRuleSource(), ruleInfo.getDslSource(), ruleInfo.getReload());
- return executeStatefulRules(ruleBase, ruleInfo, message);
+ DroolsRuleBaseState ruleBaseState = getRuleBaseStateForFileBasedRules( ruleInfo.getRuleSource(), ruleInfo.getDslSource(), ruleInfo.getReload());
+ return ruleBaseState.executeStatefulRules(ruleInfo, message);
}
/**
@@ -305,8 +296,8 @@
public Message executeStatefulRules(final StatefulRuleInfo info, final Message msg) throws RuleServiceException
{
AssertArgument.isNotNull(info, "ruleInfo" );
- final RuleBase ruleBase = getRuleBaseForFileBasedRules(info.getRuleSource(), info.getDslSource(), info.getReload());
- return executeStatefulRules(ruleBase, info, msg);
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForFileBasedRules(info.getRuleSource(), info.getDslSource(), info.getReload());
+ return ruleBaseState.executeStatefulRules(info, msg);
}
/**
@@ -343,9 +334,9 @@
builder.defaultFacts(objectList);
StatefulRuleInfoImpl ruleInfo = new StatefulRuleInfoImpl(builder.build(), false, false);
- final RuleBase ruleBase = getRuleBaseForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
- return executeStatefulRules(ruleBase, ruleInfo, message);
+ return ruleBaseState.executeStatefulRules(ruleInfo, message);
}
/**
@@ -361,8 +352,8 @@
@Deprecated
public Message executeStatefulRulesFromDecisionTable(StatefulRuleInfo ruleInfo, Message msg) throws RuleServiceException
{
- final RuleBase ruleBase = getRuleBaseForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
- return executeStatefulRules(ruleBase, ruleInfo, msg);
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForDecisionTable(ruleInfo.getRuleSource(), ruleInfo.getReload());
+ return ruleBaseState.executeStatefulRules(ruleInfo, msg);
}
/**
@@ -395,9 +386,9 @@
builder.defaultFacts(objectList);
StatefulRuleInfoImpl ruleInfo = new StatefulRuleInfoImpl(builder.build(), false, false);
- final RuleBase ruleBase = getRuleBaseForRuleAgent(ruleInfo.getRuleSource()) ;
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForRuleAgent(ruleInfo.getRuleSource()) ;
- return executeStatefulRules(ruleBase, ruleInfo, message);
+ return ruleBaseState.executeStatefulRules(ruleInfo, message);
}
catch (IOException e)
{
@@ -417,9 +408,9 @@
{
try
{
- final RuleBase ruleBase = getRuleBaseForRuleAgent(ruleInfo.getRuleSource()) ;
+ final DroolsRuleBaseState ruleBaseState = getRuleBaseStateForRuleAgent(ruleInfo.getRuleSource()) ;
- return executeStatefulRules(ruleBase, ruleInfo, msg);
+ return ruleBaseState.executeStatefulRules(ruleInfo, msg);
}
catch (IOException e)
{
@@ -465,15 +456,15 @@
try
{
- final Map<String, RuleBase> ruleBases = lifecycleRuleBases.getLifecycleResource();
+ final Map<String, DroolsRuleBaseState> ruleBaseStates = getCachedRuleBaseStates();
final RuleInfoBuilder builder = new RuleInfoBuilder(rules);
builder.globals(globals);
builder.defaultFacts(objectList);
StatefulRuleInfo ruleInfo = new StatefulRuleInfoImpl(builder.build(), dispose, true);
- final RuleBase ruleBase = ruleBases.get( rules );
+ final DroolsRuleBaseState ruleBaseState = ruleBaseStates.get( rules );
- return executeStatefulRules(ruleBase, ruleInfo, message);
+ return ruleBaseState.executeStatefulRules(ruleInfo, message);
}
catch (Exception e)
{
@@ -485,10 +476,10 @@
{
try
{
- final Map<String, RuleBase> ruleBases = lifecycleRuleBases.getLifecycleResource();
- final RuleBase ruleBase = ruleBases.get(info.getRuleSource());
+ final Map<String, DroolsRuleBaseState> ruleBaseStates = getCachedRuleBaseStates();
+ final DroolsRuleBaseState ruleBaseState = ruleBaseStates.get(info.getRuleSource());
- return executeStatefulRules(ruleBase, info, msg);
+ return ruleBaseState.executeStatefulRules(info, msg);
}
catch (Exception e)
{
@@ -503,7 +494,7 @@
// package protected methods
/**
- * Determine if file based rules need reloading and return the rulebase
+ * Determine if file based rules need reloading and return the rulebase state
*
* @param ruleSet -
* String reference to a file which contains a ruleSet.
@@ -516,7 +507,7 @@
*
* @return Message with updated objects.
*/
- RuleBase getRuleBaseForFileBasedRules(
+ DroolsRuleBaseState getRuleBaseStateForFileBasedRules(
final String ruleSet,
final String dsl,
final boolean ruleReload) throws RuleServiceException
@@ -525,36 +516,41 @@
{
final DroolsRuleBaseHelper rbHelper = DroolsRuleBaseHelper.getInstance();
- String newRuleSet = null;
- boolean isRulesChanged = false;
- final Map<String, String> ruleSets = lifecycleRuleSets.getLifecycleResource();
+ final ConcurrentHashMap<String, String> ruleSets = lifecycleRuleSets.getLifecycleResource();
- synchronized (ruleSets) {
- if ( ruleReload )
- {
- String currentRuleSet = ruleSets.get( ruleSet );
- newRuleSet = rbHelper.getRulesAsString( ruleSet, dsl );
- if ( currentRuleSet == null || !currentRuleSet.equals(newRuleSet) )
- {
- isRulesChanged = true;
- }
- }
- final Map<String, RuleBase> ruleBases = lifecycleRuleBases.getLifecycleResource();
- RuleBase ruleBase = ruleBases.get( ruleSet );
- if ( ruleBase == null || isRulesChanged )
- {
- ruleBase = rbHelper.createRuleBaseFromRuleFiles(ruleSet, dsl);
- if (ruleBase != null)
- ruleBases.put(ruleSet, ruleBase);
- if (newRuleSet == null)
- newRuleSet = rbHelper.getRulesAsString(ruleSet, dsl);
- if (ruleSet != null)
- ruleSets.put(ruleSet, newRuleSet);
- }
+ synchronized(ruleSets)
+ {
+ String newRuleSet = null;
+ if ( ruleReload )
+ {
+ newRuleSet = rbHelper.getRulesAsString( ruleSet, dsl );
+ String oldRuleSet = ruleSets.put( ruleSet, newRuleSet );
+ if ((oldRuleSet != null) && !oldRuleSet.equals(newRuleSet) )
+ {
+ final DroolsRuleBaseState ruleBaseState = getCachedRuleBaseStates().remove(oldRuleSet);
+ if (ruleBaseState != null)
+ {
+ ruleBaseState.dispose() ;
+ }
+ }
+ }
- return ruleBase;
- }
+
+ final Map<String, DroolsRuleBaseState> ruleBaseStates = getCachedRuleBaseStates();
+ DroolsRuleBaseState ruleBaseState = ruleBaseStates.get(ruleSet) ;
+ if (ruleBaseState == null)
+ {
+ final RuleBase ruleBase = rbHelper.createRuleBaseFromRuleFiles(ruleSet, dsl);
+ if (newRuleSet == null)
+ newRuleSet = rbHelper.getRulesAsString(ruleSet, dsl);
+ ruleSets.put(ruleSet, newRuleSet);
+ ruleBaseState = new DroolsRuleBaseState(ruleBase) ;
+ ruleBaseStates.put(ruleSet, ruleBaseState) ;
+ }
+
+ return ruleBaseState;
+ }
}
catch (final LifecycleResourceException e)
{
@@ -571,7 +567,7 @@
}
/**
- * Determine if decision table need reloading and return the rulebase
+ * Determine if decision table need reloading and return the rulebase state
*
* @param decisionTable -
* String reference to a file which contains a decision table.
@@ -581,23 +577,37 @@
*
* @return Message with updated objects.
*/
- RuleBase getRuleBaseForDecisionTable(
+ DroolsRuleBaseState getRuleBaseStateForDecisionTable(
final String decisionTable,
final boolean ruleReload ) throws RuleServiceException {
try
{
- Map<String, RuleBase> ruleBases = getCachedRuleBases();
+ Map<String, DroolsRuleBaseState> ruleBaseStates = getCachedRuleBaseStates();
- synchronized (ruleBases) {
- RuleBase ruleBase = ruleBases.get( decisionTable );
- if ( ruleReload || ruleBase == null )
+ DroolsRuleBaseState ruleBaseState = (!ruleReload ? ruleBaseStates.get( decisionTable ) : null) ;
+ if (ruleBaseState == null)
+ {
+ synchronized (ruleBaseStates)
{
- ruleBase = DroolsRuleBaseHelper.getInstance().createRuleBaseFromDecisionTable(decisionTable);
- ruleBases.put( decisionTable, ruleBase );
+ if (!ruleReload)
+ {
+ ruleBaseState = ruleBaseStates.get( decisionTable );
+ }
+
+ if (ruleBaseState == null)
+ {
+ final RuleBase ruleBase = DroolsRuleBaseHelper.getInstance().createRuleBaseFromDecisionTable(decisionTable);
+ ruleBaseState = new DroolsRuleBaseState(ruleBase) ;
+ final DroolsRuleBaseState origRuleBasedState = ruleBaseStates.put( decisionTable, ruleBaseState );
+ if (origRuleBasedState != null)
+ {
+ origRuleBasedState.dispose() ;
+ }
+ }
}
- return ruleBase;
}
+ return ruleBaseState;
}
catch (final IOException e)
{
@@ -613,198 +623,8 @@
}
}
- /**
- * Execute rules using using the Stateless API
- *
- * @param rulebase -
- * the rulebase to use
- * @param message -
- * Message that is updated with the results.
- * @param objectList -
- * a list with additional objects (typically pulled from the message)
- * to be inserted into working memory
- * @param globals -
- * Map of globals variables that should be set in the working memory
- *
- * @return Message -
- * with updated objects.
- */
- Message executeStatelessRules(
- final RuleBase ruleBase,
- final Message message,
- final Map<String,Object> globals,
- final List<Object> objectList)
+ DroolsRuleBaseState getRuleBaseStateForRuleAgent( final String ruleAgentProperties ) throws IOException, Exception
{
-
- final StatelessSession statelessSession = ruleBase.newStatelessSession();
- RulesContext.clearContext() ;
- try
- {
- final List<Object> facts = getFacts( message, objectList );
- addGlobalsVariables( statelessSession, globals );
- statelessSession.execute(facts);
- }
- finally
- {
- RulesContext.clearContext() ;
- }
- return message;
- }
-
- /**
- * Execute rules using using the Stateful API
- *
- * @param rulebase -
- * the rulebase to use
- * @param dispose -
- * if true the working memory will be dereferenced.
- * @param message -
- * Message that is updated with the results.
- * @param globals -
- * Map of globals variables that should be set in the working memory
- * @param entryPointMap -
- * a map with additional objects to be inserted into working memory or
- * into the named WorkingMemoryEntryPoint. Any objects included in the
- * {@link #DEFAULT_ENTRY_POINT} name will be inserted into the normal
- * working memory. The rest will lookup the entry point working memory
- * and insert the objects into the those working memories.
- * @return Message -
- * a possibly updated Message object. The message object is available
- * to Rules and my be updated by them.
- * @throws RuleServiceException
- */
- Message executeStatefulRules(
- final RuleBase ruleBase,
- final StatefulRuleInfo ruleInfo,
- final Message message) throws RuleServiceException
- {
- synchronized (ruleBase)
- {
- RulesContext.clearContext() ;
-
- final StatefulSession statefulSession = getStatefulSession( ruleBase, ruleInfo.continueState() );
- try
- {
- addGlobalsVariables(statefulSession, ruleInfo.getGlobals());
-
- // Always insert the ESB Message object.
- InternalFactHandle handle = (InternalFactHandle) statefulSession.insert(message);
- if (log.isDebugEnabled())
- {
- if (handle.isEvent())
- {
- EventFactHandle ef = (EventFactHandle) handle;
- log.debug("Event :" + ef.getObject().getClass().getName() + ", startTimeStamp: " + ef.getStartTimestamp());
- }
- }
-
- // Always insert the Default facts
- final List<Object> defaultFacts = ruleInfo.getDefaultFacts();
- for (Object object : defaultFacts)
- {
- statefulSession.insert(object);
- }
-
- // Insert any object that that did not specify an entry-point into the main working memory.
- if (ruleInfo.getFacts() != null)
- {
- for (Entry<String, List<Object>> entry : ruleInfo.getFacts().entrySet())
- {
- String entryPointName = entry.getKey();
- // Insert object that have explicitely specifed an entry-point.
- WorkingMemoryEntryPoint wmep = statefulSession.getWorkingMemoryEntryPoint(entryPointName);
- if (wmep == null)
- {
- throw new RuleServiceException("The entry-point '" + entryPointName + "' was not found in the current stateful session. Please double check your rules source");
- }
- for (Object object : entry.getValue())
- {
- wmep.insert(object);
- }
- }
- }
- // Fire rules.
- statefulSession.fireAllRules();
- }
- finally
- {
- RulesContext.clearContext() ;
- if ( ruleInfo.dispose() )
- {
- statefulSession.dispose();
- }
- }
- }
- return message;
- }
-
- private List<Object> getFacts(final Message message, final List<Object> objectList )
- {
- final List<Object> facts = new ArrayList<Object>();
- facts.add( message );
- if ( objectList != null )
- facts.addAll( objectList );
- return facts;
- }
-
- /*
- * Checks whether the ruleBase has an existing session, and returns
- * that session, otherwise a new session is created.
- */
- private StatefulSession getStatefulSession( final RuleBase ruleBase, final boolean continueState )
- {
- synchronized (ruleBase) {
- final StatefulSession[] statefulSessions = ruleBase.getStatefulSessions();
- boolean existingSession = statefulSessions != null && statefulSessions.length > 0;
- if (existingSession)
- {
- final StatefulSession session = statefulSessions[0];
- if (continueState)
- {
- return session ;
- }
- else
- {
- session.dispose();
- }
- }
- return ruleBase.newStatefulSession();
- }
- }
-
- /*
- * Will set the passed-in elements in the globals Map as global
- * variables.
- */
- private void addGlobalsVariables( final StatelessSession statelessSession, final Map<String,Object> globals )
- {
- if ( globals != null )
- {
- Set<Entry<String, Object>> entrySet = globals.entrySet();
- for ( Entry<String, Object> entry : entrySet ) {
- statelessSession.setGlobal( entry.getKey(), entry.getValue() );
- }
- }
- }
-
- /*
- * Will set the passed-in elements in the globals Map as global
- * variables.
- */
- private void addGlobalsVariables( final StatefulSession statefulSession, final Map<String,Object> globals )
- {
- if ( globals != null )
- {
- Set<Entry<String, Object>> entrySet = globals.entrySet();
- for ( Entry<String, Object> entry : entrySet )
- {
- statefulSession.setGlobal( entry.getKey(), entry.getValue() );
- }
- }
- }
-
- RuleBase getRuleBaseForRuleAgent( final String ruleAgentProperties ) throws IOException, Exception
- {
Map<String, RuleAgent> ruleAgents = getCachedRuleAgents();
RuleAgent ruleAgent = ruleAgents.get( ruleAgentProperties );
if ( ruleAgent == null )
@@ -822,16 +642,26 @@
RuleBase currentRuleBase = ruleAgent.getRuleBase();
// always update the cache as the rulebase might have been updated.
- final RuleBase origRuleBase = getCachedRuleBases().put( ruleAgentProperties, currentRuleBase );
- if ((origRuleBase != currentRuleBase) && (origRuleBase != null))
+ final Map<String, DroolsRuleBaseState> ruleBaseStates = getCachedRuleBaseStates() ;
+ DroolsRuleBaseState ruleBaseState = ruleBaseStates.get(ruleAgentProperties) ;
+ if ((ruleBaseState == null) || (ruleBaseState.getRuleBase() != currentRuleBase))
{
- if (log.isInfoEnabled())
+ synchronized(ruleBaseStates)
{
- log.info("destroying stateful session for " + LifecycleResourceManager.getSingleton().getIdentity());
+ ruleBaseState = ruleBaseStates.get(ruleAgentProperties) ;
+ currentRuleBase = ruleAgent.getRuleBase();
+ if ((ruleBaseState == null) || (ruleBaseState.getRuleBase() != currentRuleBase))
+ {
+ if (ruleBaseState != null)
+ {
+ ruleBaseState.dispose() ;
+ }
+ ruleBaseState = new DroolsRuleBaseState(currentRuleBase) ;
+ ruleBaseStates.put(ruleAgentProperties, ruleBaseState) ;
+ }
}
- disposeStatefulSessions(origRuleBase.getStatefulSessions()) ;
}
- return currentRuleBase;
+ return ruleBaseState;
}
Map<String, RuleAgent> getCachedRuleAgents() throws LifecycleResourceException
@@ -839,17 +669,17 @@
return lifecycleRuleAgents.getLifecycleResource();
}
- Map<String, RuleBase> getCachedRuleBases() throws LifecycleResourceException
+ Map<String, DroolsRuleBaseState> getCachedRuleBaseStates() throws LifecycleResourceException
{
- return lifecycleRuleBases.getLifecycleResource();
+ return lifecycleRuleBaseStates.getLifecycleResource();
}
/**
- * The lifecycle resource factory for rule sets.
+ * The lifecycle resource factory for rule base state.
*
* @author kevin
*/
- public static class LifecycleRuleBaseFactory implements LifecycleResourceFactory<Map<String, RuleBase>>
+ public static class LifecycleRuleBaseStateFactory implements LifecycleResourceFactory<Map<String, DroolsRuleBaseState>>
{
/**
* Create a resource object which will be associated with the
@@ -861,9 +691,9 @@
* @throws LifecycleResourceException
* for errors during construction.
*/
- public Map<String, RuleBase> createLifecycleResource( final String lifecycleIdentity) throws LifecycleResourceException
+ public Map<String, DroolsRuleBaseState> createLifecycleResource( final String lifecycleIdentity) throws LifecycleResourceException
{
- return new ConcurrentHashMap<String, RuleBase>();
+ return new ConcurrentHashMap<String, DroolsRuleBaseState>();
}
/**
@@ -877,35 +707,20 @@
* @throws LifecycleResourceException
* for errors during destroy.
*/
- public void destroyLifecycleResource( final Map<String, RuleBase> resource, final String lifecycleIdentity) throws LifecycleResourceException
+ public void destroyLifecycleResource( final Map<String, DroolsRuleBaseState> resource, final String lifecycleIdentity) throws LifecycleResourceException
{
if (resource != null)
{
- final Collection<RuleBase> values = resource.values();
- for (RuleBase ruleBase : values)
- {
- if (log.isInfoEnabled())
- {
- log.info("destroying stateful session for " + lifecycleIdentity);
- }
- disposeStatefulSessions(ruleBase.getStatefulSessions());
- }
+ final Collection<DroolsRuleBaseState> values = resource.values();
+ for (DroolsRuleBaseState ruleBaseState : values)
+ {
+ ruleBaseState.dispose() ;
+ }
resource.clear();
}
}
}
- private static void disposeStatefulSessions(final StatefulSession[] sessions)
- {
- if (sessions == null)
- return;
-
- for (StatefulSession statefulSession : sessions)
- {
- statefulSession.dispose();
- }
- }
-
public static class LifecycleRuleAgentFactory implements LifecycleResourceFactory<Map<String, RuleAgent>>
{
/**
@@ -944,10 +759,17 @@
{
if (log.isInfoEnabled())
{
- log.info("destroying stateful session for " + lifecycleIdentity);
+ log.info("destroying rule agent for " + lifecycleIdentity);
}
- disposeStatefulSessions(ruleAgent.getRuleBase().getStatefulSessions());
ruleAgent.stopPolling() ;
+ final StatefulSession[] sessions = ruleAgent.getRuleBase().getStatefulSessions();
+ if (sessions != null)
+ {
+ for (StatefulSession statefulSession : sessions)
+ {
+ statefulSession.dispose();
+ }
+ }
}
resource.clear();
}
@@ -959,7 +781,7 @@
*
* @author kevin
*/
- public static class LifecycleRuleSetFactory implements LifecycleResourceFactory<Map<String, String>>
+ public static class LifecycleRuleSetFactory implements LifecycleResourceFactory<ConcurrentHashMap<String, String>>
{
/**
* Create a resource object which will be associated with the
@@ -971,7 +793,7 @@
* @throws LifecycleResourceException
* for errors during construction.
*/
- public Map<String, String> createLifecycleResource( final String lifecycleIdentity) throws LifecycleResourceException
+ public ConcurrentHashMap<String, String> createLifecycleResource( final String lifecycleIdentity) throws LifecycleResourceException
{
return new ConcurrentHashMap<String, String>();
}
@@ -988,7 +810,7 @@
* @throws LifecycleResourceException
* for errors during destroy.
*/
- public void destroyLifecycleResource( final Map<String, String> resource, final String lifecycleIdentity) throws LifecycleResourceException
+ public void destroyLifecycleResource( final ConcurrentHashMap<String, String> resource, final String lifecycleIdentity) throws LifecycleResourceException
{
if (resource != null)
{
Modified: labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/test/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleServiceUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/test/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleServiceUnitTest.java 2010-01-12 20:40:46 UTC (rev 31038)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/services/jbrules/src/test/java/org/jboss/internal/soa/esb/services/rules/DroolsRuleServiceUnitTest.java 2010-01-12 20:53:14 UTC (rev 31039)
@@ -63,7 +63,7 @@
{
private DroolsRuleService ruleService = new DroolsRuleService();
- private RuleBase ruleBase;
+ private DroolsRuleBaseState ruleBaseState;
private Message message;
private Order order;
@@ -74,7 +74,7 @@
public void executeStatelessRules()
{
Map<String,Object> globals = getGlobalsWithDestAndMessage();
- message = ruleService.executeStatelessRules( ruleBase, message , globals, null );
+ message = ruleBaseState.executeStatelessRules( message , globals, null );
ArrayList<String> destinations = getDistinations( globals );
assertTrue( destinations.size() == 1 );
}
@@ -300,7 +300,7 @@
@Before
public void setup() throws RuleServiceException
{
- ruleBase = ruleService.getRuleBaseForFileBasedRules( "JBossESBRules.drl", null, true );
+ ruleBaseState = ruleService.getRuleBaseStateForFileBasedRules( "JBossESBRules.drl", null, true );
message = MessageFactory.getInstance().getMessage();
order = new Order();
More information about the jboss-svn-commits
mailing list