Drools Server Configuration Using Spring

Now we can forget the profiles.xml configuration file, that I introduce on my previous post, and configure the service using Spring. If you have used the drools-spring module you know what I’m talking about. Or you can check this here

Don’t get crazy, but now we have 4 xml configuration files. Let’s talk a little about them.

configuration.xml: It is the main xml file, but only is used to import the next three files. So, you don’t need to modify this file.

core.xml
: As the previous file, you don’t need to modify this one either. This file only contains the REST/SOAP services configuration.

sessions.xml: In this file you can configure the knowledge base and knowledge sessions that are going to be used on the service definition. The configuration is the same as previously used on the drools-spring module, but now the drools:kbase can have a XSD model definition file using the tag <drools:model/>

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:drools="http://drools.org/schema/drools-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
		http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd"
    default-autowire="byName">

    <drools:connection id="connection1" type="local" />

    <drools:execution-node id="node1" connection="connection1" />

    <drools:kbase id="kbase1" node="node1">
	<drools:resource source="classpath:changesets/change-set-1.xml" type="CHANGE_SET" />
        <drools:model source="classpath:model/person.xsd" />
    </drools:kbase>

    <drools:kbase id="kbase2" node="node1">
        <drools:resource source="classpath:changesets/change-set-2.xml" type="CHANGE_SET" />
    </drools:kbase>

    <drools:ksession id="ksession1" type="stateful"  kbase="kbase1" node="node1"/>

    <drools:ksession id="ksession2" type="stateless" kbase="kbase2" node="node1"/>

</beans>

services.xml: In this file you can configure the drools server service, and contains the new definitions added to the drools-spring service.

The first thing that you should know is that there’s a new xml namespace for this, named drools-service. The configuration files shipped with the drools-service.war already have this definition, so you shouldn’t take care about this.

Here’s a full configuration example.


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:camel="http://camel.apache.org/schema/spring"
    xmlns:drools-service="http://drools.org/schema/drools-service-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
		http://drools.org/schema/drools-service-spring http://drools.org/schema/drools-service-spring.xsd
		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"
    default-autowire="byName">

	<!-- Only needed to deploy on JBoss AS 5.X -->
    <bean id="jbossResolver" class="org.apache.camel.jboss.JBossPackageScanClassResolver"/>

    <!-- This camel context bean is required -->
	<camelContext id="executionContext" xmlns="http://camel.apache.org/schema/spring" />

	<drools-service:configuration id="service-conf-2" marshaller="XSTREAM" session="ksession2" />

	<drools-service:definition id="service" smId="sm1" camelContext="executionContext">
		<drools-service:configuration marshaller="JAXB" session="ksession1">
			<drools-service:class>org.drools.model.Person</drools-service:class>
			<drools-service:startup-command>
				<![CDATA[
				<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
				<batch-execution lookup="ksession1" xmlns:ns2="http://drools.org/model">
				    <insert out-identifier="santa">
				        <object xsi:type="ns2:person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
				            <ns2:name>santa</ns2:name>
				            <ns2:age>99</ns2:age>
				        </object>
				    </insert>
				</batch-execution>
	  	   		]]>
			</drools-service:startup-command>
		</drools-service:configuration>
		<drools-service:configuration-ref id="service-conf-2" />
	</drools-service:definition>

</beans>

There are a lot of new definitions, so let’s go step by step.

The next bean definition is only needed when the war file is deployed on a JBoss AS 5, to solve Apache Camel issues with the new AS classloader.

<bean id="jbossResolver" class="org.apache.camel.jboss.JBossPackageScanClassResolver"/>

Here we configure the Apache Camel Context bean instance.

<camelContext id="executionContext" xmlns="http://camel.apache.org/schema/spring" />

We can define an external drools service configuration, in this example we define a configuration that will use the Stateless Knowledge Session with id ksession2 and with XStream as the command marshaller.

<drools-service:configuration id="service-conf-2" marshaller="XSTREAM" session="ksession2" />

And next is the drools service definition, named by default as service (note: if you want to change the drools service definition id you must also change the bean reference on core.xml file). Also this definition must reference to the serviceManager used in the Knowledge Sessions creation and the Camel Context bean defined previously.

Inside the definition we can add multiple configurations, defined internally or externally. In this example we are adding to configurations: one externally referenced as “service-conf-2” and another internally.
The internal definition is using the JAXB marshaller and associated to the Stateful Knowledge Session with id ksession1. Also it is making a reference to the class called org.drools.model.Person, which was defined on the XSD file used in the creation of the KnowledgeBase with id kbase1, to be included on the JAXB Context that is going to be used on the marshalling/unmarshalling of the commands with JAXB format.

