Dejo la presentación de una charla que estoy dando de introducción a SOA y BPM
miércoles, 7 de julio de 2010
sábado, 29 de mayo de 2010
JBoss Seam
En estos momentos me toca trabajar con este de JBoss, y debo decir que le tenía cierta desconfianza y lo prejuzgue anticipadamente.
Luego de participar en una presentación de Gavin King hace un par de años sobre este framework me había quedado la idea de que era poco flexible y apuntaba a resolver la problematica común de las aplicaciones web desde la perspectiva de JSF/EJB/JPA haciendolo así un fullstack framework.
Justamente por lo recien mencionado, me quedo la idea de que JBoss Seam, era solo JSF, EJBs como BackingBean que usan JPA directamente, lo cual no me parecia mal para aplicaciones simples y/o pequeñas, pero para grandes sistemas web no me cerraba sobre todo por el hecho de las capas, en este sentido Seam según mi visión en aquel momento, tenia 2 capas, la vista (con JSF components) o el negocio (EJB como backing beans) cerrando así la posibilidad de tener independencia entre las capas (presentación, negocio, persitencia, integración).
Definitivamente, ahora veo que tenía un pre concepto erróneo de lo que realmente es Seam principalmente porque uno de los features principales de Seam es la flexibilidad.
Encontre en JBoss Seam un framework que resuelve los problemas típicos de las aplicaciones web en una manera simple como por ejemplo:
i18n: Usando .properties
navegación: Usando un mecanismo que extiende al mecanismo de navegación estandar de JSF y que provee muchas mas opciones, como ser condiciones. También soporta pageflows usando un proceso jBPM.
contextos: además de los contextos clásicos agrega contextos muy utilies sobre todo el contexto CONVERSATION.
Manejo de excepciones y paginas de error: Facilita la administración de las excepciones y provee opciones de configuración para las páginas de error de la aplicación.
Manejo de mensajes: Facilita el manejo de mensajes por medio de extensiones al FacesMessage de JSF e inyección del mismo.
Validaciones: Usando Hibernate-Validator
Exportación a varios formatos.
Templating y layout de páginas: Usando Facelets.
Como features que me encontre con los siguientes:
Fuertemente basado en anotaciones (adiós XMLs gigantes) con una gran cantidad de las mismas que permiten configuraciones de las mas variadas.
Gran cantidad de tipos de componentes: Interceptores, Beans, Logger, manejadores de eventos, FacesMessages, IdentityStore, etc.
Bijection: Permite la clásica inyección y agrega la outyección (publicando en algún contexto por ejemplo) de objetos.
Componentes visuales: Permite utilizar frameworks de componentes visuales como RichFaces o ICEFaces. También provee tags especializados que facilitan muchas tareas.
JPA: integración directa con JPA. Inyección del EntityManager.
Seguridad: Presenta un modelo de autenticación y autorización completo basado en clases y anotaciones. Extensible usando componentes Seam.
SpringFramework: Integración con Spring permitiendo inyectar en componentes Seam Spring-beans y definir Spring-beans como componentes Seam
Otros features que no estoy usando: email, caching, remoting
Luego de ver todos estos beneficios y ventajas de usar JBoss Seam, debo concluir en que estaba completamente equivocado sobre todo por la flexibilidad dado que en la implementación del proyecto podríamos haber usado Seam de diferentes maneras:
1. Tal cual lo vi hace año: JSF/RichFaces + EJB (como BackingBeans) + JPA.
2. Usando las mismas tecnologías pero separandolas en capas: JSF/RichFaces + Seam components (presentación) + EJB (negocio) + EJB/DAO + JPA (persistencia).
3. o finalmente como lo implementamos usando JSF/Facelets/Richfaces como componentes para construir las interfaces de usuario (*.xhtml) haciendo un fuerte uso de AJAX, luego componentes Seam (clases simplemente anotadas con @Name) para implementar la lógica de presentación a las cuales se les inyecta un servicio de negocio implementado y configurado con Spring Framework. A su vez Spring tiene otros componentes configurados dentro de su container como ser los Repositories que nos abstraen del acceso a los datos, que en nuestro caso son implementaciones que utilizar Hibernate. Las clases de dominio se mapean al modelo relacional usando anotaciones JPA (y alguna que otra extension de Hibernate-Annotations).
Para concluir podría decir que Seam provee una framework interesante y simple para llevar adelante desarrollos de aplicaciones web en gran escala y desde mi (nuevo) punto de vista podría decir que es mi primera elección (a otro frameworks que he usado como ser SpringMVC, Struts o Wicket) a la hora de comenzar con un nuevo desarrollo web en Java.
Luego de participar en una presentación de Gavin King hace un par de años sobre este framework me había quedado la idea de que era poco flexible y apuntaba a resolver la problematica común de las aplicaciones web desde la perspectiva de JSF/EJB/JPA haciendolo así un fullstack framework.
Justamente por lo recien mencionado, me quedo la idea de que JBoss Seam, era solo JSF, EJBs como BackingBean que usan JPA directamente, lo cual no me parecia mal para aplicaciones simples y/o pequeñas, pero para grandes sistemas web no me cerraba sobre todo por el hecho de las capas, en este sentido Seam según mi visión en aquel momento, tenia 2 capas, la vista (con JSF components) o el negocio (EJB como backing beans) cerrando así la posibilidad de tener independencia entre las capas (presentación, negocio, persitencia, integración).
Definitivamente, ahora veo que tenía un pre concepto erróneo de lo que realmente es Seam principalmente porque uno de los features principales de Seam es la flexibilidad.
Encontre en JBoss Seam un framework que resuelve los problemas típicos de las aplicaciones web en una manera simple como por ejemplo:
Como features que me encontre con los siguientes:
Luego de ver todos estos beneficios y ventajas de usar JBoss Seam, debo concluir en que estaba completamente equivocado sobre todo por la flexibilidad dado que en la implementación del proyecto podríamos haber usado Seam de diferentes maneras:
1. Tal cual lo vi hace año: JSF/RichFaces + EJB (como BackingBeans) + JPA.
2. Usando las mismas tecnologías pero separandolas en capas: JSF/RichFaces + Seam components (presentación) + EJB (negocio) + EJB/DAO + JPA (persistencia).
3. o finalmente como lo implementamos usando JSF/Facelets/Richfaces como componentes para construir las interfaces de usuario (*.xhtml) haciendo un fuerte uso de AJAX, luego componentes Seam (clases simplemente anotadas con @Name) para implementar la lógica de presentación a las cuales se les inyecta un servicio de negocio implementado y configurado con Spring Framework. A su vez Spring tiene otros componentes configurados dentro de su container como ser los Repositories que nos abstraen del acceso a los datos, que en nuestro caso son implementaciones que utilizar Hibernate. Las clases de dominio se mapean al modelo relacional usando anotaciones JPA (y alguna que otra extension de Hibernate-Annotations).
Para concluir podría decir que Seam provee una framework interesante y simple para llevar adelante desarrollos de aplicaciones web en gran escala y desde mi (nuevo) punto de vista podría decir que es mi primera elección (a otro frameworks que he usado como ser SpringMVC, Struts o Wicket) a la hora de comenzar con un nuevo desarrollo web en Java.
martes, 30 de marzo de 2010
Vista Contextual y Diagrama conceptual
La vista contextual de una arquitectura de software es una de las primeras vistas que debe ser creada y se basa en información suministrada por el área de ingeniería de requerimientos o de alguna otra área que pueda realizar una descripción del sistema en alto nivel.
Este vista es la encargada de mostrar el sistema, las entidades externas con las cuales el sistema interactua (junto con sus interfaces) y las interfaces que el sistema presenta a dichas entidades externas. El objetivo es crear una única vista en donde se pueda capturar el sistemas y todas las entidades externas con sus interfaces.
Este vista puede ser usada como revisión de diseño de alto nivel del sistema, para iniciar el entendimiento de los subsistemas y capturar sus interfaces, para entrenamiento inicial del equipo o para comunicar los limites y las interfaces externas del sistema. Esta vista es útil también para iniciar discusiones dentro del equipo de arquitectura, diseño y desarrollo como así también con grupos externos que proveen o implementan las mencionadas interfaces externas.
Por otro lado puede ser necesario tener que comunicar los elementos del sistema y sus relaciones con sistemas externos en una forma no técnica o menos formal a otras áreas de la organización. Para ellos podemos utilizar un diagrama conceptual que muestra los diversos aspectos de un sistema de manera menos formal.
Este diagrama puede ser usado para comunicar la organización del sistema a áreas involucradas que no estén familiarizadas con diagramas UML (preferentemente equipos externos no relacionados con el desarrollo del sistema).
Básicamente, ambos intentan expresar y comunicar la misma idea solo que uno es parte de la descripción de la arquitectura y será utilizado para crear otras vistas de la arquitectura y el otro no.
Este vista es la encargada de mostrar el sistema, las entidades externas con las cuales el sistema interactua (junto con sus interfaces) y las interfaces que el sistema presenta a dichas entidades externas. El objetivo es crear una única vista en donde se pueda capturar el sistemas y todas las entidades externas con sus interfaces.
Este vista puede ser usada como revisión de diseño de alto nivel del sistema, para iniciar el entendimiento de los subsistemas y capturar sus interfaces, para entrenamiento inicial del equipo o para comunicar los limites y las interfaces externas del sistema. Esta vista es útil también para iniciar discusiones dentro del equipo de arquitectura, diseño y desarrollo como así también con grupos externos que proveen o implementan las mencionadas interfaces externas.
Por otro lado puede ser necesario tener que comunicar los elementos del sistema y sus relaciones con sistemas externos en una forma no técnica o menos formal a otras áreas de la organización. Para ellos podemos utilizar un diagrama conceptual que muestra los diversos aspectos de un sistema de manera menos formal.
Este diagrama puede ser usado para comunicar la organización del sistema a áreas involucradas que no estén familiarizadas con diagramas UML (preferentemente equipos externos no relacionados con el desarrollo del sistema).
Básicamente, ambos intentan expresar y comunicar la misma idea solo que uno es parte de la descripción de la arquitectura y será utilizado para crear otras vistas de la arquitectura y el otro no.
jueves, 4 de febrero de 2010
Arquitectura de Software. Definiciones
El término "Arquitectura de software" esta ampliamente difundido pero no siempre correctamente definido. Lo mismo sucede con muchos otros términos asociados a la arquitectura de software. Aquí se presentan algunas definiciones de estos términos a fin de aclarar un poco el panorama:
Según IEEE 1471:
Arquitectura: Es la organización fundamental de un sistema comprendido en sus componentes, en las relaciones entre ellos y con el ambiente, y los principio que guían su diseño y evolución.
Descripcion de arquitectura: Es un conjunto de productos que documentan la arquitectura.
Vista de arquitectura: Es la representación de un sistema o parte de un sistema desde una perspectiva en particular.
"Viewpoint" arquitectural: Es un template que describe como crear y usar una vista de arquitectura. Una vista es el resultado de aplicar una viewpoint a un sistema en particular.
System Architecture: Es un conjunto de entidades, sus propiedades y relaciones entre ellas, que definen la estructura de un sistema.
Software Architecture: Es un conjunto de componentes de software, subsistemas, relaciones, interacciones y propiedades de cada uno de estos elementos, y un conjunto de principios que constituyen las propiedades y limitaciones fundamentales de un sistema de software.
Software architecting: Refiere al análisis, diseño, documentación, revisión, aprobación, y otras actividades relacionadas con la definición y management de una arquitectura de software.
Arquitectura de Referencia: Refiere a una definición de una arquitectura para un dominio en particular. Describe en alto nivel un conjunto de elementos involucrados en aplicaciones pertenecientes al dominio. Estos elementos deben intencionalmente ser dejados en alto nivel para poder aplicar a un gran número de sistemas. Las arquitecturas de referencia ahorran mucho tiempo de trabajo de arquitectos de software durante el diseño de una nueva aplicación del mismo dominio, además de proveer un lenguaje común entre arquitectos y desarrolladores, lo cual facilita la comunicación.
Atributos de la arquitectura de software.
Cultural adaptability: Soporte a múltiples lenguajes y culturas
Security: Previene accesos no autorizados
Data integrity: El sistema no corrompe datos ni suministra datos inconsistentes.
Maintainability:
Testability: ¿El software puede ser testeado eficientemente?
Usability: Es la medida de eficacia para la interface humana del software
Operational:
Performance
Safety: El sistema no crea riesgos en el mundo real.
Según IEEE 1471:
Arquitectura: Es la organización fundamental de un sistema comprendido en sus componentes, en las relaciones entre ellos y con el ambiente, y los principio que guían su diseño y evolución.
Descripcion de arquitectura: Es un conjunto de productos que documentan la arquitectura.
Vista de arquitectura: Es la representación de un sistema o parte de un sistema desde una perspectiva en particular.
"Viewpoint" arquitectural: Es un template que describe como crear y usar una vista de arquitectura. Una vista es el resultado de aplicar una viewpoint a un sistema en particular.
System Architecture: Es un conjunto de entidades, sus propiedades y relaciones entre ellas, que definen la estructura de un sistema.
Software Architecture: Es un conjunto de componentes de software, subsistemas, relaciones, interacciones y propiedades de cada uno de estos elementos, y un conjunto de principios que constituyen las propiedades y limitaciones fundamentales de un sistema de software.
Software architecting: Refiere al análisis, diseño, documentación, revisión, aprobación, y otras actividades relacionadas con la definición y management de una arquitectura de software.
Arquitectura de Referencia: Refiere a una definición de una arquitectura para un dominio en particular. Describe en alto nivel un conjunto de elementos involucrados en aplicaciones pertenecientes al dominio. Estos elementos deben intencionalmente ser dejados en alto nivel para poder aplicar a un gran número de sistemas. Las arquitecturas de referencia ahorran mucho tiempo de trabajo de arquitectos de software durante el diseño de una nueva aplicación del mismo dominio, además de proveer un lenguaje común entre arquitectos y desarrolladores, lo cual facilita la comunicación.
Atributos de la arquitectura de software.
- Portability: ¿Puede el software ser portado a otras plataformas?
- Changeability: Habilidad para agregar nuevas funciones y modificar funcionalidad existente
- Fragility: pequeños cambios tienden a romper funcionalidad existentes
- Rigidity: el software es difícil de modificar incluso cambios simples.
- Duplication: el software con duplicación es mas difícil de mantener porque es grande y porque el cambio no es localizado.
- Understandability: ¿Puede el software ser entendido de manera que sea facil realizar cambios?
- Debugging: ¿El software soporta debugging?
- Availability: Porcentaje de tiempo en el que el sistema esta funcionando.
- Manageability: Habilidad para inspeccionar y manejar componentes en ejecución
- Upgradeability: ¿Puede el software ser actualizado mientras ejecuta?
- Reliability: Habilidad para ejecutar funciones requeridas en un periodo de tiempo especificado.
- Recoverability: Tiempo requerido para recuperarse de una falla.
- Response: ¿Es la respuesta suficientemente rápida para escenarios de uso normal y extremo?
- Scalability: La capacidad del sistema puede ser incrementada si es necesario?
- Capacity/Throughput: Manejar grandes cargas y aún mantener la respuesta
martes, 20 de octubre de 2009
Pasar un Array a un Stored Procedure en Oracle
Durante estos días tuve que hacer la prueba de pasar un array como parámetro a un Stored Procedure en un Oracle 8i desde Java. Al principio pense que era una tarea simple, pero luego encontre que no es tan así dado que me tope con 3 problemas que trataré de describir aquí.
Pero primero dejo dos URL que tienen información de como hacer esto:
* Muy buen foro
* Documentación Oficial de Oracle
Como mencione, al principio pense que usando JDBC podría lograr esto sin tener problemas pero me encontre con algunas limitaciones de JDBC y el tratamiento de los Array, así que tuve que trabajar directamente usando clases propietarias de Oracle. Quedando un código:
Ya en la base de datos, primero declaré el tipo de dato ARRAY que use para la prueba (un ARRAY de VARCHAR). Aquí tenia dos opciones, o bien declararlo dentro del package donde iba a tener mi SP o a nivel del schema.
Opte por la primer opción y enseguida me encontre con el sigueinte error:
Basicamente, no me encontraba el tipo de dato declarado.:
Buscando la solución encontré 2 soluciones posibles, una (la mas simple) es declarar el tipo de datos a nivel del esquema y la otra es crear un sinónimo publico para el tipo (T_LISTAVARCHAR2) con los accesos y permisos correspondientes al usuario que intente acceder.
Una vez solucionado este problema, me encontre por un par de errores de NoClassDefFoundError por falta de algunos JARs. Para solucionarlo además de classes12.jar puse en mi classpath: nls_charset12.jar
Además aquí dejo otro link con información valiosa sobre los jar a colocar en nuestro classpath.
La verdad que no fue complicado, pero tampoco fue tan simple como esperaba.
Pero primero dejo dos URL que tienen información de como hacer esto:
* Muy buen foro
* Documentación Oficial de Oracle
Como mencione, al principio pense que usando JDBC podría lograr esto sin tener problemas pero me encontre con algunas limitaciones de JDBC y el tratamiento de los Array, así que tuve que trabajar directamente usando clases propietarias de Oracle. Quedando un código:
DriverManager.registerDriver(new OracleDriver());
String url = "jdbc:oracle:thin:@10.65.72.52:1521:BNPAIS";
Connection conn = DriverManager.getConnection(url, "*******", "*******");
String[] array = {"hola", "mundo"};
ArrayDescriptor descriptor =
ArrayDescriptor.createDescriptor( "T_LISTAVARCHAR2", conn );
ARRAY array_to_pass =
new ARRAY( descriptor, conn, array);
CallableStatement ps = conn.prepareCall("{call TEST.TEST_ARRAY(?,?)}");
ps.setArray(1, array_to_pass);
ps.registerOutParameter(2, OracleTypes.VARCHAR);
ps.execute();
System.out.println( ps.getString(2) );
conn.close();
Ya en la base de datos, primero declaré el tipo de dato ARRAY que use para la prueba (un ARRAY de VARCHAR). Aquí tenia dos opciones, o bien declararlo dentro del package donde iba a tener mi SP o a nivel del schema.
CREATE OR REPLACE TYPE t_listavarchar2 IS TABLE OF varchar2(300)
Opte por la primer opción y enseguida me encontre con el sigueinte error:
java.sql.SQLException: invalid name pattern:
Basicamente, no me encontraba el tipo de dato declarado.:
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor( "T_LISTAVARCHAR2", conn );
Buscando la solución encontré 2 soluciones posibles, una (la mas simple) es declarar el tipo de datos a nivel del esquema y la otra es crear un sinónimo publico para el tipo (T_LISTAVARCHAR2) con los accesos y permisos correspondientes al usuario que intente acceder.
Una vez solucionado este problema, me encontre por un par de errores de NoClassDefFoundError por falta de algunos JARs. Para solucionarlo además de classes12.jar puse en mi classpath: nls_charset12.jar
Además aquí dejo otro link con información valiosa sobre los jar a colocar en nuestro classpath.
La verdad que no fue complicado, pero tampoco fue tan simple como esperaba.
lunes, 5 de octubre de 2009
Typical Web Architecture.
In computer security, a demilitarized zone, named after the military usage of the term and normally abbreviated to DMZ; also known as a Data Management Zone or Demarcation Zone or Perimeter Network, is a physical or logical subnetwork that contains and exposes an organization's external services to a larger, untrusted network, usually the Internet. The purpose of a DMZ is to add an additional layer of security to an organization's Local Area Network (LAN); an external attacker only has access to equipment in the DMZ, rather than the whole of the network.
See more: DMZ - Wikipedia
A DMZ is typically used to locate servers that need to be accessed from outside, like e-mail servers, Web and DNS.
Here is a Dual firewalls DMZ typical for enterprise web applications:

