lunes, 18 de mayo de 2015

JAVA implementación Patrón Generic Dao

Que tal, en esta oportunidad se desea realizar la implementación del patrón GENERIC DAO y GENERIC SERVICE en una arquitectura empresarial JAVA con las tecnologías de SPRING para la capa de servicio e HIBERNATE para persistencia, pero antes vamos a comprender que significa este patrón de diseño.

GENERIC DAO: Como su nombre lo indica es es un patrón de diseño o llámese también practica de programación que busca reutilizar código mediante la implementación de operaciones básicas que se desea implementar en variedad de clases, un ejemplo de ello son las operaciones de crear, consultar, listar, eliminar, y modificar (CRUD) que generalmente tienen las clases dao,
Su técnica de implementación consiste en definir una clase que implementa una interfaz genérica que tendrá definidas estas operaciones y así mismo su implementación, a partir de esto las demás clases heredaran sus metodos mediante el atributo extends, como resultado podremos realizar todas estas operaciones solo con la creación e instanciamiento de la clase Dao sin necesidad de volver a declarar dichos métodos, a largo plazo esto representa una gran reutilización de código que permitirá realizar el mantenimiento de nuestra aplicación de forma mas sencilla.

Creación de interfaz GenericDao:

_________________________________________________________________________________


public interface GenericDao<T> {     T insertar(T t);
    void eliminar(T t);
    T encontrarPorId(Long id);
    T actualizar(T t);  
    List<T> listar();  
}
_________________________________________________________________________________


Creación de la clase GenericDaoImpl:

public abstract class GenericDaoImpl<T> implements Serializable, GenericDao<T> {

private static final long serialVersionUID = 1020243919685111719L;

protected SessionFactory sessionFactory;

private Class<T> entityClass;

@SuppressWarnings({ "unchecked", "rawtypes" })
@Autowired
public GenericDaoImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
Type t = getClass().getGenericSuperclass();
         ParameterizedType pt = (ParameterizedType) t;
         this.entityClass = (Class) pt.getActualTypeArguments()[0];
}

protected Session currentSession() {
return sessionFactory.getCurrentSession();
}

@SuppressWarnings("unchecked")
public List<T> listar() {
return currentSession().createQuery("SELECT e FROM "+this.entityClass.getSimpleName()+" e").list();
}

@SuppressWarnings("unchecked")
public T encontrarPorId(Long t) {
return (T) currentSession().get(this.entityClass, t);
}

public T insertar(T t) {
currentSession().saveOrUpdate(t);
return t;
}

public T actualizar(T t) {
currentSession().merge(t);
return t;
}

public void eliminar(T t) {
currentSession().delete(t);
}

}
_________________________________________________________________________________


Interface para el acceso a datos de personas PersonaDao:
_________________________________________________________________________________

public interface PersonaDao extends GenericDao<Persona> {

}
_________________________________________________________________________________


Clase implementación para el acceso a datos de personas PersonaDaoImpl: Heredara los atributos e implementación de metodos de GenericDaoImpl, ademas implementa la interfas PersonaDao que a su vez hereda la declaración de los metodos de insertar, actualizar, eliminar permitiendo que estos esten disponibles al llamar esta clase desde un servicio,
_________________________________________________________________________________

@Repository
public class PersonaDaoImpl extends GenericDaoImpl<Persona> implements PersonaDao {

private static final long serialVersionUID = -1745907453415561590L;

@Autowired
public PersonaDaoImpl(SessionFactory sessionFactory) {
super(sessionFactory);
}

}
_________________________________________________________________________________

La anterior implementación permitira que todas nuestra clases Daos que extiendan del Generic tenga los metodos del CRUD basico por defecto sin necesidad de su declaración o implementación, a continuación este será el resultado desde el llamado de un servicio.




Implementación de GenerciService: GenericServices nos permitirá disponer de las operaciones CRUD para cualquier de nuestros servicios que extiendan de la clase GenericService, a continuación se presenta la implementación de GenericService.

Codigo de interfas PersonaService.
_________________________________________________________________________________

public interface PersonaService extends GenericService<Persona> {
}

_________________________________________________________________________________

Codigo de clase PersonaServiceImpl.
_________________________________________________________________________________

@Service("personaService")
@Transactional
public class PersonaServiceImpl extends GenericServiceImpl<Persona>  implements PersonaService {

private static final long serialVersionUID = 6641349706597372948L;


@Autowired
public PersonaServiceImpl(PersonaDao personaDao) {
this.setGenericDao(personaDao);
}

}

_________________________________________________________________________________


Archivos de configuración de Spring.