And finally, there is a tag named to specify commands that are going to be executed when the .war file is deployed. You don’t need to include this startup commands, it’s just only in case that you need something to initialize your Knowledge Session. Remember that you must use the tags, that allows us to include xml snippets without the need of escaping all the xml tags, when you add one xml command.

<drools-service:definition id="service" smId="sm1" camelContext="executionContext">
		<drools-service:configuration marshaller="JAXB" session="ksession1">
			<drools-service:class>org.drools.model.Person</drools-service:class>
			<drools-service:startup-command>
				<![CDATA[
				<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
				<batch-execution lookup="ksession1" xmlns:ns2="http://drools.org/model">
				    <insert out-identifier="santa">
				        <object xsi:type="ns2:person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
				            <ns2:name>santa</ns2:name>
				            <ns2:age>99</ns2:age>
				        </object>
				    </insert>
				</batch-execution>
	  	   		]]>
			</drools-service:startup-command>
		</drools-service:configuration>
		<drools-service:configuration-ref id="service-conf-2" />
	</drools-service:definition>

How to use drools-server

On this new version we are using the Drools Commands API in XML form. Take a look at the following example:

BatchExecutionCommand executionCommand = new BatchExecutionCommand();

InsertObjectCommand insertCommand = new InsertObjectCommand();
insertCommand.setObject(new Person("lucaz"));
insertCommand.setOutIdentifier("person1");

executionCommand.setLookup("ksession1");
executionCommand.getCommands().add(insertCommand);

String xml = BatchExecutionHelper.newXStreamMarshaller().toXML(executionCommand);

With this lines you will get the xml command representation, using xstream marshaller, that you can use to interact with the drools execution server:

<batch-execution lookup="ksession1">
  <insert out-identifier="person1" return-object="true">
    <org.drools.pipeline.camel.Person>
      <name>lucaz</name>
    </org.drools.pipeline.camel.Person>
  </insert>
</batch-execution>

RestWS integration

Let’s test the RestWS service by following this steps:

1) Create an Apache HttpClient instance and configure it with the drools-server ip address and port:

HttpClient httpClient = new HttpClient();
httpClient.getHostConfiguration().setHost("127.0.0.1", 8080);

2) Create a PosthMethod and send the xml command to the URI /drools-server/services/rest/execute

PostMethod postMethod = new PostMethod("/drools-server/services/rest/execute");
postMethod.addParameter("command", xmlCommand);

3) Execute the method. If the execution was succesfull you will got a HTTP Response Code OK (200) otherwise a BAD_REQUEST (400) response code will be thrown to the client.

httpClient.executeMethod(postMethod);
assertEquals(200, postMethod.getStatusCode());

4) And finally, get the execution response

String response = postMethod.getResponseBodyAsString();

SOAP integration

Here’s one way to use the SOAP interface with Apache CXF:

1) Create a JaxWsProxyFactoryBean, set the KnowledgeServiceSoap (that could be generated with the WSDL exposed at http://127.0.0.1:8080/drools-server/services/soap?wsdl ) as the Service Class and the URL

JaxWsProxyFactoryBean clientFactory = new JaxWsProxyFactoryBean();
clientFactory.setServiceClass(KnowledgeServiceSoap.class);
clientFactory.setAddress("http://127.0.0.1:8080/drools-server/services/soap");

2) Create the KnowledgeServiceSoap client and execute the xml command

<span style="font-size: x-small;">KnowledgeServiceSoap client = (KnowledgeServiceSoap) clientFactory.create();
String response = client.execute(xmlCommand);</span>

That’s all, not too much more magic. Now, with these features, we have a more unified service definition using the drools-spring module. If you want to see this running, you can download a client project and the compiled drools-server.war from this link

Feedback is always appreciated.

Advertisements

New Drools Execution Server

Update: drools-server features/configuration were changed, please read the updated post here

Hi everyone,  last week I was working on a new version of the Drools Execution Server. The goal of this new version was to get the new XStream/JAXB Drools Camel integration to execute commands using a simple service that can be accessed using the RestWS and SOAP protocols. Similar to the previous version, the Drools Execution Server is a simple WAR file that can be deployed on a JBoss AS or any other servlet container.

But the big new feature is the ability to use both stateful and stateless knowledge sessions that can be accessed throught REST and SOAP at the same time.

