Jugando con Drools 5.0 – #3 Drools Expert
Mayo 29, 2009
Continuando con los dos post anteriores (post1 y post2), vamos a analizar el comportamiento de la aplicación cuando la misma se ejecuta. La idea es explicar y aclarar el comportamiento del framework para esta situación en particular y además dejar planteado los comportamientos que por lo general se intentan modelar con estos motores de inferencias.
Primero que nada recordemos el código que armaba la sesión de Drools con la que vamos a interactuar:
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newInputStreamResource(new App().getClass().getResourceAsStream("/rules/juego.drl")),ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.out.println(kbuilder.getErrors());
return;
}
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kpkgs );
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);
ksession.insert(new Juego("Poker",2));
ksession.insert(new Jugador("Jugador 1"));
ksession.insert(new Jugador("Jugador 2"));
ksession.fireAllRules();
Como podemos ver, una vez que creamos la sesión podemos interactuar con ella mediante el método insert(), que va a insertar nuevos Facts/Hechos a la memoria de trabajo que posee Drools para realizar las inferencias. Una vez ejecutado el método insert(), el objeto ya se encontrara dentro de la memoria de trabajo y automáticamente Drools analizara que deducciones puede realizar sobre el.
Análisis de la ejecución
A continuación vamos a ir viendo como se relaciona la salida que obtenemos por consola con la ejecución del código y las evaluaciones que se realizan las reglas sobre los facts.
Cuando realizamos el primer ksession.insert(new Juego(“Poker”,2)); la siguiente linea aparece por consola:
OBJECT ASSERTED value:Juego =Poker factId: 1
Lo mismo sucede cuando insertamos el primero Jugador:
OBJECT ASSERTED value:Jugador 1 - cartas: [] puntos =0 factId: 3
Ahora cuando vamos a realizar el siguiente insert, es decir cuando llamamos al método insert e insertamos un nuevo Jugador, debido a que hay una regla que esta esperando 2 jugadores para activarse, una Activación es creada. Esto significa que ya hay una regla lista para ejecutarse para un set de Facts determinados.
ACTIVATION CREATED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1) OBJECT ASSERTED value:Jugador 2 - cartas: [] puntos =0 factId: 4
Si analizamos la linea que comienza con “ACTIVATION CREATED” veremos que nos indica el nombre de la regla que esta cumpliendo con la condición (y sus restricciones) junto con los datos de los Facts que las satisfacen.
Ahora bien, en nuestra aplicación, no llamamos mas al método insert, ahora es el turno de llamar al famoso y querido método fireAllRules(). Este método, se encargara de ejecutar las Activaciones creadas, que se hayan generado con los inserts anteriores. Por esto, las siguientes lineas se mostraran en la consola cuando el metodo fireAllRules se ejecute:
BEFORE ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1) ACTIVATION CREATED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1) OBJECT ASSERTED value:Poker Dealer - cartas: [] puntos =0 factId: 5 AFTER ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0, Poker Dealer - cartas: [] puntos =0](2); $juego=Juego =Poker(1) BEFORE ACTIVATION FIRED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1) ACTIVATION CREATED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [] puntos =0(4) ACTIVATION CREATED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [] puntos =0(3) OBJECT ASSERTED value:Nueva Ronda factId: 6 AFTER ACTIVATION FIRED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [13 de Pica, 13 de Diamante, 7 de Trebol, 8 de Corazon, 6 de Corazon, ] puntos =0(5); $juego=Juego =Poker(1) BEFORE ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [] puntos =0(4) AFTER ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [18, 4, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 2 - cartas: [2 de Trebol, 4 de Corazon, ] puntos =0(4) BEFORE ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [] puntos =0(3) AFTER ACTIVATION FIRED rule:Nueva Ronda activationId:Nueva Ronda [19, 3, 1, 6] declarations: $juego=Juego =Poker(1); $jugador=Jugador 1 - cartas: [9 de Pica, 13 de Trebol, ] puntos =0(3)
Todo esto sucede cuando el método fireAllRules() se ejecuta, pero, que exactamente hace este método? Como vemos en la consola, lo primero que este método va a realizar es la ejecución de la activación que se habia generado cuando estábamos insertando facts en la sesión. La ejecución de estas activaciones van a ser loggeadas en consolas antes y después de ejecutarse. Esto es para que nosotros podamos ver, si la consecuencia de la regla que se ejecuta nos modifica el estado actual de la memoria de trabajo.
Como vemos en el log anterior, en las primeras 4 lineas, sucede exactamente esto que estábamos describiendo.
BEFORE ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0](2); $juego=Juego =Poker(1) ACTIVATION CREATED rule:Iniciar Ronda Poker activationId:Iniciar Ronda Poker [5, 1] declarations: $dealer=Poker Dealer - cartas: [] puntos =0(5); $juego=Juego =Poker(1) OBJECT ASSERTED value:Poker Dealer - cartas: [] puntos =0 factId: 5 AFTER ACTIVATION FIRED rule:Comienza una ronda de Poker cuando hay n jugadores activationId:Comienza una ronda de Poker cuando hay n jugadores [2, 1] declarations: $jugadores=[Jugador 1 - cartas: [] puntos =0, Jugador 2 - cartas: [] puntos =0, Poker Dealer - cartas: [] puntos =0](2); $juego=Juego =Poker(1)
Entre un BEFORE ACTIVATION FIRED y un AFTER ACTIVATION FIRED, de la misma regla podemos ver si la consecuencia de la misma, cambio el estado de algún hecho/fact, se inserto un nuevo hecho/fact o por alguna otra razón se genero una nueva activación. En este caso en particular vemos que se creo una nueva Activación de de una regla llamada “Iniciar Ronda Poker” al haber sido insertado un objeto de tipo Dealer en la consecuencia de la regla “Comienza una ronda de Poker cuando hay n jugadores“.
Si recordamos la consecuencia de la regla “Comienza una ronda de Poker cuando hay n jugadores“, podemos ver que efectivamente esta regla esta insertando un nuevo hecho de tipo Dealer, con lo cual causa una nueva activación para la regla llamada “Iniciar Ronda Poker“.
then
$juego.setMazo(MazoPoker());
Dealer dealer =new Dealer("Poker Dealer");
insert(dealer);
Cuando este hecho/fact de tipo Dealer sea insertado en la memoria de trabajo de Drools, la regla llamada “Iniciar Ronda Poker“, que tiene la siguiente condición, genera una activación:
$juego: Juego(nombre == "Poker") $dealer: Dealer()
Esto se debe a que ya teniamos un Juego, el que nosotros habiamos insertado y ahora la regla anterior inserto un nuevo Dealer, entonces la consecuencia de la regla tiene que ser ejecutada.
Siguiendo esta misma lógica, pueden analizar el resto de las activaciones que se generan, asi modificar el ejemplo para que se generen nuevas o diferentes activaciones según el estado de la memoria de trabajo de Drools.
Consultas sobre la memoria de trabajo
Para ir terminando con este post, solo resta ver la ejecución de cada uno de los queries que se realiza al finalizar todas las inferencias. Es bueno aclarar también que cuando ya no quedan activaciones que ejecutar, el método fireAllRules devuelve el control a nuestra aplicación para que pueda continuar su ejecución.
Cuando el control retorna a la aplicación luego del método fireAllRules(), podemos consultar como quedaron nuestros hechos en la memoria de trabajo. Para esto podemos definir consultas/queries en nuestros archivos DRL que incluimos a la hora de armar nuestra sesión.
En este caso, se agrego la siguiente consulta:
query "Jugador por nombre" (String qnombre) jugador : Jugador( nombre == qnombre) end
Es bueno notar que la sintaxis para definir consultas es la misma que para expresar restricciones en las condiciones de nuestras reglas.
La salida a consola de la ejecución de esta consulta con diferentes parámetros es la siguiente:
El Dealer tiene las cartas: OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 20 [Carta -> 13dePica, Carta -> 13deDiamante, Carta -> 7deTrebol, Carta -> 8deCorazon, Carta -> 6deCorazon] El Jugador 1 tiene las cartas: OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 21 [Carta -> 9dePica, Carta -> 13deTrebol] El Jugador 2 tiene las cartas: OBJECT ASSERTED value:org.drools.base.DroolsQuery@f7a53d93 factId: 22 [Carta -> 2deTrebol, Carta -> 4deCorazon]
Donde el código para ejecutar cada una de estas consultas es el siguiente:
QueryResults results = ksession.getQueryResults("Jugador por nombre", new Object[]{"Poker Dealer"});
for ( QueryResultsRow row : results ) {
Jugador jugador = ( Jugador ) row.get( "jugador" );
System.out.println( jugador.getCartas() + "\n" );
}
Donde se puede apreciar que estas consultas se ejecutan obteniendolas por nombre y pasando los parámetros como un array de objetos. Luego para recuperar los resultados obtenemos los objetos mediante el nombre de su variable vinculada, en este caso llamada “jugador“. Vale la aclaración de que debería llamarse $jugador para seguir con las reglas de legibilidad.
Conclusión
Vimos un poco como es el flujo de ejecución de este ejemplo propuesto en particular. Espero que esta explicación, también genere dudas e inquietudes sobre como funciona el framework internamente. La idea principal de estos posts, es dejar precedencia para poder escribir artículos mas profundos sobre temas mas avanzados. Espero sus comentarios, criticas y dudas si es que las hay.
Saludos.
PD: nuevamente les dejo el link del ejemplo, para que no tenga que andar buscandolo por todos lados: www.jbug.com.ar/external/playingWithDrools-ExpertIntroduction.zip
Jugando con Drools 5.0 – #2 Drools Expert
Mayo 27, 2009
Continuando con el ejemplo propuesto en el post anterior, vamos a analizar las reglas propuestas, junto con el modelo de dominio (objetos) propuestos para el ejemplo.
Hay que tener en cuenta que este modelo, fue creado a modo de ejemplo, y puede no contemplar algunas situaciones. Asi que acepto sugerencias, si el ejemplo no les parece el mas adecuado, o se les ocurre algún otro modelo de dominio con el cual ejemplificar.
Les recomiendo que si no leyeron el post anterior, lo lean, ya que explica la estructura del proyecto propuesto y aclara un poco las APIs básicas que vamos a utilizar cuando definimos conocimiento en forma de reglas de negocio dentro de Drools 5.0.
Modelo de dominio
En este ejemplo, vamos a utilizar un modelo de dominio bastante simple para crear algunas reglas de negocio simples. La idea de este dominio es simular un escenario donde podemos definir distintos juegos de cartas y dependiendo de la cantidad de jugadores que el juego necesite, crear una ronda cuando se pueda empezar con algún juego. En este caso, vamos a ver como se podría escribir algunas reglas para que cuando se cumplan las condiciones, el juego definido comience.
Como podemos ver en la imagen, la clase Juego nos permitiría definir el nombre del juego y algunos datos genéricos que el mismo debería almacenar. Por ejemplo, todo juego tiene una relación con un Mazo de cartas y cuantas cartas por mano se deberán repartir a los jugadores de dicho juego.
Asi también estan definidas las clases Carta y Jugador, que mantienen información genérica sobre estas entidades que se utilizaran en todos los juegos.
Como podran apreciar, estas clases son simples POJOS (Plain Old Java Objects), por lo tanto, técnicamente no hay mucho que aclarar. Estas clases representaran las entidades que nuestro dominio necesita poder representar las interacciones de la realidad. En otras palabras, estas clases representan la información que se manejara en un escenario real donde tengamos Juegos de cartas.
Especificando reglas de negocio
Una vez que conocemos nuestro modelo de dominio, ya estamos listos para empezar a escribir reglas que van a actuar sobre el. Para esto, vamos a crear un archivo de texto plano en el directorio /src/main/resources/rules llamado juego.drl.
Para los que no conocen DRL es la extensión que se suele utilizar para los archivos que van a contener reglas de negocios expresados en el lenguaje que propone Drools. A continuación vemos este archivo que pueden encontrar dentro del directorio antes mencionado.
package com.wordpress.salaboy.playing.with.drools
import com.wordpress.salaboy.playing.with.drools.model.Juego;
import com.wordpress.salaboy.playing.with.drools.model.Jugador;
import com.wordpress.salaboy.playing.with.drools.model.Dealer;
import com.wordpress.salaboy.playing.with.drools.model.MazoPoker;
import com.wordpress.salaboy.playing.with.drools.model.Mazo;
import com.wordpress.salaboy.playing.with.drools.model.Ronda;
import com.wordpress.salaboy.playing.with.drools.model.Carta;
import java.util.ArrayList;
query "Jugador por nombre" (String qnombre)
jugador : Jugador( nombre == qnombre)
end
rule "Comienza una ronda de Poker cuando hay n jugadores"
when
$juego: Juego(nombre == "Poker")
$jugadores: ArrayList( size == 2 ) from collect (Jugador())
then
$juego.setMazo(new MazoPoker());
Dealer dealer = new Dealer("Poker Dealer");
insert(dealer);
end
rule "Iniciar Ronda Poker"
when
$juego: Juego(nombre == "Poker")
$dealer: Dealer()
then
$dealer.addCartas($juego.getMazo().getMano(5));
insert(new Ronda());
end
rule "Nueva Ronda"
when
Ronda()
$juego: Juego(nombre == "Poker")
$jugador: Jugador()
ArrayList(size == 0) from collect ( Carta() from $jugador.cartas)
//eval($jugador.getCartas().size() == 0)
then
$jugador.addCartas($juego.getMazo().getMano($juego.getCantidadCartasPorMano()));
end
Como podemos ver, en el archivo juego.drl, se definen actualmente 3 reglas y una consulta (query). Cada regla delimitada por las palabras reservadas del lenguaje “rule” y “end“.
Una Regla
Cada una de estas reglas tiene un nombre asociado y dos secciones internas que definen la condición de la regla y la consecuencia que se ejecutara cuando la condición sea cierta. Como podemos apreciar las palabras reservadas “when” y “then” son utilizadas para demarcar estas secciones dentro de cada regla.
Luego de la palabra reservada “when“, expresaremos la condición que debera cumplirse para que esta regla se ejecute. Esta condición se expresa en un lenguaje especial donde las restricciones de la condición se expresan utilizando tipos de objetos y filtrando por propiedades. Este lenguaje es llamado DRL (Drools Rule Language) y es muy sencillo de aprender.
Analicemos juntos una de estas reglas:
rule "Comienza una ronda de Poker cuando hay n jugadores"
when
$juego: Juego(nombre == "Poker")
$jugadores: ArrayList( size == 2 ) from collect (Jugador())
then
$juego.setMazo(new MazoPoker());
Dealer dealer = new Dealer("Poker Dealer");
insert(dealer);
end
La Condición
Como podemos ver, la condición de esta regla especifica dos restricciones que deben cumplirse para que la consecuencia se ejecute. Analizaremos estas dos restricciones y vamos a aprovechar para hacer algunos comentarios de la sintaxis y la semántica con la que se escriben estas restricciones.
when
$juego: Juego(nombre == "Poker")
$jugadores: ArrayList( size == 2 ) from collect (Jugador())
Es importante notar, que hay dos restricciones expresadas aqui, ambas unidas por un operador AND implícito. La dos restricciones que tenemos en esta condición pueden ser expresadas de la siguiente manera en lenguaje natural:
SI…
- Hay un Juego que se llama Poker
- Y hay 2 jugadores
Entonces… Consecuencia
Por lo tanto si estas restricciones se cumplen, la consecuencia de la regla se ejecutara. La primer restricción “Hay un Juego que se llama Poker” es expresada con la siguiente linea en Drools:
Juego(nombre == "Poker")
Donde lo unico que estamos expresando aqui es que en la memoria de trabajo que Drools utiliza, tendra que haber una instancia del objecto Juego, por eso se utiliza el tipo de la clase (con la J mayúscula) y luego se hace una restriccion de valor de propiedad, en este caso, que el valor de la propiedad nombre sea igual a Poker. En Drools cada instancia de objeto que es insertada en la memoria de trabajo es tratada con el nombre de Hecho. Esto hace referencia a que cada objecto que insertemos, va a generar en Drools un hecho cierto del mundo real sobre el cual queremos hacer inferencias y deducciones.
La siguiente restricción un poco mas compleja, sin embargo, lo unico que hace es contar que hayan dos jugadores para comenzar el juego. Basicamente para esto, realiza una búsqueda en la memoria de trabajo sobre todas las instancias del objeto Jugador que hayamos insertado y cuando sean dos evalúa como verdadera.
Esta bueno notar, que como con Drools escribimos código declarativo y no imperativo, no podríamos escribir esta segunda parte de la restricción de la siguiente manera:
when
$juego: Juego(nombre == "Poker")
Jugador()
Jugador()
Debido a que aquí estaríamos expresando que por cada par de Jugadores se debería empezar un Juego. Esto causaría que si en la memoria de trabajo tuviéramos 2 instancias de objetos Jugador, la consecuencia se ejecutaría dos veces, ya que el par [Jugador 1, Jugador 2] es distinto al par [Jugador 2, Jugador 1].
Como ultima aclaración sobre las restricciones en las condiciones, vale la pena mencionar los bindeos/enlaces a variables que se estan realizando en ambas restricciones con: $juego y $jugadores. Estas variables, luego pueden ser usadas dentro de restricciones siguientes o en la consecuencia de la regla, como veremos a continuación.
La consecuencia
Pasando a la consecuencia, solamente hay que aclarar que podemos expresar cualquier código Java que queramos que se ejecute cuando las restricciones de la condición son satisfechas.
then
$juego.setMazo(new MazoPoker());
Dealer dealer = new Dealer("Poker Dealer");
insert(dealer);
Como podemos ver, hacemos uso de dos facilidades que son agregadas a la condición. La primer facilidad usada aquí es la la variable que relacionamos en la condición ($juego) y luego la función/método insert que nos deja insertar un nuevo hecho dentro de la memoria de trabajo desde la consecuencia de una regla.
Interacción y conclusión
Para ir terminando con el post, ya que se hizo muy extenso, lo falta aclarar como interactuamos con la sesión que habíamos creado en el post anterior. Si descargan el proyecto y revisan la clase App.java, veran que luego de configurar y obtener la session interactuamos con ella llamando los métodos insert y fireAllRules.
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);
ksession.insert(new Juego("Poker",2));
ksession.insert(new Jugador("Jugador 1"));
ksession.insert(new Jugador("Jugador 2"));
ksession.fireAllRules();
Espero que a grandes rasgos se entienda el post, y como podemos crear reglas que representen nuestro conocimiento para poder interactuar con el. Aparte de querer compartir los lineamientos básicos para utilizar Drools, la idea del post también es generar dudas, para poder establecer un canal de discusión. Asi que espero sus comentarios, criticas y preguntas si las dudas comienzan a surgir.
Saludos
PD: les dejo de vuelta el link del ejemplo para que puedan descargarlo sin tener que ir al post anterior: www.jbug.com.ar/external/playingWithDrools-ExpertIntroduction.zip
Drools 5.0 reviews en The Server Side.
Mayo 25, 2009
Hace tres dias ya, Mark Proctor lider del proyecto JBoss Drools publico en la famosa pagina The Server Side (http://www.theserverside.com) un articulo sobre el lanzamiento oficial de la versión 5.0 de Drools (http://www.theserverside.com/news/thread.tss?thread_id=54698). En este articulo se mencionan las características de la nueva versión, mas varios links de referencia bastante útiles. Mas alla de la nota en si, es siempre bueno ver la respuesta/feedback de la comunidad en estos sitios donde se suelen hacer este tipo de presentaciones oficiales.
Como era de esperarse, si leen los comentarios, aparecieron varias preguntas, y yo espero que aparezcan mas, sobre el solapamiento de funcionalidades con JBoss jBPM. Yo aproveche para contar mi experiencia, para ayudar a todos aquellos a los que le surgen dudas sobre estos temas, tan comunes.
Tanto yo, como el equipo de Drools, estamos a la espera de feedbacks sobre esta nueva versión para poder continuar la mejora del proyecto para el bien de la comunidad de desarrolladores open source.
Les dejo mi comentario en TSS, y espero sus feedbacks al respecto:
http://www.theserverside.com/news/thread.tss?m=c.reply&thread_id=54698#309325
Estaría bueno poder armar este tipo de discusiones en vivo y compartir experiencias con la comunidad de desarrolladores aquí en Argentina, y en latino america para ver la aceptación de herramientas como Drools que van guiando y cambiando constantemente los paradigmas de desarrollo que conocíamos. Si hay algún entusiasta leyendo, lo invito a contactarse conmigo para organizar charlas o discusiones abiertas sobre estas herramientas tan interesantes.
Saludos!
Actualización:
Agrego un link al blog oficial de los core developers de Drools que vieron mi comentarion en The Server Side y me invitaron a compartirlo tambien en su blog: http://blog.athico.com/2009/05/drools-vs-jbpm-personal-experience.html
Drools 5.0 Final Release
Mayo 20, 2009
Ayer 19 de mayo del 2009 fue publicada la versión final de Drools 5.0.1. (un regalo de cumpleaños atrasado)
Los invito a descargarla y a empezar a jugar con ella. Como veran, voy a empezar a postear ejemplos ( algunos posts utiles: post1, post2, post3, post4) que hagan uso de cada uno de sus módulos y un poco de teoría como para que la gente que no conoce el framework pueda ir metiendo mano.
Les dejo el link de la pagina actualizada:
Y el link directo para la descarga:
http://jboss.org/drools/downloads.html
Se agradecen comentarios, sobre las primeras impresiones del framework, tanto sobre mejoras como criticas constructivas para mejorar las experiencia de usuario.
Actualizacion:
Recien hoy (22 de mayo 2009) se hizo la publicación oficial. Les dejo algunos links de interes:
Home Page
http://www.jboss.org/drools
PD: grep -i “salaboy” * -R | wc -l en los source da 49! y viene mucho mas!
JBoss Drools 5.0 – www.infoworld.com
Mayo 20, 2009
Los invito a leer la nota publicada sobre los features de la nueva versión 5.0 de Drools. Es un muy buen articulo para empezar a ver todas las características que esta nueva versión nos propone.
“JBoss Drools 5.0 adds several new features, such as workflow, constraint programming, and event programming, all of which significantly boost its usefulness as a decision management toolkit.”
Para leer el articulo completo dirigirse al siguiente link:
http://www.infoworld.com/d/developer-world/first-look-jboss-drools-grows-and-out-137?page=0,0
Jugando con Drools 5.0 – #1 Drools Expert
Mayo 19, 2009
Introducción a Drools Expert
Básicamente vamos a ver un ejemplo sencillo de como Drools Expert nos permite expresar reglas de negocios, para dejar ejemplos simples de como se expresan las reglas y de las interacciones que podemos tener entre ellas.
En este post veremos solamente la estructura del proyecto, las dependencias y las lineas básicas que necesitamos para poder hacer uso del framework. En el siguiente post veremos como esta compuesto el conocimiento, nuestro modelo de objetos y que podemos hacer con el.
Por esto mismo, la idea principal de estos dos primeros posts sobre Drools Expert, es documentar y dejar un ejemplo sencillo para que la gente que no conoce el framework, pueda ir de a poco introduciendoce en cada uno de los submódulos de Drools.
En estos posts voy a utilizar la versión 5.0 del framework cuyas APIs estan orientadas al conocimiento en general. Asi es, es tan genérica como para permitirnos definir el conocimiento que tenemos en una situación de negocio en particular. Por lo tanto veran que toda la terminología que antes se usaba, como por ejemplo RuleBase o WorkingMemory (cuando estaba solamente orientado a reglas de negocio, en la version 4.0.7 o anterior), ahora estas son mucho mas genéricas y no estan tan atadas solamente a reglas, sino al concepto de conocimiento en general (Knowledge).
El Proyecto
Este ejemplo, mediante un proyecto sencillo construido con Maven, se mostraran los primeros pasos para utilizar el framework. Es importante ver el proyecto completo para comprender como interactúan las partes. Y tratar de jugar un poco con el cambiando las reglas y los hechos que se insertan para ver el comportamiento.
Sin mas vamos a ver el proyecto que utiliza Drools. Como en todo proyecto de Drools vamos a tener que incluir las dependencias a los módulos base que vamos a utilizar del proyecto.
Esto, como estamos utilizando Maven, estara descripto en el archivo pom.xml file que describe al proyecto:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wordpress.salaboy.playing.with.drools</groupId> <artifactId>playingWithDrools-ExpertIntroduction</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>playingWithDrools-ExpertIntroduction</name> <url>http://maven.apache.org</url><repositories> <repository> <id>repository.jboss.org</id> <url>http://repository.jboss.org/maven2</url> <snapshots> <enabled>false</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>5.0.0.CR1</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-api</artifactId> <version>5.0.0.CR1</version> <type>jar</type> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>5.0.0.CR1</version> <type>jar</type> </dependency> </dependencies> </project>
Algunos conceptos de Maven
Para aquellos que no estan acostumbrados a Maven es importante notar que:
- groupId: nos va a decir el grupo donde podremos encontrar nuestro proyecto construido dentro del repositorio de Maven.
- artifactId: nombre de nuestro proyecto construido.
- packaging: tipo de empaquetado, en este caso estamos generando un Jar, pero podríamos querer hacer un war, algún otro tipo de proyecto.
- version: la versión de nuestro proyecto.
- sección repositories: en esta sección se incluye el repositorio maven2 de JBoss donde estan las ultimas versiones empaquetadas de Drools. Necesitamos tener este repositorio para poder buscar las dependencias y el framework en si.
- dependencies con groupId org.drools: incluimos las dependencias a las bibliotecas core, api y compiler, ya que son necesarias para la compilación y ejecución de nuestro proyecto que hace uso del framework.
Una vez dicho esto, solo queda bajar el proyecto, descomprimirlo y recorrer su estructura (la estructura refleja un típico proyecto Maven, para un empaquetado de tipo Jar).
Conociendo las APIs básicas
Vamos a analizar el uso mas común de las APIs básicas de Drools, para esto podemos abrir la clase App.java dentro del paquete com.wordpress.salaboy.playing.with.drools, donde encontraremos las siguientes lineas dentro del método main de la clase:
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newInputStreamResource(new App().getClass().getResourceAsStream("/rules/juego.drl")),ResourceType.DRL);
Con estas dos grandes lineas de codigo, lo que estamos haciendo es mediante un KnowledgeBuilder recaudar todo el conocimiento que vamos a utilizar en nuestra aplicación para luego obtener paquetes de conocimiento ya compilado. Estos paquetes de conocimiento ya compilados se llaman KnowledgeBase, en versiones anteriores llamados RuleBase.
Collection kpkgs = kbuilder.getKnowledgePackages(); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kpkgs );
Como podemos ver, ya tenemos nuestro conocimiento compilado, ahora contra este conocimiento compilado, que llamamos KnowledgeBase podemos crear sesiones para hacer uso de este conocimiento.
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);
Como vemos, a partir de nuestra base de conocimiento se obtiene una sesion de tipo StatefulKnowledgeSession con la cual vamos a poder interactuar para obtener las deducciones que se generen a partir de nuestro conocimiento.
A continuación solamente creo un logger que nos va a ir indicando los eventos que se van generando dentro de nuestra sesión mientras interactuamos con ella. Este tipo de logger, ConsoleLogger, como su nombre lo aclara, nos mostrara por consola todos los eventos que se vayan generando.
Conclusión
Hasta aquí vimos algunos conceptos básicos de como construir un proyecto que utilice Drools y un preview con una breve explicación de como se ven las APIs que utilizaremos en el día a día si nuestra aplicación utiliza Drools.
En el siguiente post discutiremos el modelo del ejemplo y como se realizaran las ejecuciones de las reglas. Para los ansiosos, el siguiente link tiene el proyecto completo con las reglas y un Main, para probar la ejecucion.
www.jbug.com.ar/external/playingWithDrools-ExpertIntroduction.zip
Pueden bajarlo, jugar y romper tranquilos.
Lanzamiento de JBug Argentina
Mayo 5, 2009
Los invito a visitar y ser parte de esta iniciativa que intenta conformar una comunidad activa de profesionales con conocimientos en JBoss. Donde la meta es compartir intereses, gustos y conocimientos sobre las herramientas y middleware que JBoss propone.
Si ya tenes un blog o has escrito artículos sobre tecnologías propuestas por JBoss, contactate con el grupo de usuarios de JBoss y hagamos juntos crecer esta comunidad de habla hispana.

