22/07/2023
En el dinámico mundo del desarrollo de software, la capacidad de adaptar rápidamente la lógica de negocio es crucial. Las aplicaciones tradicionales a menudo encadenan los cambios de requisitos a tediosos ciclos de desarrollo y despliegue. Sin embargo, una alternativa poderosa ha surgido para transformar este paradigma: los Business Rule Management Systems (BRMS). Estos sistemas ofrecen un ecosistema completo para definir, mantener, encapsular y ejecutar reglas de negocio como entidades únicas e independientes. Dentro de este fascinante campo, Drools se erige como una solución robusta y flexible, permitiéndonos externalizar la lógica de negocio de nuestro código. Pero, ¿qué sucede cuando necesitamos que nuestras reglas interactúen con funcionalidades complejas ya existentes en nuestra aplicación o con utilidades auxiliares? Aquí es donde la integración de librerías de utilidades en Drools brilla con luz propia, brindando una sinergia perfecta entre la flexibilidad de las reglas y la potencia de nuestro código Java.

Este artículo explorará en profundidad cómo Drools, la implementación BRMS de Red Hat, nos permite no solo definir reglas de manera intuitiva, sino también cómo podemos potenciar estas reglas al integrar funciones y tipos personalizados, tanto definidos en Java como directamente en los archivos DRL. Veremos la preparación del entorno, la anatomía de una regla, los atributos que controlan su comportamiento y, lo más importante, las diversas maneras de incorporar nuestras librerías de utilidades, asegurando que el motor de reglas actúe como una verdadera 'caja negra' portable y extensible dentro de nuestra aplicación.
- ¿Qué es un BRMS y por qué Drools?
- Conceptos Fundamentales en Drools
- Preparación del Entorno con Spring Boot
- Anatomía de una Regla Drools (.drl)
- Controlando la Ejecución de Reglas: Atributos
- Aprovechando Librerías de Utilidades en las Reglas
- Organizando el Código de Reglas para la Escalabilidad
- Preguntas Frecuentes (FAQs)
- Conclusiones
¿Qué es un BRMS y por qué Drools?
Un Business Rule Management System (BRMS) es mucho más que un simple motor de reglas; es una suite completa de herramientas que facilita la gestión del conocimiento de negocio. Su principal ventaja radica en centralizar la edición de reglas, permitiendo que perfiles no técnicos participen en su definición y que los cambios se realicen de manera rápida y sencilla, sin necesidad de recompilar y redesplegar la aplicación principal. Esto se traduce en una flexibilidad inigualable y un costo de mantenimiento mínimo.
Drools, también conocido como JBoss Rules, es un motor de reglas de negocio de código abierto implementado por Red Hat. Proporciona las herramientas necesarias para la definición, compilación y ejecución de reglas. Su corazón late gracias al algoritmo de inferencia Rete, desarrollado por el Dr. Charles L. Forgy. Rete es un algoritmo de reconocimiento de patrones que, basándose en las reglas definidas y las posibles acciones inferidas, genera un árbol de decisiones. Este enfoque, aunque puede consumir más memoria, garantiza una ejecución extremadamente rápida del motor de reglas al evitar la comprobación de todas las reglas en cada ciclo de ejecución.
La suite de Red Hat BRMS se complementa con otros elementos clave como KIE Engine (Knowledge Is Everything), que engloba Drools, OptaPlanner (para optimización) y jBPM (para gestión de procesos de negocio), KIE Execution Server (un servidor centralizado para el motor de reglas accesible vía REST) y Business Central WorkBench (una herramienta web para la gestión colaborativa y versionado de reglas).
Conceptos Fundamentales en Drools
Antes de sumergirnos en la integración de utilidades, es vital comprender los conceptos básicos que rigen el funcionamiento de Drools:
- Facts: Son los argumentos de entrada al motor de reglas. Generalmente, son objetos POJO (Plain Old Java Objects) que representan el estado actual de los datos sobre los que se evaluarán las reglas.
- Rule: Es el bloque fundamental de lógica de negocio. Cada regla consta de dos partes principales:
- LHS (Left Hand Side): Aquí se definen los criterios o condiciones que deben cumplirse para que la regla se dispare. Utiliza un lenguaje declarativo para describir patrones en los Facts.
- RHS (Right Hand Side): Contiene las acciones que se ejecutarán una vez que las condiciones del LHS se hayan satisfecho. Puede modificar Facts, invocar métodos Java o realizar otras operaciones.
- WorkingMemory: Es el contexto de ejecución del motor de reglas, donde se evalúan y ejecutan las reglas. Es el runtime donde los Facts residen y son procesados.
- KnowledgeSession: Se crea dentro de la Working Memory y es la encargada de preparar la ejecución y montar el ecosistema de reglas asociadas a dicha ejecución. Puede ser stateless (para una ejecución única sin retener el estado) o stateful (para interacciones continuas donde el estado de los Facts se mantiene a lo largo de múltiples disparos de reglas).
- KnowledgeBase: Es el repositorio donde se encuentran las definiciones de las reglas. A partir de ella se construye el engine, es decir, la KnowledgeSession. Puede nutrirse de diversas fuentes, como archivos locales o repositorios remotos.
Preparación del Entorno con Spring Boot
Integrar Drools en una aplicación Spring Boot es un proceso sencillo. Necesitamos las dependencias de Drools Core y Kie-Spring para facilitar la integración con el contenedor de Spring. A continuación, un ejemplo de las dependencias Maven:
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>7.18.0.Final</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-spring</artifactId> <version>7.18.0.Final</version> </dependency>La configuración del motor de reglas en Spring Boot se realiza a través de una clase de configuración que inyecta un Bean de tipo KieContainer. Este contenedor encapsula todos los elementos necesarios (KnowledgeBase, configuración de Working Memory, etc.) y proporciona una API sencilla para interactuar con ellos:
@Configuration public class BPMConfigurations { private static final String[] drlFiles = { "rules/discountRules.drl" }; @Bean public KieContainer kieContainer() { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); for (String ruleFile: drlFiles) { kieFileSystem.write(ResourceFactory.newClassPathResource(ruleFile)); } KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem); kieBuilder.buildAll(); KieModule kieModule = kieBuilder.getKieModule(); return kieServices.newKieContainer(kieModule.getReleaseId()); } }Con el KieContainer en el contexto de Spring, podemos crear una KieSession en nuestro servicio para insertar Facts y disparar las reglas:
@Service public class PriceCalculatorService { @Autowired private KieContainer kieContainer; public void executeRules(ProductPrice productPrice) { KieSession kieSession = kieContainer.newKieSession(); kieSession.insert(productPrice); kieSession.fireAllRules(); kieSession.dispose(); } }Anatomía de una Regla Drools (.drl)
Las reglas de Drools se definen en archivos con extensión .drl (Drools Rule Language) o, para perfiles no técnicos, en hojas de cálculo Excel (Decision Tables). Un archivo .drl básico tiene la siguiente estructura:
package myAppRules; import com.dppware.droolsDemo.bean.*; dialect "mvel" rule "Adjust Product Price" when $p: ProductPrice(basePrice > 2 ) then System.out.println("EJECUTANDO -Adjust Product Price- para el producto [" + $p + "]"); endpackage: Agrupación lógica de reglas, funcionando como un namespace. Los nombres de las reglas deben ser únicos dentro de un paquete.import: Importa definiciones de clases Java necesarias para la compilación y ejecución de las reglas. Por defecto,java.lang.*siempre está importado.dialect: Define el lenguaje utilizado dentro de las reglas. Los más comunes son:"mvel": MVFLEX Expression Language. Un lenguaje declarativo sencillo y legible, con sintaxis similar a Java, ideal para el LHS y operaciones simples en el RHS."java": Permite incluir sintaxis Java pura, aunque su uso está restringido principalmente al RHS (la secciónthen).
rule "Nombre de la Regla" ... end: Define el bloque de una regla individual.when(LHS): Contiene las condiciones. Puede incluir operadores lógicos (>,<,>=,<=,==,||,&&,contains,matches, etc.) y la cláusulaeval()para condiciones booleanas más complejas o la invocación de métodos externos.then(RHS): Contiene las acciones a ejecutar. Para modificar un Fact existente, se utiliza el bloquemodify().
Ejemplo de modificación de un Fact:
rule "Adjust Product Price" when $p: ProductPrice(basePrice > 2 ) then modify($p){ setBasePrice($p.basePrice - 5); } System.out.println("el precio ajustado es " + $p.basePrice); endControlando la Ejecución de Reglas: Atributos
Drools ofrece atributos de regla para controlar su comportamiento en tiempo de ejecución. Se definen justo después del nombre de la regla:
no-loop: Este atributo previene que una regla se dispare repetidamente si modifica un Fact que la vuelve a activar. Es fundamental para evitar bucles infinitos. Si una regla modifica un Fact en su RHS y esa modificación hace que el LHS de la misma regla se cumpla de nuevo, sinno-loop, la regla se ejecutaría indefinidamente hasta que la condición ya no se cumpla.salience: Permite establecer la prioridad de ejecución de las reglas. Por defecto, Drools ejecuta las reglas en el orden en que las encuentra en el archivo DRL. Un valor de salience más alto indica mayor prioridad (ej:salience 10se ejecuta antes quesalience 5). Los valores pueden ser negativos para indicar baja prioridad.agenda-group/auto-focus: Permite agrupar reglas lógicamente. Solo las reglas delagenda-groupque tiene el foco se evaluarán y ejecutarán. Esto es útil para controlar grandes conjuntos de reglas, activando solo subconjuntos relevantes en un momento dado. Se establece el foco programáticamente desde Java conkieSession.getAgenda().getAgendaGroup("GroupName").setFocus();.date-effective/date-expires: Condicionan la ejecución de una regla a un rango de fechas. La regla solo se activará si la fecha actual cae dentro del período especificado.calendars/timer: Para acciones temporales más avanzadas.calendarspermite integrar calendarios personalizados (ej: solo días de semana), mientras quetimerpermite definir reglas que se disparan en intervalos de tiempo o después de un retardo específico.
Aprovechando Librerías de Utilidades en las Reglas
La verdadera potencia de Drools reside en su capacidad de interactuar con el código Java existente y de definir nuevas funcionalidades directamente en DRL. Esto permite a los desarrolladores y expertos de negocio colaborar de manera más efectiva.
1. Importando Funciones Estáticas de Java (`import function`)
Si ya tienes una clase Java con métodos de utilidad (por ejemplo, para formatear cadenas, realizar cálculos complejos o interactuar con servicios externos) y quieres usarlos dentro de tus reglas, puedes importarlos directamente. El método debe ser static y public.
Clase Java de utilidad (Utils.java):
public class Utils { public static void prettyTraces(Object message) { System.out.println("PrettyTraces -> *"+message+"*"); } }Uso en el archivo .drl:
import function com.dppware.droolsDemo.utils.Utils.prettyTraces; rule "Example Rule with Imported Function" when $p: ProductPrice(basePrice > 0) then prettyTraces("El precio base es: " + $p.basePrice); endEsto permite reutilizar la lógica de negocio ya implementada en Java sin tener que reescribirla en DRL.
2. Definiendo Funciones Directamente en DRL (`function`)
Para lógica auxiliar específica de las reglas, o para evitar dependencias con clases Java pequeñas, puedes definir funciones directamente dentro de tu archivo .drl. Estas funciones estarán disponibles en todo el package (namespace) donde se definen.
package myAppRules; function Integer calculateIncrement(Integer value, int quantity) { return value + quantity; } rule "Adjust Product Price" when $p: ProductPrice(basePrice > 2 ) then modify($p){ setBasePrice($p.basePrice - 5); } System.out.println("El precio ajustado es " + $p.basePrice); System.out.println("Precio incrementado: " + calculateIncrement($p.basePrice, 3)); endEsto es útil para encapsular pequeños fragmentos de lógica que son específicos del dominio de las reglas y no necesariamente forman parte de la lógica de negocio principal de la aplicación Java.
3. Definiendo Nuevos Tipos (Clases) en DRL (`declare type`)
Drools permite la declaración de nuevas clases directamente en el archivo .drl. El compilador de Drools generará estas clases en tiempo de ejecución, haciéndolas disponibles para su instanciación y uso dentro de las reglas. Por defecto, se generarán getters, setters, toString, equals y hashCode.
package myAppRules; declare Product code: int name: String description: String end rule "Create and Print Product" when // No conditions needed for this example then Product pro = new Product(); pro.setCode(3321); pro.setName("Leche"); pro.setDescription("Rica en Calcio"); System.out.println(pro); endEsta característica es particularmente útil cuando necesitas estructuras de datos temporales o específicas para las reglas que no justifican la creación de una clase Java completa o cuando quieres mantener la definición de datos cerca de la lógica que los utiliza dentro del ecosistema de reglas.