You must note that in the past, the old drools-server saved the following information in order to create only stateless knowledge session:

newInstance=true
file=TestService.drl

This information was stored in a file called <session>.properties, where <session> is the name of the stateless session that was used in the request to reference a specific state knowledge session, that in the previous version can only contain a single rule file.

This approach was extended with the concept of Knowledge Context Profiles. Each Knowledge Context Profile let us define more complex execution scenarios. Now we can define Stateful and Stateless sessions with more that one Knowledge resource, using different marshallers to send and recieve the information that we will use to interact with this remote sessions.

Profiles can be configured through a simple profiles.xml file, which resides inside the WAR file, and can contain multiple Knowledge Context Profiles definitions, as in the following XML example:

<?xml version="1.0" encoding="UTF-8" ?>
<profiles>
	<knowledge-context-profile id="ksession1">
		<session-type>stateful</session-type>
		<change-sets>
			<file>changesets/change-set-1.xml</file>
		</change-sets>
		<marshaller>jaxb</marshaller>
		<jaxb-models>
			<file>model/person.xsd</file>
		</jaxb-models>
		<startup-commands>
			<command>
        	<![CDATA[
			<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
			<batch-execution lookup="ksession1" xmlns:ns2="http://drools.org/model">
			    <insert out-identifier="santa">
			        <object xsi:type="ns2:person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			            <ns2:name>santa</ns2:name>
			            <ns2:age>99</ns2:age>
			        </object>
			    </insert>
			</batch-execution>
  	   		]]>
			</command>
		</startup-commands>
	</knowledge-context-profile>

	<knowledge-context-profile id="ksession2">
		<session-type>stateless</session-type>
		<marshaller>xstream</marshaller>
		<change-sets>
			<file>changesets/change-set-2.xml</file>
		</change-sets>
	</knowledge-context-profile>

</profiles>

As you can see to configure each knowledge-context-profiles you need to set up the following information:

  • id: the session identifier (required)
  • session-type: stateless/stateful (required)
  • change-sets: here you can add the changesets that contains references to the rules to be used on the session
  • jaxb-models: this is only if you wanted to use jaxb-commands and define the model with an XSD model definition (required only when using jaxb)
  • classes-names:  classes that you could include on jaxb context (required on jaxb)
  • startup-commands: here you can add xml commands to be executed on the session  startup.

Deployment
Actually the drools server was tested on JBoss AS 5.X and JBoss AS 4.2.3, but should work on any servlet container. Just copy the .war file on the deploy folder and configure the profiles.xml file inside the /WEB-INF/classes directory.

Note: to deploy in JBoss AS 4.X (and probably another servlet containter) you need to modify the cxf.xml server configuration file located inside /WEB-INF/. You need to replace the next lines

<bean id="knowledgeService" class="org.drools.server.KnowledgeService" >
        <property name="packageScanClassResolver">
            <ref local="jbossResolver" />
        </property>
</bean>

<bean id="jbossResolver" />

with

<bean id="knowledgeService"  class="org.drools.server.KnowledgeService" /> to make it work.

This will change how Apache Camel will interact with the JBoss AS5 classloader, pretty simple.

Commands

On this new version we are using the Drools Commands API in XML form. Take a look at the following example:

BatchExecutionCommand executionCommand = new BatchExecutionCommand();

InsertObjectCommand insertCommand = new InsertObjectCommand();
insertCommand.setObject(new Person("lucaz"));
insertCommand.setOutIdentifier("person1");

executionCommand.setLookup("ksession1");
executionCommand.getCommands().add(insertCommand);

String xml = BatchExecutionHelper.newXStreamMarshaller().toXML(executionCommand);

With this lines you will get the xml command representation, using xstream marshaller, that you can use to interact with the drools execution server:

<batch-execution lookup="ksession1">
  <insert out-identifier="person1" return-object="true">
    <org.drools.pipeline.camel.Person>
      <name>lucaz</name>
    </org.drools.pipeline.camel.Person>
  </insert>
</batch-execution>

RestWS integration

Let’s test the RestWS service by following this steps:

1) Create an Apache HttpClient instance and configure it with the drools-server ip address and port:

HttpClient httpClient = new HttpClient();
httpClient.getHostConfiguration().setHost("127.0.0.1", 8080);

2) Create a PosthMethod and send the xml command to the URI /drools-server/services/rest/execute

PostMethod postMethod = new PostMethod("/drools-server/services/rest/execute");
postMethod.addParameter("command", xmlCommand);

