martes abril 17, 2007 Estuve analizando las diferentes posibilidades que existen dentro del Spring Framework para la implementación del "pattern" Open session in view.
Spring propone dos formas:
Probe ambos mecanismos y encontre el primero tiene dos problema grave (al menos es lo que yo encontre)
Grupo grupo = new Grupo(); grupo.setId(form.getIdGrupo()); empresa.setGrupo(grupo);
Grupo grupo = servicio.findById(form.getIdGrupo()); // cargo el objeto empresa.setGrupo(grupo);
En el mecanismo de deferred session encontre que para ciertas consultas se pueden abrir una gran cantidad de sessiones, por lo que hay que tener en cuenta esto para definir el tamaño del pool de conexiones
( abr 17 2007, 04:47:34 PM ART ) Permalink Comentarios [0]
viernes marzo 30, 2007 En el proyecto que estoy trabajando actualmente existe cierto contenido que se genera dinamicamente que puede ser cacheado (por ejemplo en menu), para ello utilice oscache para cachear dicho contenido.
Pero tuve un problema a la hora de poner el tag <cache:cache> en mi layout.jsp (define el layout de mi pagina llamando a <tiles:insert>
.
Can't insert page '/layout.jsp' : Illegal to flush within a custom tag
Ahora bien, hice la prueba rapida de poner el valor de flush en false y funciona:
<cache:cache> <tiles:insert attribute="menu" flush="false"/> </cache:cache>
Por otro lado lo que si funciona es utilizar el tag <cache:cache> dentro de las paginas jsp que tiles incluyo, por ejemplo en la pagina definida como body. En este caso si oscache realiza su trabajo correctamente y cache el contenido definido.
( mar 30 2007, 01:05:20 PM ART ) Permalink
martes diciembre 19, 2006 Segunda parte del tutorial que muestra como trabajar el engine de reglas OT-Rules.
http://opentranquera.sourceforge.net/tiki/tiki-read_article.php?articleId=5 ( dic 19 2006, 10:21:31 AM ART ) Permalink
viernes noviembre 24, 2006 Acabo de publicar en la wiki de OTF un articulo sobre como utilizar OT-Web JSF Locator para obtener e inyectar servicios (JNDI, Spring, EJB) a backing beans en un manera simlpe y flexible.
( nov 24 2006, 11:27:52 AM ART ) Permalink
jueves noviembre 23, 2006 Listado de libros de EJB3
Escribi un tutorial de una pequeña framework de rules que basicamente ayuda al programador Java a construir logica de negocio en pequeños fragmentos (clases) llamados rules que luego pueden ser compuestas y reutilizadas.
ot-rules
martes marzo 28, 2006 Este es un patrón propuesto en la documentación de bea weblogic para incrementar la performance de una aplicación que trabaja en su capa de persistence con EntityBeans más precisamente con CMP 2.0. La idea detras de este es hacer un uso intenso de la cache de entities y del mecanismo de invalidación implícita que WebLogic provee.
Las entidades candidatas a ser implementadas con este patrón son aquellas en las cuales se realizan operaciones de lectura frecuentes y operaciones de escritura ocasionalmente.
Para implementar este patrón se deben crear dos entity beans uno de read-only y otro de read-write apuntando a la misma tabla de la base de datos, el bean de read-only se utiliza para las operaciones de lectura mientras que el bean de read-write se utiliza para las operaciones de escritura y comportamiento transaccional. Luego se indica mediante configuración que cuando el bean de read-write sea modificado invalide el bean read-only de la cache.
Cuando se accede al bean de read-only en una transacción (JTA Transaction) el container activa una nueva instancia de este bean para la transacción con los datos tomados desde la cache, si no se encuentra en la cache llama a el método ejbLoad(), carga el bean y lo coloca en la cache de entities para su posterior uso. De esta forma las operaciones de lectura de la entidad se realizan todas sobre la cache mejorando los tiempos de acceso.
Ahora bien, cuando se utiliza el bean de read-write y este se ve modificado en alguno de sus campos, el container cuando comité la transacción (y llame a ejbStore() del bean) llama al mecanismo de invalidación y de esta forma se invalida el bean de read-only para que en su próxima lectura este se refrescado (se llame a ejbLoad()).
Otra forma de hacer que los beans de read-only se refresquen es utilizando un timeout de forma tal que cada un lapso determinado de tiempo estos bean se sincronizan con los datos en la base de datos.
Con el uso de este patrón se obtienen tiempo de respuesta mucho mejores dado el uso de la cache de bean read-only. Para casos similares podria tenerse en cuenta el uso de estrategias de concurrencia optimistas, las cuales mejoran el control de cambio de las entidades.
( mar 28 2006, 12:19:15 PM ART ) Permalink Comentarios [1]
viernes marzo 17, 2006 Ya hace un tiempo que los POJOs (Plain Old Java Objects) están invadiendo las diferentes capaz de nuestras aplicaciones. Empujados por el intenso uso de lightweight frameworks (Spring por ejemplo) y AOP (Aspect Oriented-Programming), este tipo de objetos se están utilizando masivamente en el desarrollo de nuevas aplicaciones en JEE (Java Enterprise Edition).
Los POJOs son utilizados en la capa de persistencia a través de los ORM, donde se realizan mapeos entre estos objetos y tablas del mundo relacional. Persistence frameworks como Hibernate, JDO o Java Persistence API alientan el uso de los pojos y suministran persistence transparente para estos objetos.
En la capa de servicios, cada ves es mas común ver pojos publicados bajo diferentes mecanismos (EJB, web services, etc) y gracias a la utilización de AOP se pueden obtener objetos con muy bajas dependencias que disfruten de servicios de bajo nivel como transacciones, seguridad, logging, validaciones, notificaciones, etc. Utilizando POJOs como facade simplifica el desarrollo permitiendo que toda la lógica sea desarrollada y testeada fuera del application server y al mismo tiempo soportar los servicios de bajo nivel ya mencionados.
En la capa de presentación se encuentra JSF, donde sus managed bean pueden verse como pojos, objetos sin dependencias que son manejados por JSF.
Ahora bien, en la capa de integración con otros sistemas, el jugador más importante es XML. Sin embargo hay formas de transformar XML a Pojo y viceversa utilizando frameworks como JAXB, XMLBeans o XStreams por mencionar algunas.
Donde también los POJOs entran en acción es en el desarrollo del modelo de dominio que representan las entidades del mundo real que el sistema trata de modelar. Aquí los POJOs suministran simplicidad, OOD (Object-Oriented Design), mantenibilidad y extensibilidad
Como dijimos anteriormente frameworks como Spring, Hibernate, etc. alientan el uso de POJOs para el desarrollo de aplicaciones y cabe destacar que EJB3 también alienta la utilización de POJOs sobre todo por nueva API de persistencia de Java - JPA y por el uso de POJOs Facade, donde el EJB Container es el encargado de suministrar los servicios de bajo nivel
Para concluir podemos decir que hoy en día, para desarrollar una aplicación lo que se desarrollaran son POJOs utilizando técnicas de OOP y OOD, conectándolos y configurándolos a través de frameworks externas como ser Spring, Hibernate, EJB3, etc.
( mar 17 2006, 04:20:23 PM ART ) Permalink Comentarios [1]
miércoles marzo 15, 2006 Hace un tiempo fui a un par de cursos de Oracle sobre ADF - Application Development Framework, aunque a mi me gusta llamarla "Awful Development Framework".
La verdad que no me gusta en nada (salvo la nueva versión que trae el diseño de paginas JSF bastante bueno) y aunque no la conozco profundamente voy a dar mi opinión acerca de esta mmm, llamemosla framework.
miércoles diciembre 07, 2005
Todos conocemos el patrón de diseño Template que permite que alguna parte de un algoritmo sea definido y pueda ser implementado en una clase base definiendo un comportamiento genérico de modo que las diferentes implementaciones definan un comportamiento específico para completar la tarea del algoritmo. De esta manera, las subclases pueden sobrescribir métodos de forma de darle significado a un algoritmo sin cambiar la estructura general de este. Es particularmente usado para separar el comportamiento variante del invariante, minimizando la cantidad de código escrito. El comportamiento invariante es codificado en la clase abstracta (template) a entonces cualquier subclase que herede de esta puede sobrescribir los métodos abstractos e implementan las necesidades especificas del contexto. (1)
En el libro GOF se realiza la siguiente definición: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. (2)
El problema con este modelo es que la herencia a un tipo de relación entre objetos que es muy acoplado, haciendo que el diseño sea poco flexible de modo que aca se plantea utilizar un modelo por composición para reemplazar la herencia. De esta manera se obtiene un diseño más flexible dado que se obtiene un modelo donde se pueden intercambiar (a través de la inyección) las partes específicas de un algoritmo.
Veamos como se vería un modelo de diseño aplicando estos principios. En primer lugar en tendríamos una clase que haga de template tal como el patrón en su forma original, por ejemplo:
public class Processor {
private Collaborator1 coll1;
private Collaborator2 coll2;
public Processor(Collaborator1 c1, Collaborator2 c2) {
this.coll1 = c1;
this.coll2 = c2;
}
/**
* Define el comportamiento genérico del algoritmo
* El comportamiento especifico de este algoritmo esta desarrollado en
* las implementaciones de los colaboradores
*/
public String process() {
// ejecuta alguna tarea ...
long id = coll2.getId();
coll1.doIt(id);
// realiza otra tarea ...
String result = coll2.execute();
// procesa el resultado
return result;
}
}
public interface Collaborator1 {
public void doIt(long cod);
}
public interface Collaborator2 {
public long getId();
public String execute();
}
De esta simple manera se obtiene la implementación del patrón template utilizando composición de objetos en lugar de herencia. Como vemos aquí se pueden reemplazar/combinar fácilmente, utilizando inyección, las implementaciones de los colaboradores que son los que tienen el código especifico del algoritmo. En este caso en particular se podrían crear diferentes instancias de la clase Processor para obtener diferentes implementaciones del algoritmo genérico. Incluso se podrían inyectar mock objects para los test unitarios del sistema.
Por otro lado, seria recomendable utilizar algún IoC container para realizar la inyección de los colaboradores.
Si quisiéramos hacer esto mismo utilizando el patrón template con herencia, tendríamos la clase abstracta Processor, donde si método process se vería así:
public String process() {
// ejecuta alguna tarea ...
long id = this.getId();
this.doIt(id);
// realiza otra tarea ...
String result = this.execute();
// procesa el resultado
return result;
}
public abstract long getId();
public abstract void doIt(long cod);
public abstract String execute();
Y ahora tendríamos una nueva clase que herede de esta donde se implementen los métodos específicos del algoritmo. Como se puede queda un modelo más acoplado y menos flexible.
Aunque yo recomiendo utilizar esta técnica para el patrón template creo que hay que evaluar en cada caso lo que más conviene y queda mejor para un determinado caso.
(1) The Template Design Pattern
(2) Design Patterns - Elements of reusable Object-Oriented Software (GOF book)
martes noviembre 15, 2005 La nueva especificación de EJB 3.0 tiene muchas variantes y mejoras con respecto a sus predecesoras:
- Simplifica el desarrollo de aplicaciones
- Uso del nuevo feature de J2SE 5, metadata, para especificar comportamiento esperado del container, para injectar recursos y servicios (otros beans) y especificar el mapeo objeto/relacional. De esta forma el bean provider puede obviar el deployment descriptor.
- Permite el uso de deployment descriptor para sobreescribir las configuraciones realizadas con anotaciones. Tambien se puede obviar el uso de anotaciones y utilizar solamente el deployment descriptor como mecanismo de configuración.
- Utiliza POJO/POJI para definir un Enterprise Bean Class. No hay dependencias con las viejas interfaces (EJBObject o EJBLocalObject).
- Uso mas flexible de excepciones (unchecked exceptions).
- Uso no obligado de callback methods aunque si es necesario si se desea recibir notificaciones y eventos del container. De echo los callback methods se pueden reemplazar por callback listeners de modo de no tener estos metodos dentro de la clase de negocio.
- Permite el uso de interceptores para session y message-driven bean.
- Se eliminaron las Home interface.
- Un entity bean es un objeto de dominio liviano.
jueves octubre 27, 2005 Aca dejo un par de links de mocks para prepararse para esta certificación:
http://www.javabeat.net/javabeat/scjp5/index.php
http://www.examulator.com/phezam/login.php
http://www.wickedlysmart.com/SCJPStudyGuide/Java_5_SCJPquestions.html
http://www.richardchen.info/home/scjp/
Guía online:
http://java.boot.by/scjp-tiger/
Libros:
- Complete Java 2 Certification Study Guide, Fifth Edition
- Java 1.5 Tiger. A developer notebooks
jueves octubre 20, 2005 Se me plantea la siguiente duda con respecto a como injectar colaboradores/recursos a objetos. Utilizar injección por constructor o por setter (considerando que estos dos son los más utilizados).
Veo las ventajas y desventajas de cada uno de estos approach, sin embargo, creo que la injección por constructor tiene una gran ventaja con respecto a la injección por setter que es que me permite crear los objetos totalmente configurados con lo cual mantienen un estado consistente del objeto mientras que la injección por setter podría dejar colaboraciones en null, siendo mas propenso a errores. Ademas la injección por constructor genera menos código (setXXX).
Pero, a pesar de esto, creo que la injección de setter es mejor en la mayoria de los casos, dado que disfruta de un conjunto de ventajas como ser:
(Tomado del libro Expert One-on-One? J2EE Development without EJB Rod Johnson with Juergen Hoeller)
- JavaBean properties are well supported in IDEs.
- JavaBean properties are self-documenting.
- JavaBean properties are inherited by subclasses without the need for any code.
- It?s possible to use the standard JavaBeans property-editor machinery for type conversions if necessary.
- Many existing JavaBeans can be used within a JavaBean-oriented IoC container without modification.
- If there is a corresponding getter for each setter (making the property readable, as well as writable), it is possible to ask the component for its current configuration state.
- Setter Injection works well for objects that have default values, meaning that not all properties
need to be supplied at runtime.
Además (de acuerdo a la implementación del IoC container) puede lograr el mismo resultado en el checkeo de las dependencias para obtener objetos creados con un estado consistente.
Que creen ustedes?
( oct 20 2005, 12:09:16 PM ART )
Permalink
Comentarios [1]
martes octubre 11, 2005 Varargs
Varargs (Variable Arguments) nos permite especificar que un método puede tomar múltiples argumentos de un mismo tipo, es decir, permite que pasar un número indeterminado de argumentos a un método.
En versiones anteriores si queríamos hacer algo así teníamos que pasar un array de objetos (Object[]) como argumento de un método, ahora con varargs queda más simple y claro el pasaje de parámetros indeterminado a un método, por ejemplo:
public void doIt(Object... args) {
...
}
this.doIt("Java", "5", "J2EE", new Integer(5));
Varargs se aplica teniendo en cuenta las siguientes reglas sintácticas y semánticas:
- El tipo de datos debe estar seguido de tres puntos (...)
Type...
- El argumento variable debe ser el último en la lista de argumentos del método.
- Es interpretado como Type[]
De esta forma vemos que varargs lo que hace es ocultar el proceso de transformar el argumento variable en un Type[], creandolo con los parámetros pasados al método para luego invoca al método propiamente dicho pasándole el Type[].
Veamos otro ejemplo, ahora la forma de declarar el método main utilizando varargs se vería asi:
public static void main(String... args) {
...
}
Una de las principales ventajas de varargs es que nos permite reducir el numero de métodos escritos para resolver una funcionalidad, en lugar de tener 4 o 5 métodos con diferentes listas de argumentos, podemos hacer uno solo con argumentos variables. Sin embargo el problema que surge con esto es que podemos llegar a tener un código que se preocupe mas por como trabajar con los argumentos variables que por la lógica de negocios que este debe resolver, por eso hay que tener cuidado y no abusar de este feature.
Otras de las ventajas es que se obtiene un código mas limpio y flexible.
Iterando sobre variable-length argument list
Ahora como hacer para trabajar con un argumento variable? Es muy simple, este es tratado como un array, por lo tanto se lo trabaja como si se estuviera trabajando un Type[].
public void doIt(String name, int ... codes) {
StringBuilder sb = new StringBuilder("Name = ")
.append(name)
.append(" -> ");
Formatter formatter = new Formatter(sb);
for( int code : codes ) {
formatter.format("%d ", code);
}
System.out.println( sb.toString() );
}
La llamada a este método se puede realizar de diferentes formas:
Test test = new Test();
test.doIt("jh"); // codes = new int[]{}
test.doIt("jh", 1); // codes = new int[]{1}
test.doIt("jh", 1,2,3,4,5,6); // codes = new int[]{1,2,3,4,5,6};
La salida del siguiente código es:
Name = jh ->
Name = jh -> 1
Name = jh -> 1 2 3 4 5 6
Como se resuelve la sobrecarga y sobre escritura de métodos?
Unos de los temas a tener en cuenta cuando utilizamos varargs es la forma en la cual se resuelven la sobre carga y la sobre escritura de los métodos.
Por ejemplo que sucede si tenemos el siguiente código:
public class VargArgs {
public static void main(String[] args) {
VargArgs va = new VargArgs();
va.doIt("a", "b", "c");
va.doIt(1,2,3,4);
va.doIt(1,2,"d");
va.doIt("a", new Integer(10));
}
public void doIt(String... a) {
System.out.println("String..." + Arrays.toString(a));
}
// Duplicate method.
// public void doIt(String[] a) {
// System.out.println("[]" + Arrays.toString(a));
// }
public void doIt(Number... n) {
System.out.println("Number..." + Arrays.toString(n));
}
public void doIt(Object... o) {
System.out.println("Object..." + Arrays.toString(o));
}
}
Como vemos tenemos varios métodos doIt sobrecargados con diferentes lista de argumentos, nada del otro mundo, pero que pasa si ejecutamos el método main de esta clase? Tendremos una salida como la que se muestra a continuación:
String...[a, b, c]
Number...[1, 2, 3, 4]
Object...[1, 2, d]
Object...[a, 10]
Bueno, creo que queda claro a que método se llama en cada línea, pero ahora que sucede si realizamos algunos cambios en el código, como por ejemplo, declaramos un nuevo método doIt que reciba un String[]. Lo que sucede es que obtendremos un error en tiempo de compilación debido a que estaria el método duplicado. Otro cambio que hará que tengamos un error en tiempo de compilación en las líneas va.doIt(1,2,"d"); y va.doIt("a", new Integer(10)); al cambiar el signature del método public void doIt(Object... o) por public void doIt(Object[] o), pero porque? Es simple la declaración public void doIt(Object... o) significa que el método puede recibir una cantidad variable de argumentos mientras que public void doIt(Object[] o) significa que el método espera recibir un array de objetos.
Las reglas explicadas para la resolución de métodos explicadas en Java 5. ¿Que tiene de bueno y de malo?. Parte II son aplicadas a varargs.
En lo que respecta a la sobre escritura de métodos veámoslo con un ejemplo.
public class SubVarArgs extends VargArgs {
public static void main(String[] args) {
SubVarArgs s = new SubVarArgs();
s.doIt(1,2,3,4);
s.doIt(new Number[]{1,2,3});
}
public void doIt(Number... n) {
System.out.println(this.getClass().getName() + "[]" + Arrays.toString(n));
}
}
La salida es:
varargs.SubVarArgs[][1, 2, 3, 4]
varargs.SubVarArgs[][1, 2, 3]
Dado que se sobrescribe el método doIt(Number...) ambas llamadas se realizan sobre el objeto de la subclase. Ahora si cambiamos el signature de doIt(Number...) por doIt(Number[]) tendremos la siguiente salida:
Object[][1, 2, 3, 4]
varargs.SubVarArgs[][1, 2, 3]
Se invoca el método doIt(Object...) de la superclase dado que el compilador no entiende que se ha sobrescrito el método, si en cambio, se invoca doIt(Number[]) cuando llamamos el método pasándole un array de Number.
Otro detalle a tener en cuenta es que si cambiamos el signature doIt(Object...) de la superclase por el signature doIt(Object[]) nos dará un error de compilación debido a que no hay método que se resuelva para s.doIt(1,2,3,4).
Como podemos ver varargs es un interesante features de Tiger, pero debería utilizarse con precaución y moderación y solamente cuando el beneficio sea alto. También debería tenerse cuidado a sobrecargar y sobrescribir varargs methods.
( oct 11 2005, 03:49:12 PM ART )
Permalink
Comentarios [1]
viernes septiembre 16, 2005
Contexto.
En las aplicaciones J2EE donde la persistencia es manejada mediante Enterprise JavaBeans de Entidad, mas presisamente utilizando CMP, las
actualizaciones (DMLs) de una gran cantidad de datos puede volverse poco eficiente dada la naturaleza de los entity beans.
Problema.
Todos conocemos el patrón Fast Lane Reader (1) que propone un mecanismo para obtener grandes cantidades de información utilizando un acceso directo sobre la base de datos en lugar de trabajarlos con Entity Beans.
Sin embargo se nos planteo el problema de tener que realizar una gran actualización/inserción de información en la base de datos. El problema concreto era por cada registro habia que realizar una actualización campos y una inserción de un registro en otra tabla relacionada. En principio lo trabajamos utilizando los CMP (en Bea Weblogic 8.1) y realizando un poco de tunning (enable-batch-operations = True, concurrency-strategy = Optimistic, etc) pensamos que podria funciona bien, pero al momento de realizar las pruebas con grandes cantidades de datos nos encontramos con que el método no era el mas eficiente (teniamos que, para cada bean actualizarle el atributo y settear la relación) con lo cual los tiempos se fueron un poco de lo esperado.
Solución.
Usamos una modificación de Fast Lane Reader (bautizado Fast Lane Writer) aplicado a la actualización masiva de información en la base de datos y ejecutando DML directamente sobre JDBC o invocando un Stored Procedure, se mejoraron los tiempo en un 500% aproximandamente.
Una de las desventajas de este utilizar esto es la des-sincronización entre las caches (del appserver) y la BD, pero utilizando mecanismos de invalidacion de caches (en el caso nuestro, con weblogic no tuvimos problema) se puede solucionar facilmente.
Otro tema a tener en cuenta es como ejecutarlas sentencias DML que en nuestro caso tuvimos la posibilidad de hacerlo a traves de inserts masivos ( insert / select ... ).
Conclusion.
Con la aplicación de este patrón obtuvimos una mejora importante en la performance del proceso mejorando los tiempos de respuestas y una mejor administración de los recursos, sin tener grandes problemas.
Referencias.
(1)
- http://java.sun.com/blueprints/patterns/FastLaneReader.html
- http://java.sun.com/developer/technicalArticles/J2EE/J2EEpatterns/