JSE - Ejemplo básico de inyección de dependencias con CDI, DeltaSpike, Weld; persistencia: Batoo JPA con H2,Transacción incluida
Bueeeeeno... pues resulta que andando de ocioso, quise hacer algo en JSE que incluyera algo de inyección de dependencias. Estuve viendo opciones y me pareció buena idea hacer algo con CDI (de spring hay hartos ejemplos) y las casi recién nacidas extensiones de Apache Delta Spike y para la parte de persistencia, vagando por las internetes me encontré con Batoo que clama ser mucho más rápido que Hibernate (éso es ooooootro tema) y pues decidí incluirlo para mi ejemplo, para la base de datos usé H2; manos a la obra:
De entrada, como acá en el trabajo no puedo usar Maven, tuve que bajar y configurar todo casi a mano, la lista de jars queda así:
-guava-14.0.1.jar
-commons-lang-2.6.jar
-validation-api-1.0.0.GA.jar
-bonecp-0.7.1.RELEASE.jar
-h2-1.3.171.jar
-commons-dbutils-1.5.jar
-commons-io-2.4.jar
-asm-3.3.1.jar
-deltaspike-cdictrl-weld-0.3-incubating.jar
-deltaspike-core-api-0.3-incubating.jar
-deltaspike-core-impl-0.3-incubating.jar
-deltaspike-jpa-module-api-0.3-incubating.jar
-deltaspike-cdictrl-api-0.3-incubating.jar
-deltaspike-jpa-module-impl-0.3-incubating.jar
-weld-api.jar
-weld-spi.jar
-weld-se.jar
-batoo-annotations-2.0.1.0-RTM.jar
-batoo-jdbc-2.0.1.0-RTM.jar
-batoo-jpa-2.0.1.0-RTM.jar
-batoo-jpa-spi-2.0.1.0-RTM.jar
-jpql-0.1.6.jar
-parser-2.0.1.0-RTM.jar
-persistence-api-2.0.jar
Ahora, para la parte de código, el punto de entrada para detonar el contexto de inyección de dependencias, queda así:
import org.apache.deltaspike.cdise.api.CdiContainerLoader;
import org.apache.deltaspike.cdise.api.ContextControl;
import org.apache.deltaspike.core.api.provider.BeanProvider;
public class Access {
public static void main(String[] args) {
//con las dos lineas siguientes se detona el contenedor de inyección de dependencias
CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();
cdiContainer.boot();
//con las siguientes el alcance(scope) de la aplicación, se puede cambiar ;-)
ContextControl contextControl = cdiContainer.getContextControl();
contextControl.startContext(RequestScoped.class);
//acá la clase con la que vamos a comenzar (que sería algo como un segundo main
Mediator mediator = BeanProvider.getContextualReference(Mediator.class, false);
//ejecutamos el metodo que nos da entrada a nuestro programa
mediator.execInTransaction();
//detenemos el contexto
contextControl.stopContext(RequestScoped.class);
//damos de baja el contenedor
cdiContainer.shutdown();
}
}
Ya con ésto podemos dentro del código de la clase Mediator
(que puede ser el punto de entrada a toda una aplicación) obtener recursos mediante anotaciones, el código de dicha clase es:
import javax.inject.Inject;
@RequestScoped
public class Mediator{
@Inject
private InjectedByDI injectedByDI;
//este es el metodo que se ejecuta en la clase anterior
public void execInTransaction() {
injectedByDI.tryToExec();
}
}
Como se puede ver, ya tengo una interface InjectedByDI
que está anotada con @Inject
con lo cual ya no tenemos que hacer la implementación a mano; se ejecuta el método tryToExec()
; en la implementación el código queda así:
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
@RequestScoped
@Default
public class InjectedByDIImpl implements InjectedByDI {
@Inject
EntityManager entityManager;
@Override
@Transactional
public void tryToExec() {
System.out.println(">>> begin tryToExec()");
AppUser appUser = new AppUser();
appUser.setId((int)(Math.random()*100));
this.entityManager.persist(appUser);
System.out.println(">>> end tryToExec()");
}
}
En la implementación ya tengo anotado mi entityManager
también anotado, y la implementación de mi método tryToExec
la cual insertará un registro en mi base de datos (un objeto de la clase AppUser
.
Ahora, aquí hay un punto a notar, porqué el EntityManager
no está anotado con: @PersistenceContext(unitName="el nombre de la unidad de persistencia")
; bueno, según la documentación es porque éso sólo está permitido en ambientes EE; entonces, como no soy nadie para discutir las docs, y en la página de DeltaSpike viene un ejemplo, pues de ahí parto para poder generar mi EntityManager
; el código queda así:
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class EntityManagerProducer {
private EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("aqui el nombre de la unidad de persistencia");
@Produces
@Default
@RequestScoped
protected EntityManager createEntityManager() {
return this.entityManagerFactory.createEntityManager();
}
protected void closeEntityManager(@Disposes EntityManager entityManager) {
if (entityManager.isOpen()) {
entityManager.close();
}
}
}
Con ésta clase, ya tenemos disponible los EntityManager
por medio de la anotación @Inject
.
La clase de mi bean, pojo, modelo, VO, DTO, entidad o como le quieran llamar quedó:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="APP_USER")
public class AppUser implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="ID" ,nullable=false)
private Integer Id;
public Integer getId() {
return this.Id;
}
public void setId(Integer Id) {
this.Id = Id;
}
}
Ya con ésto queda el código completo del ejemplo.
Los ficheros de configuración quedan de la siguiente forma:
el beans.xml
que es algo así como el applicationContext.xml
de spring, queda:
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee <a href="http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
" title="http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
">http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</a> <interceptors>
<class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
</interceptors>
</beans>
Sólo contiene la declaración del interceptor de transacciones propio del DeltaSpike, y ya.
Y el persistence.xml
queda:
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence <a href="http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
" title="http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
">http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
</a> <persistence-unit name="aqui el nombre de la unidad de persistencia" transaction-type="RESOURCE_LOCAL">
<provider>org.batoo.jpa.core.BatooPersistenceProvider</provider>
<class>paquete1.paquete2.AppUser</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test" />
<property name="javax.persistence.jdbc.user" value="sa" />
<property name="javax.persistence.jdbc.password" value="" />
</properties>
</persistence-unit>
</persistence>
Lo único que no me gustó (y que espero corrijan en otro release) es el control de transacciones que no queda taaan a detalle como el de las anotaciones de spring (las propiedades de isolation level y propagation), de ahí en fuera, me gusta cómo va quedando éste rollito de unificar las varias extensiones existentes (CODI,CanDI,Seam, por mencionar algunas) en DeltaSpike.
Espero que en algún desarrollo en Swing tengan oportunidad de incluir y probar algo como mi ejemplo :-)
Digo, es una posibilidad (ya sabemos que existe Griffon, antes de que lo venga a promocionar Enrique =D )
Hasta la próxima.
- neko069's blog
- Inicie sesión o regístrese para enviar comentarios
Comentarios recientes
hace 11 semanas 6 días
hace 11 semanas 6 días
hace 11 semanas 6 días
hace 36 semanas 2 días
hace 37 semanas 4 días
hace 44 semanas 1 día
hace 1 año 37 semanas
hace 2 años 48 semanas
hace 3 años 4 días
hace 3 años 8 semanas