3) Execute the method. If the execution was succesfull you will got a HTTP Response Code OK (200) otherwise a BAD_REQUEST (400) response code will be thrown to the client.

httpClient.executeMethod(postMethod);
assertEquals(200, postMethod.getStatusCode());

4) And finally, get the execution response

String response = postMethod.getResponseBodyAsString();

SOAP integration

Here’s one way to use the SOAP interface with Apache CXF:

1) Create a JaxWsProxyFactoryBean, set the KnowledgeServiceSoap (that could be generated with the WSDL exposed at http://127.0.0.1:8080/drools-server/services/soap?wsdl ) as the Service Class and the URL

JaxWsProxyFactoryBean clientFactory = new JaxWsProxyFactoryBean();
clientFactory.setServiceClass(KnowledgeServiceSoap.class);
clientFactory.setAddress("http://127.0.0.1:8080/drools-server/services/soap");

2) Create the KnowledgeServiceSoap client and execute the xml command

<span style="font-size: x-small;">KnowledgeServiceSoap client = (KnowledgeServiceSoap) clientFactory.create();
String response = client.execute(xmlCommand);</span>

Future Steps (in development)

Currently I’m working on a new Guvnor module that will let us define the Knowledge Context Profile with a guided editor (without write XML!), and with a similar change-sets structure. Also you could add drools-server instance and do simple operations, as send commands to execute, check the server status and others features.

Note: Drools Execution Server is not merged into the trunk, but we are working to merge it as soon as possible and include this features in the M2 release. Please, let me kwow what do you think when M2 is ready!



Como configurar el plugin de Drools Eclipse

Algo muy útil para desarrollar nuestras reglas es utilizar el plugin que nos brinda Drools. Para esto necesitamos tener una version de Eclipse 3.5 (recomendado) o una anterior. Una vez iniciado Eclipse vamos a instalar el plugin, para esto nos dirijimos al menú Help -> Install new software y en este wizard agregamos el repositorio de JBoss Tools

Lo más recomendable, y si querés instalarlo en Eclipse 3.5, es utilizar el repositorio de Development que tiene la siguiente url: http://download.jboss.org/jbosstools/updates/development/ , para update sites de otras versiones entrá acá

Una vez aceptado, seleccionado JBoss Tools y actualizada la información del repositorio, hacemos un filtrado rápido buscando Drools y seleccionamos los plugins que necesitamos (Core, Guvnor y/o Task). Ahora lo único que debemos hacer es seguir los pasos de instalación, aceptar las licencias y reiniciar el workbench.

Una vez reiniciado Eclipse se tiene que configurar el Drools Runtime en las Preferencias de Eclipse. Estos Drools Runtime nos van a permitir ejecutar/debugguear nuestras reglas con distintas versiones de Drools. Lo que tenemos que hacer acá es agregar los distintos runtimes que queramos utilizar en nuestros Drools Project. Tan solo es necesario ingresar un nombre y el path donde están todas las librerías de Drools, o al menos las necesarias para la ejecución/compilación. Que según la documentación oficial son:

* drools-core
* drools-api
* drools-compiler
* antlr3-runtime-3.1.1
* xerces-2.9.1, xml-apis-2.0.2 – only if you are using XML rules, if DRL
only, can skip this.
* eclipse-jdt-core-3.4.2.v_883_R34x – only if you want to compile with
eclipse
* janino-2.5.15 – only if you want to compile with janino

Lo recomendable sería tener configurados al menos dos runtimes, uno con la última versión oficial y otra con la ultima versión estable de desarrollo, que se puede obtener del Hudson https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/

Como último dato, un problema muy común es la aparición de errores al compilarse las reglas con el Drools Builder, esto se debe a que falta agregarse la librería org.eclipse.jdt.core_{$version}.jar, que se encuentra dentro de la carpeta plugins de la instalación de eclipse, como dependencia del proyecto.

JBossInBossa 2010

JBossInBossa 2010

Del 16 al 17 de Abril se va a realizar la conferencia anual del JBug Brasil en San Pablo, donde se podrá asistir a diversas charlas/workshops sobre los productos de JBoss. Algo muy importante de esta conferencia es la asistencia de líderes de proyectos de JBoss, commiters, arquitectos de JBoss y personas interesadas en difundir el uso de diversos frameworks.