Archivo application-context.xml: Encargado de realizar la detección automática de servicios y repositorios bajo el uso de anotaciones @service, @autowired de spring.
_________________________________________________________________________________

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="co.com.sp.capapersistencia" />
<context:component-scan base-package="co.com.sp.capaservicio" />

</beans>
____________________________________________________________________


Archivo datasource.xml: Encargado de definir la conexión con base de datos, el driver utilizado y el bean para manejo de transacciones.
_________________________________________________________________________________

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd">

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/my_bd_nombre" />
<property name="username" value="usuario" />
<property name="password" value="contraseña" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" p:dataSource-ref="dataSource">
<property name="packagesToScan">
<list>
<value>co.com.sp.capadominio</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.format_sql=true hibernate.show_sql=true
hibernate.dialect=org.hibernate.dialect.H2Dialect</value>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" />

</beans>
_________________________________________________________________________________



martes, 12 de mayo de 2015

Activity error unknown version from database: '5.x'

Error al correr la aplicación activity-explorer unknown version from database: '5.17.x' generado al realizar la conexión con la base de datos configurada en el archivo db.properties.

Causa: Las versión de la base de datos es superior a la version del activity-explorer, esto puede suceder cuando tenemos una bd creada por el activity-explorer por defecto en su versión 5.16 y se ha realizado al mismo tiempo una conexión desde un test de activity que contiene dependencias de la version 5.17 y actualiza la bd a una versión superior que no es soportada por el activity-explorer 5.16.

Solución: Estabilizar las versión tanto del test como del activity-explorer, preferiblemente las dos a la versión superior que la bd tenga actualmente.

lunes, 11 de mayo de 2015

Solventar error CORBA MARSHAL 1330446343

Error CORBA MARSHAL 1330446343 generado al realizar una llamara RMI a una interfas remota que retorna un objeto personalizado.

Causa: Las versiones del objeto retornado en el cliente o en el servidor son diferentes

Solución: Realizar una limpieza del proyecto, comprobar que los dos proyecto tanto el servidor como el cliente tienen como dependencia el proyecto que contiene las interfaces remotas y el DTO que se desea intercambiar.

Implementación en codigo:

Servidor:

PersonaServiceImpl: Debe de implementar la interfas remota  MensajeServiceRemote del proyecto de dependencias.

public class PersonaServiceImpl implements MensajeServiceRemote, Serializable{

private static final long serialVersionUID = 7143324113539318787L;
public OrdenCompra enviarMensaje(OrdenCompra orden) {
orden.setId(orden.getId()+1);
orden.setNombreSocio(orden.getNombreSocio()+" procesado");
orden.setNumeroOrden(orden.getNumeroOrden()+" procesado");
return orden;
}
}


_________________________________________________________________________________

Proyecto dependencia Interfaces y DTOs:
Debe contener la interfas remota y el DTO que se va a intercambiar entre el cliente y servidor

Interfas:

@Remote
public interface MensajeServiceRemote {
OrdenCompra enviarMensaje(OrdenCompra orden);
}

DTO:

public class OrdenCompra implements Serializable {

private static final long serialVersionUID = -7986978429487671468L;

private Long id;
private String numeroOrden;
private String nombreSocio;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNumeroOrden() {
return numeroOrden;
}
public void setNumeroOrden(String numeroOrden) {
this.numeroOrden = numeroOrden;
}
public String getNombreSocio() {
return nombreSocio;
}
public void setNombreSocio(String nombreSocio) {
this.nombreSocio = nombreSocio;
}

}

___________________________________________________________________________

Proyecto Cliente RMI

Clase de prueba:

public class ClientePersonaService {
public static void main(String[] args) {
System.out.println("Se esta llamando a la clase pertienente");
System.out.println("Iniciando llamada al EJB desde el cliente\n");
Context jndi = null;
try {
jndi = new InitialContext();
MensajeServiceRemote mensajeService = (MensajeServiceRemote) jndi.lookup("java:global/proyectoweb/PersonaServiceImpl!co.com.sp.interfaces.MensajeServiceRemote");
OrdenCompra orden = new OrdenCompra();
orden.setId((long)1);
orden.setNombreSocio("Servio Pantoja");
orden.setNumeroOrden("11111");
orden = mensajeService.enviarMensaje(orden);
System.out.println(orden.getId()+" "+orden.getNombreSocio()+" "+orden.getNumeroOrden()+" "+" Procesado cliente");
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Tener en cuenta que el jndi.lookup("java:global/proyectoweb/PersonaServiceImpl!co.com.sp.interfaces.MensajeServiceRemote");
Debe ser el Jndi de la interfas que se quiere invocar como servicio.