Typically, the DMZ is located between two firewalls and connects these.
The first firewall (also called the "front-end" firewall) must be configured to allow both traffic destined both to the DMZ as well as to the internal network. The second firewall (also called "back-end" firewall) allows only traffic from the DMZ to the internal network. The first firewall handles a much larger amount of traffic than the second firewall.
The application server and database are protected with this schema
See more: DMZ - Wikipedia
A DMZ is typically used to locate servers that need to be accessed from outside, like e-mail servers, Web and DNS.
Here is a Dual firewalls DMZ typical for enterprise web applications:

Typically, the DMZ is located between two firewalls and connects these.
The first firewall (also called the "front-end" firewall) must be configured to allow both traffic destined both to the DMZ as well as to the internal network. The second firewall (also called "back-end" firewall) allows only traffic from the DMZ to the internal network. The first firewall handles a much larger amount of traffic than the second firewall.
The application server and database are protected with this schema
viernes, 20 de abril de 2007
OT-Rules
Execute business validations using OT Rules
Abstract
OT Rules is a simple rule engine that focuses on execution, validation and business rules composition. One of the main advantages of using OT Rules is that you can define business validations and keep them isolated from business logic so you can add, remove, change or compose these rules and new rules in a simple, flexible way without affecting the business logic. In this article, we will apply these validations, enable, disable and reuse them in different methods and add new validations without changing the business logic methods.
How to create a rule.
Rule creation is a simple process, you just have to create a new class that implements or extends some of the following interfaces or classes:
#
net.sf.opentranquera.rules.Rule: Base Interface for all the rules.#
net.sf.opentranquera.rules.BusinessRule: Business rule specific Interface#
net.sf.opentranquera.rules.CompositeRule: Composite rule specific Interface#
net.sf.opentranquera.rules.AbstractRule: Can be used in different rule types#
net.sf.opentranquera.rules.AbstractBusinessRule: Useful for creating business rules# Extend some of the existing rules in OT Rules so enhancing its behavior.
In our example, we will extend
net.sf.opentranquera.rules.AbstractBusinessRule in order to create different business validation rules.Example application
Let's consider that we have to develop an application that makes an electronic fund transfer between different accounts. We can identify several services:
# Fund transfer from one account to other
# Get the balance of an existing account.
We can identify here business validations that have to be considered when executing these services, for instance, when we are executing an electronic fund transfer or when we get an account balance we must validate that the accounts are valid or exist. To implement these validations, we are going to use OT Rules because:
* Validations can change without changing the business logic
* We could require to disable the validations in some particular environments
* We could add new rules as the business change or evolve
* We need flexibility to compose validations
* We need to reuse the business validation along the project and not rewrite code.
Note: in our example, for simplicity sake, we are going to use an in-memory java.util.Map . the configuration of the example application will be based on SpringFramework.
Creating the rules.
We have identified the following business rules:
# DifferentAccountsRule: checks that both accounts source and destination are different.
# AccountsExistsRule: Validates that both accounts exist. Uses AccountExistsRule to check each account.
This is the rules source code:
public class DifferentAccountRule extends AbstractBusinessRule {
/*
* @see net.sf.opentranquera.rules.Rule#evaluate()
*/
public RuleResult evaluate() {
Transfer transfer = (Transfer) this.getEvaluatedObject();
if( transfer.getCreditAccount().equals(transfer.getDebitAccount()) )
return this.getError("The accounts are equal");
return this.getSuccess();
}
}
public class AccountsExistsRule extends AbstractBusinessRule {
private BusinessRule rule;
/*
* @see net.sf.opentranquera.rules.Rule#evaluate()
*/
public RuleResult evaluate() {
Transfer transfer = (Transfer) this.getEvaluatedObject();
AbstractCompositeRuleResult result = new AbstractCompositeRuleResult(true) {
};
this.rule.setEvaluatedObject(transfer.getDebitAccount());
RuleResult r1 = this.rule.evaluate();
this.rule.setEvaluatedObject(transfer.getCreditAccount());
RuleResult r2 = this.rule.evaluate();
result.addResult( r1 );
result.addResult( r2 );
result.setSuccessful(r1.isSuccessful() && r2.isSuccessful());
return result;
}
public void setRule(BusinessRule rule) {
this.rule = rule;
}
}
public class AccountExistsRule extends AbstractBusinessRule {
private AccountDao dao;
/*
* @see net.sf.opentranquera.rules.Rule#evaluate()
*/
public RuleResult evaluate() {
String account = (String)this.getEvaluatedObject();
// Verify that the account exists.
if(this.dao.getAccount(account) == null)
return super.getError("The account " + account + "does not exist.");
return this.getSuccess();
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
}
Now, we have to configure the rules and the service being used, in this example, SpringFramework (there is also another configuration format using XML, provided out-of-the-box by OT Rules):
<bean id="service" class="net.sf.opentranquera.samples.rules.TransferServiceImpl">
<property name="evaluator" ref="ruleEvaluator"/>
</bean>
<bean id="ruleEvaluator" class="net.sf.opentranquera.rules.RuleEvaluator">
<property name="rules">
<map>
<entry key="transfer"><ref local="transferRule"/></entry>
<entry key="balance"><ref local="accountExistsRule"/></entry>
</map>
</property>
</bean>
<bean id="transferRule" class="net.sf.opentranquera.rules.logical.AndRule">
<constructor-arg index="0">
<list>
<bean class="net.sf.opentranquera.samples.rules.DifferentAccountRule"/>
<bean class="net.sf.opentranquera.samples.rules.AccountsExistsRule">
<property name="rule" ref="accountExistsRule"/>
</bean>
</list>
</constructor-arg>
<constructor-arg index="1" value="true"/>
</bean>
<bean id="accountExistsRule" class="net.sf.opentranquera.samples.rules.AccountExistsRule">
<property name="dao" ref="dao"/>
</bean>
<bean id="dao" class="net.sf.opentranquera.samples.rules.AccountDao"/>
As we can see iin the example, an evaluator gets injected in the service. The evaluator is
net.sf.opentranquera.rules.RuleEvaluator typed. The ruleEvaluator is configured like a Spring-Bean, being injected the different rules that it can evaluate, in the example two: Transfer and Balance.Each rule can be, like the transfer rule, a CompositeRule, that contains other rules inside. Now, from the service implementation or with an interceptor, you can call the evaluate in the RuleEvaluator to execute the rules. This example is inside the method, but using an interceptor is recommended:
public boolean transfer(Transfer transfer) throws TransferException {
this.evaluator.setEvaluatedObject(transfer);
RuleResult result = this.evaluator.evaluateRule("transfer");
if(!result.isSuccessful())
throw new TransferException(result.getMessages());
// TODO logic ..
return true;
}
Add a new validation using composition.
Now, the features of OT Rules come to light while adding and modifying new rules and execute business validations without changing the source code (in this case, the service implementation). We are going to add a new business rule that checks if there is enough funds in the source account. First of all, we create the new java rule class:
public class DebitAccountRule extends AbstractBusinessRule {
/*
* @see net.sf.opentranquera.rules.Rule#evaluate()
*/
public RuleResult evaluate() {
Transfer transfer = (Transfer) this.getEvaluatedObject();
// Get the balance of the account
// Checks if ther is enough funds to execute the transfer.
return this.getSuccess();
}
}
In this case, we have an mock implementation just to prove how OT rules works and is configured. Now we add the new rule in the configuration file:
<bean id="transferRule" class="net.sf.opentranquera.rules.logical.AndRule">
<constructor-arg index="0">
<list>
<bean class="net.sf.opentranquera.samples.rules.DifferentAccountRule"/>
<bean class="net.sf.opentranquera.samples.rules.AccountsExistsRule">
<property name="rule" ref="accountExistsRule"/>
</bean>
<bean class="net.sf.opentranquera.samples.rules.DebitAccountRule"/>
</list>
</constructor-arg>
<constructor-arg index="1" value="true"/>
</bean>
That's all what you have to do in order to add a new validation rule to the method execution. As we can see, nothing is changed in the TransferServiceImpl source code.
Rules reuse
OT Rules allows to reuse the rules in different objects or RuleEvaluators, for instance in the previous example we are going to reuse the rule
net.sf.opentranquera.samples.rules.AccountExistsRule, in the ruleEvaluator bean asigning the execution of the rule "balance" and in transferRule as one of the included rules:
<bean id="ruleEvaluator" class="net.sf.opentranquera.rules.RuleEvaluator">
<property name="rules">
<map>
<entry key="transfer"><ref local="transferRule"/></entry>
<entry key="balance"><ref local="accountExistsRule"/></entry>
</map>
</property>
</bean>
<bean id="transferRule" class="net.sf.opentranquera.rules.logical.AndRule">
<constructor-arg index="0">
<list>
<bean class="net.sf.opentranquera.samples.rules.DifferentAccountRule"/>
<bean class="net.sf.opentranquera.samples.rules.AccountsExistsRule">
<property name="rule" ref="accountExistsRule"/>
</bean>
<bean class="net.sf.opentranquera.samples.rules.DebitAccountRule"/>
</list>
</constructor-arg>
<constructor-arg index="1" value="true"/>
</bean>
More Rules
OT Rules has a built-in rule set to make the development easier:
*
AndRule: Executes the AND operation between several rules. Can use a short circuit if needed.*
OrRule: Executes the OR operation between several rules. Also can use a short circuit if needed.*
XorRule: Executes XOR between several rules.*
NotRule: Applies NOT to the result of the rule execution*
IfRule: Executes one or other rule using as a condition another rule.Also a set of
RuleResults are provided, as follows:*
SimpleResult: Basic functionality for a RuleResult.*
TrueResult: Is a RuleResult that returns true.*
FalseResult: Is a RuleResult that returns false.Finally, as mentioned earlier, OT Rules can be configured using different mechanisms:
* Spring: as used in this example
* API: You can create rule with java code, using a FluentAPI that enables the creation of rules in the java programming language, for example:
FluentRule fir = new FluentRule("test");
fir.rule(new TrueRule()).and(new TrueRule()).or(new FalseRule()).not();
RuleEvaluator evaluator = FluentInterfaceRuleEvaluatorBuilder.createRuleEvaluator(fir);
RuleResult result = evaluator.evaluateRule("test");
* XML: A XML format that has an Eclipse plugin to edit. Here is an example:
<rules>
<rule name="test.single.rule"
ruleClass="net.sf.opentranquera.rules.HelloWorldRule" />
<rule name="test.param.rule"
ruleClass="net.sf.opentranquera.rules.WordLengthRule">
<param name="length" value="11" />
</rule>
<rule name="test.and.rule"
ruleClass="net.sf.opentranquera.rules.logical.AndRule">
<rule ruleClass="net.sf.opentranquera.rules.HelloWorldRule" />
<rule ruleClass="net.sf.opentranquera.rules.WordLengthRule">
<param name="length" value="14" />
</rule>
</rule>
<rule name="test.not.rule"
ruleClass="net.sf.opentranquera.rules.logical.NotRule">
<rule ruleClass="net.sf.opentranquera.rules.support.FalseRule" />
</rule>
<rule name="test.negate.rule"
ruleClass="net.sf.opentranquera.rules.support.TrueRule"
modifier="negate" />
<rule name="test.and.ref"
ruleClass="net.sf.opentranquera.rules.logical.OrRule"
shortCircuit="false">
<rule ref="test.single.rule" />
<rule ref="test.param.rule" />
</rule>
</rules>
Summary:
In this article, we introduced OT Rules and walked through a simple example using OT Rules to execute business validations. We've also explained the different built-in handy rules and how to configure the rule set to perform validations.
Suscribirse a:
Comentarios (Atom)