Como representante argentino va a estar Mauricio “salaboy” Salatino (JBoss Drools Commiter / Plug Tree CTO) realizando un workshop en conjunto a otro commiter de Drools, Alexandre Porcelli (Caravela Tech / JBoss Drools Commiter), sobre los fundamentos del proyecto junto a algunos ejemplos muy interesantes para mostrar otros posibles usos del motor de reglas.

También está confirmada la presencia de Pete Muir (Lider de los proyectos Seam y Weld), que va a comentar sobre las novedades de Seam 3 y sobre la nueva especificación JSR 299 – Contexts and Dependency Injection for Java EE que está incluida en Java EE6

Hay muchas más charlas agendadas y otras por confirmarse, así que nada mejor que revisar la agenda del evento para mantenerse al tanto. Si tienen la oportunidad de concurrir no se la pierdan, ya que sino me equivoco es el evento más importante sobre JBoss en Latinoamérica.

Para más información podes entrar al sitio del evento http://www.jbossinbossa.com.br/ y también seguirlos en twitter http://www.twitter.com/jbossinbossa

HornetQ: la nueva mensajería de JBoss

hornetQ_logo_450px

HornetQ es el nuevo producto de mensajería que está siendo desarrollado para reemplazar JBoss Messaging en su stack de aplicaciones. Si bien está basado en JBoss Messaging está completamente desarrollado desde cero tomando las mejores características de este y agregando un nuevo diseño basado en POJO lo que permite ejecutarlo standalone dentro de tu aplicación con unas pocas líneas de código, entre otras características. Desde su sorpresivo anuncio en el JBoss World está teniendo muchísima atención como una buena alternativa para reemplazar a otros productos open source como ActiveMQ, que desgraciadamente está dando muchas decepciones a la comunidad, a tal punto que varias empresas están empezando a migrar a HornetQ sin siquiera existir una versión final.

Características principales:

  • Open Source y desarrollado en Java 1.5, aunque hay planes para migrar a 1.6 dejando retrocompatibilidad
  • Soporte JMS y una API propia de mensajería (que elimina el overhead de JMS), además existen planes para agregar otros protocolos como AMQP, STOMP, etc.
  • Diseñado con POJOs y con una mínima dependencias de libreria de terceros (practicamente nula)
  • Alta disponibilidad, clustering y alta performance a partir de su propio journaling de alta performance (libaio/Java NIO)

Se espera que esté integrado en la próxima release del AS 5 y una versión GA dentro de las próximas semanas. Si bien se puede instalar en un AS 4 no es lo óptimo, pero se puede hacer mediante los scripts de integración que viene en la distro.

Precisamente en esa tarea estuve involucrado estas últimas semanas junto al team de desarrollo. Lo que realice fue básicamente unos scripts y un par de  Standard MBean que permiten instalar una instancia de HornetQ en cualquier versión del AS 4 de forma transparente al usuario y de forma similar a la que se realiza ahora en un AS 5. Esta funcionalidad está disponible en el trunk de proyecto y en los nighty builds, mientras se espera que esté disponible la CR1.

Es una buena oportunidad de ayudar a la comunidad en tus tiempos libres, si alguien está interesado los developers están buscando activamente nueva gente para involucrarse y te lo van a agradecer.

Por último dejo el sitio oficial del proyecto, donde pueden ver la documentación, las FAQs y hacia donde se dirigen

http://www.hornetq.org

JBoss Community Asylum – Episodio 2

Hoy salió una nueva emisión del podcast de JBoss donde varios core developers e invitados discuten y comentan sobre las novedades de la comunidad. Una buena manera de enterarnos que es lo que está pasando, que es lo que se viene y en que andan algunos developers como Michael Neale, Emannuel Bernard, Max Rydahl Andersen y otros.

UPDATE: Van a poder escuchar a Neale intentando pronunciar mi apellido y explicar mi trabajo en el Google Summer of Code!

http://asylum.jboss.org/

Fin del Google Summer of Code 2009

Si, finalmente se terminaron los plazos, se commitearon las modificaciones, se enviaron las evaluaciones y se terminó la codificación de los últimos días en contra del reloj… todo esto hace más de un mes atrás. Esta es una simple actualización, sin video, imagen o diagrama de clases, para tan solo comunicar que mi propossal para JBoss Drools fue terminada y aceptada así que es de esperar errores en el hudson, comportamiento erróneo en el IDE y demás luminarias 😉

Sin dudarlo es una buena experiencia para adentrarse en el mundo del open source, porque seguro que lo posterior que vas a hacer es buscarte tasks en el JIRA (aunque ahora no te paguen, claro)