4. Importando Objetos Java Instanciados (`globals`)
Una de las formas más poderosas de integrar Drools con tu aplicación es inyectar objetos ya instanciados desde tu contexto Java (como servicios de Spring, DAOs, o cualquier otro Bean) directamente en la KieSession. Estos objetos se conocen como globals y están disponibles para todas las reglas dentro de esa sesión.
Primero, define un servicio Java que quieres inyectar:
@Service public class PushSubService { public void publishNewProductCreated(Object o) throws JsonProcessingException { // Logic to publish to a topic, save to DB, etc. System.out.println("Publishing newProduct Topic, content ["+ new ObjectMapper().writeValueAsString(o) +"]"); } }Luego, inyecta este servicio en tu PriceCalculatorService y pásalo como un global a la KieSession antes de disparar las reglas:
@Service public class PriceCalculatorService { @Autowired private KieContainer kieContainer; @Autowired private PushSubService pushSubService; // Inyecta el servicio public void executeRules(ProductPrice productPrice) { KieSession kieSession = kieContainer.newKieSession(); kieSession.setGlobal("publishTool", pushSubService); // Añade el servicio como global kieSession.insert(productPrice); kieSession.fireAllRules(); kieSession.dispose(); } }Finalmente, declara el global en tu archivo .drl y úsalo en el RHS de tus reglas:
package myAppRules; global com.dppware.droolsDemo.services.PushSubService publishTool; rule "Publish Product Notification" when $p: Product(code > 0) then publishTool.publishNewProductCreated($p); endEsta capacidad es extraordinariamente útil para permitir que las reglas interactúen con la infraestructura de tu aplicación, como bases de datos, sistemas de mensajería, o cualquier otro servicio sin acoplar la lógica de negocio directamente a ellos en el código Java.
Organizando el Código de Reglas para la Escalabilidad
A medida que el número y la complejidad de las reglas crecen, un único archivo .drl puede volverse inmanejable. La solución es organizar las definiciones de tipos, funciones y reglas en múltiples archivos .drl, manteniendo el mismo package (namespace) en sus cabeceras. De esta manera, todas las definiciones seguirán estando disponibles globalmente dentro de ese paquete lógico.
Por ejemplo, podrías tener:
types.drl: Contiene todas las declaracionesdeclare type.functions.drl: Contiene todas las definicionesfunction.business_rules.drl: Contiene las reglas de negocio principales.discount_rules.drl: Contiene reglas específicas de descuentos.
Todos estos archivos empezarían con package myAppRules; y serían cargados por el KieContainer, permitiendo una estructura modular y mantenible.
Preguntas Frecuentes (FAQs)
¿Qué es Drools y para qué se utiliza?
Drools es un motor de reglas de negocio (Business Rule Engine) que forma parte de la suite BRMS de Red Hat. Se utiliza para externalizar la lógica de negocio de las aplicaciones, permitiendo que las reglas sean definidas, gestionadas y modificadas de forma independiente al código fuente, lo que mejora la flexibilidad, la agilidad y reduce los ciclos de desarrollo.
¿Por qué debería usar un BRMS como Drools en mi aplicación?
El uso de un BRMS ofrece múltiples ventajas: centraliza la lógica de negocio, permite a usuarios no técnicos participar en la definición de reglas, facilita cambios rápidos sin redespliegues de código, mejora la auditabilidad de las decisiones y desacopla la lógica de negocio del código de la aplicación, haciéndola más modular y mantenible.
¿Cómo se organiza el código de reglas en Drools?
Las reglas en Drools se organizan en archivos .drl. Para proyectos grandes, se recomienda usar la misma declaración de package (namespace) en múltiples archivos .drl, dedicando cada archivo a un tipo específico de definición (ej: tipos de datos, funciones de utilidad, reglas de negocio específicas) para mantener la modularidad y legibilidad.
¿Puedo usar mi lógica de negocio Java existente dentro de las reglas de Drools?
Sí, absolutamente. Drools permite invocar métodos estáticos de clases Java mediante la declaración import function, así como inyectar instancias de objetos Java (como servicios o DAOs de Spring) en el contexto de la sesión de reglas a través de globals. Esto asegura una integración fluida con tu aplicación Java.
¿Qué es un 'Fact' en Drools?
Un 'Fact' en Drools es un objeto de datos (generalmente un POJO Java) que se inserta en la memoria de trabajo del motor de reglas. Las reglas evalúan las condiciones basándose en los atributos de estos Facts y pueden modificarlos o generar nuevas acciones a partir de ellos.
Conclusiones
Drools se revela como una herramienta indispensable para cualquier proyecto que requiera flexibilidad y agilidad en la gestión de su lógica de negocio. Hemos explorado no solo los fundamentos de su funcionamiento y la estructura de sus reglas, sino también las potentes capacidades de integración que ofrece. La habilidad de importar funciones Java, definir funciones y tipos directamente en DRL, e inyectar objetos de servicio como 'globals' transforma a Drools en una 'caja negra' verdaderamente extensible, capaz de interactuar con cualquier parte de tu aplicación. Esta sinergia entre la lógica declarativa de las reglas y el poder de tu código Java te permitirá construir sistemas más robustos, fáciles de mantener y, lo más importante, adaptables a los constantes cambios del entorno empresarial. La externalización de la lógica de negocio con Drools es más que una práctica; es una estrategia clave para el desarrollo de software moderno.
Si quieres conocer otros artículos parecidos a Drools: Integrando Librerías de Utilidades en Reglas puedes visitar la categoría Librerías.
