viernes, 26 de marzo de 2010

Gestor de Contenidos Java - El poderoso Liferay

Empezaremos este post, con la definición de CMS (Sistema de Gestión de Contenidos).

CMS:
Programa de soporte para la creación y administración de contenidos, principalmente páginas web.
Consiste en una interfaz que controla una o varias base de datos en las cuales podemos realizar modificaciones del contenido del sitio. El sistema permite manejar de manera independiente el contenido y el diseño. Así, es posible manejar el contenido y darle en cualquier momento un diseño distinto al sitio sin tener que darle formato al contenido de nuevo, además de permitir la fácil y controlada publicación en el sitio a varios editores.

Sus ventajas saltan a la vista desde un primer momento de uso:

  • Mayor cantidad de usuarios (sin mayor conocimiento técnico)  puede indexar contenido en el portal.

  • Gestión dinámica de usuarios y permisos.

  • Costes de gestión de información son mucho menores.

  • Actualización, backup, reestructuración mucho más fácil; por el hecho de tener toda la información e una Base de Datos.

cms.png

Por ello su uso resulta casi obligatorio, al momento en que se desea desarrollar un portal de cualquier índole.

Generalmente cuando oíamos este concepto, lo relacionábamos directamente con CMS en PHP, los cuáles son muy bien conocidos como:


Pues como desarrollador java, buscaba algún CMS robusto que esté desarrollado integramente en Java.Que además permita implementar nuevas funcionalidades (portlets) muy aparte de todas las que ofrece.
Es asi como me tope con el "Poderoso Liferay".

logo-Liferay.jpg
Características de Liferay

Independencia respecto de Servidores de Aplicaciones. Liferay puede ejecutarse sobre contenedores ligeros como Tomcat o Jetty, o sobre servidores compatibles con J2EE como Borland ES, JBoss+Jetty/Tomcat, JOnAS+Jetty/Tomcat, JRun, OracleAS, Orion, Pramati, RexIP, Sun JSAS, WebLogic, y WebSphere. Un valor adicional de ser un portal basado en Java es que Liferay se ejecuta sobre múltiples sistemas operativos: BSD (FreeBSD, NetBSD, OpenBSD), Linux (Fedora, Novell), Solaris, Mac OS X y Windows.

Independencia respecto de Bases de Datos. Liferay emplea Hibernate como herramienta ORM para la capa de persistencia, lo que facilita que soporte cualquier base de datos como DB2, Firebird, Hypersonic, InterBase, JDataStore, MySQL, Oracle, PostgreSQL, SAP o SQL Server. Esto permite a las organizaciones mantener los recursos con los que cuenta y no tener que adquirir nuevo hardware y software de base de datos.

Internacionalización. Liferay puede mostrar y recibir entradas en múltiples idiomas. Incluye recursos lingüísticos en Chino, Holandés, Inglés, Alemán, Griego, Italiano, Japonés, Coreano, Portugués, Español, Turco y Vietnamita.

Altamente escalable. Liferay es escalable y usa EhCache para ofrecer a las personas encargadas de llevar a cabo el despliegue una caché en Cluster. De este modo es posible escalar añadiendo más nodos sin sacrificar la cache.

Struts y Tiles. Liferay está basado en Struts para seguir el patrón Modelo-Vista-Controlador (MVC). La apariencia del portal puede ser fácilmente adaptada y rediseñada, ya que la lógica de presentación está basada en sencillas plantillas que son leídas mediante Tiles.

Gran variedad de Portlets incluidos. Liferay ofrece más de cincuenta (50) portlets útiles: blogs, tienda, wiki, correo electrónico (webmail), tablón de anuncios, encuestas, canales RSS, etc. La mayor parte de los portlets pueden configurarse de forma que sean usados sólo por algunos usuarios del entorno colaborativo, gracias a la granularidad que permite la gestión de usuarios de Liferay Portal

Administración. Liferay permite que los administradores del portal gestionen fácilmente usuarios, grupos, localizaciones y roles a través de herramientas visuales. Los grupos y localizaciones representan conjuntos de usuarios, y un rol es un conjunto de permisos que un grupo o un usuario poseen. El acceso a portlets está restringido a usuarios en función de su rol

Tecnologías soportadas - JSR-168JSR-220 (Hibernate) - JSR-127 (JSF)AJAX , Spring, - EJB y programación orientada a aspectos (AOP) - Struts y Tiles - WSRP - Velocity

Casos de éxito:
El portal educativo PerúEduca del Ministerio de Educación del Perú usa el CMS Liferay.
http://www.perueduca.edu.pe/

Mayor información:
Tutorial Liferay
Foro oficial de Liferay en español



Bueno espero que les sirva este artículo, y empiecen a usar el CMS Liferay cuando requieran realizar algún Portal.  xD  .... edisonjc7

lunes, 22 de marzo de 2010

Mapeando la Base de Datos con Hibernate Tools

Hoy me preguntaba la forma en como mapear mis tablas de Base de Datos y generar sus respectivos *.hbm.xml para cada tabla con una herramienta open source (de libre descarga).

Si bien es cierto existe MyEclipse una IDE licenciada  derivada del eclipse que todos conocemos. El cual le da soporte a muchos de los framewoks Java tales como: Hibernate, ICEFaces, Tapestry, Struts, Spring, JSF y otros más. Lo único malo es que hay que pagar para usarla :(  , eso nos imposibilita usarla libremente.

Pero como nunca faltan los seguidores de taringa les dejo el link.. ojo.. solo para efectos didácticos eh.. taringa.net/My-Eclipse. ojo  NO abusar de ella.

Acá les dejo una imagen donde se muestra todo el soporte que te da myEclipse para los distintas arquitecturas...

Para más info sobre esta IDE visitar: myeclipseide.com


Entonces pese a todo esto que ofrece MyEclipse .. quise mapear mis tablas con una herramienta open source.. hasta que se me presento el bien merecido Hibernate Tools que cumple dicha labor tan igual o mejor que el propio MyEclipse con respecto al mapeo de tablas y a la creación de los POJOS.



Una vez que tienes el archivo en tu PC, podrás ver que existen 2 carpetas en él: features y plugins.
Ahora para integrarlo con nuestro eclipse tendremos que copiar el contenido de dichas carpetas dentro de las carpetas features y plugins de nuestra IDE. Luego tendrás que reiniciar el eclipse para visualizar sus cambios. Ojo: He probado integrarlo con el STS- SpringSource Tool Suite pero no ha funcionado del todo bien. En cambio,  he probado con el eclipse Ganymede y funciona a la perfección.

Listo terminado de configurar el Hibernate Tools, lo único que tienes que hacer es empezar a usarlo xD... Para ello, usa como referencia el manual de la herramienta :  manual hibernatetools. Para mayor precisión en su uso ver directamente el Capítulo 4.

Una foto de H. Tools in action:



Bueno como les menciono en mis anteriores artículos.. Espero que les sirva... Saludos Cordiales hasta el próximo posteo. xD ..

miércoles, 17 de marzo de 2010

Manejo de Transacciones con Hibernate y Spring AOP

En esta oportunidad hablaremos de la forma como configurar Spring AOP y Hibernate para el manejo de transacciones.

AOP (Programación Orientada a Aspectos) : es un paradigma de programación relativamente reciente cuya intención es permitir una adecuada modularización de las aplicaciones y posibilitar una mejor separación de conceptos. EL AOP siglas en inglés de la Programción Orientada a Aspectos, permite encapsular conceptos que componen una aplicación, en esta oportunidad la transaccionalidad de los métodos.

En cristiano todos los métodos que cumplan determinadas reglas definidas por nosotros, serán manejadas como transacción sin necesidad de haber indicado de forma programática dicha funcionalidad.

Para ello simplemente definiremos el applicationContext.xml de la siguiente manera.

<?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
 
<-- Definiendo el DataSource --> 
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/jdbc.properties"/>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">       
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>



<-- Configurando Hibernate con Pool de Conecciones c3p0  -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource">
    <property name="mappingDirectoryLocations">
        <list>
            <value>classpath:/mapping
        </list>         
    </property>
        

    <property name="hibernateProperties">
        <props>
             <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
             <prop key="hibernate.hbm2ddl.auto">update</prop>
             <prop key="hibernate.show_sql">true</prop>
             true</prop>

             <prop key="hibernate.c3p0.min_size">5</prop> 
             <prop key="hibernate.c3p0.max_size">20</prop> 
             <prop key="hibernate.c3p0.timeout">300</prop> 
             <prop key="hibernate.c3p0.max_statements">50</prop> 
             <prop key="hibernate.c3p0.idle_test_period">3000</prop>
    
             <prop key="hibernate.jdbc.batch_size">20</prop>
             <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
             <prop key="hibernate.cache.use_structured_entries">true
        </props>
    </property>
</bean>


<-- Configurando el manejo de Transacciones con AOP  -->
     
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
 
<tx:advice id="txAdvice" transaction-manager="txManager">     
    <tx:attributes>         
        <tx:method name="list*, get*, find*, exist*, load*" read-only="true"/>       
        <tx:method name="insert*, delete*, update*, save*" rollback-for="Throwable"/>    
        <tx:method name="*" rollback-for="Throwable"/>     
    </tx:attributes> 
</tx:advice>
    

<aop:config>
    <aop:pointcut id="serviceOperation" expression="execution(* pedro.rios.demo.service.*Service.*(..))"/>
    <aop:pointcut id="genericOperation" expression="execution(* pedro.rios.common.service.*Service.*(..))"/>
   
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="genericOperation"/>
</aop:config>


</beans>


Listo es todo lo que tenemos que hacer.. de lo demás se encarga el poderoso Spring. xD

Explicaremos:
Como podemos apreciar la cadena de conexión se sacará desde un archivo .properties para un mejor manejo en ambientes de producción.
solo hay que definir dicho archivo dentro de WEB-INF con el nombre de jdbc.properties; de esa forma se aprecia mejor y haces que tu framework sea más reutilizable.

Por otro, lado hemos definido pool de conecciones con C3P0.

El algoritmo que ya viene incluido en Hibernate para el "pooling" de conexiones es, sin embargo, bastante rudimentario. Fue concebido más que nada para ayudarlo a dar los primeros pasos, no para ser usado en un sistema de producción, ni siquiera para un test de performance.

Por eso deberías usar un "pool" de algún tercero para asegurar mayor redimiento y estabilidad. Simplemente reemplace la propiedad hibernate.connection.pool_size con propiedades específicas de la herramienta de "pooling" de su elección. Esto desactivará el "pooling" interno de Hibernate. En nuestro caso usaremos C3P0.


Para más info de Hibernate checar la siguiente url (está en español :D):  http://www.hibernar.org/documentacion_es/castellano.html
Luego, estamos definiendo la regla de los métodos que serán interceptados por Spring AOP para darles transaccionalidad. Dicha intercepción para esta demo se aplicará para los archivos que cumplan la siguiente forma: expression="execution(* pedro.rios.demo.service.*Service.*(..))" y expression= "execution(* pedro.rios.common.service.*Service.*(..))"

Listo con esto terminamos la definición del manejo de transacciones con Hibernate y Spring AOP.

Saludos Cordiales.. espero que les sirva esta demo....






lunes, 1 de marzo de 2010

Integrando Struts + Spring + Ibatis

Para empezar haré una breve definición de c/u de los frameworks:


  • Struts (1.3): Struts es una herramienta de soporte para el desarrollo de aplicaciones Web bajo el patrón MVC, usada en la programación de aplicaciones web JEE. Otros similares: Spring MVC, JSF entre los más populares.

  • Spring(2.5 - 3):es un poderoso MetaFramework para Java donde su principal objetivo es la inyección de dependencias. Desde nuestros programas - en vez de hacer new() y con cientos de inicializaciones de valores - simplemente obtenemos el objeto ya preparado desde Spring.

  • iBatis: Framework de Persistencia de Datos (se sitúa entre la lógica de Negocio y la capa de la Base de Datos). Se asocia a la fuente de datos mediante sentencias sql o procedimientos almacenados descritos en ficheros XML. Otros similares: Hibernate.
Empezaremos definiendo el archivo de web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>demoprp</display-name>

 
<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/log4j.properties</param-value>
 </context-param>

<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
 
<listener>
 <listener-class>
  org.springframework.web.util.Log4jConfigListener
 </listener-class>
</listener>

<listener>
 <listener-class>
  org.springframework.web.context.ContextLoaderListener
 </listener-class>
</listener>
 
 
 

<servlet>
 <servlet-name>action</servlet-name>
 <servlet-class>
  org.apache.struts.action.ActionServlet
 </servlet-class>

 <init-param>
  <param-name>config</param-name>
  <param-value>/WEB-INF/struts-config.xml</param-value>
 </init-param>
 <load-on-startup>2</load-on-startup>
</servlet>


Ahora definiremos el archivo de configuración de Spring el applicationContext.xml....
Por ahora definiré el bean dataSource con los datos del conexión en duro.. luego hablaremos la forma en como jalar los datos de conexión desde un *.properties para mayor facilidad de futuros cambios en en la etapa de producción. Usaremos Mysql 5.0 para esta demo.

<?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 

<property name="driverClassName">    
    <value>com.mysql.jdbc.Driver</value>
</property>
<property name="url"> 
    <value>jdbc:mysql://localhost:3306/bdTest
</property>
<property name="username"><value>root</value></property>
<property name="password"><value>mysql</value></property>

</bean>


     
   
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<property name="configLocation">
    <value> classpath:/pedro/rios/demo/persistency/ibatis/sql-map-config-cx.xml </value>
</property>
<property name="dataSource"><ref local="dataSource"/></property>     
</bean>

 
<bean id="empleadoCtx" class="pedro.rios.demo.daoIbatisImpl.EmpleadoDAOIbatisImpl">
   <property name="sqlMapClient">
      <ref bean="sqlMapClientMysql"/>
   </property>
</bean> 

<bean id="empleadoServiceId"  class="pedro.rios.demo.serviceImpl.EmpleadoServiceImpl">
    <property name="empleadoDAO" ref="empleadoCtx"> </property>
</bean>
  
</beans>

Como podemos apreciar el archivo de mapeo de xml pertenecientes a iBatis se encuentra dentro del src: en el paquete pedro.rios.demo.persistency.ibatis.sql-map-config.xml

Ahora veremos el archivo donde se encuentran mapeados todos los archivos pertenecientes a ibatis sql-map-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
    <sqlMap resource="pedro/rios/demo/ibatis/xml/Empleado.xml"/> 
    ...
</sqlMapConfig>


A continuación veremos la definición del archivo Empleado.xml que contiene todos los querys de la entidad Empleado.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Empleado" >
    <typeAlias alias="beanEmpleado" type="pedro.rios.bean.EmpleadoBean"/>

    <insert id="insertEmpleado" parameterClass="beanEmpleado">
  INSERT INTO tbempleado (nombre,apepat,apemat,email) 
  VALUES (#nombre#,#apepat#,#apemat#,#email#)
    </insert>

</sqlMap> 


En seguida veremos como está estructurado la capa DAO...

package pedro.rios.demo.dao;

import pedro.rios.demo.bean.EmpleadoBean;

public interface EmpleadoDAO { 
  public void insertEmpleado(EmpleadoBean beanEmpleado);  
}

//Otro archivo:

package pedro.rios.demo.daoIbatisImpl;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import pedro.rios.demo.bean.EmpleadoBean;
import pedro.rios.demo.dao.EmpleadoDAO;

public class EmpleadoDAOIbatisImpl extends SqlMapClientDaoSupport implements EmpleadoDAO {
 
    public void insertEmpleado(EmpleadoBean beanEmpleado){
 getSqlMapClientTemplate().insert("insertEmpleado", beanEmpleado); 
    }
 
}

Ahora definiremos los Service de acceso a los daos...

package pedro.rios.demo.service;

import java.util.List;
import pedro.rios.demo.bean.EmpleadoBean;

public interface EmpleadoService {
  
  public void insertEmpleado(EmpleadoBean beanEmpleado); 
}

//otro archivo 

package pedro.rios.demo.serviceImpl;

import java.util.List;

import pedro.rios.demo.bean.EmpleadoBean;
import pedro.rios.demo.dao.EmpleadoDAO;
import pedro.rios.demo.service.EmpleadoService;


public class EmpleadoServiceImpl implements EmpleadoService{
 
 private EmpleadoDAO empleadoDAO;

  /**
  * @return the empleadoDAO
  */
 public EmpleadoDAO getEmpleadoDAO() {
  return empleadoDAO;
 }

 /**
  * @param empleadoDAO the empleadoDAO to set
  */
 public void setEmpleadoDAO(EmpleadoDAO empleadoDAO) {
  this.empleadoDAO = empleadoDAO;
 }

  
  public void insertEmpleado(EmpleadoBean beanEmpleado){
  getEmpleadoDAO().insertEmpleado(beanEmpleado);
  }
}




Como vemos toda la lógica de negocio está lista para ser usada por nuestra capa de vista.. En el próximo posteo veremos como terminar de implementar Struts y la forma como invocar el método insertEmpleado desde un jsp. Por ahora solo hemos definido el archivo de configuración de Struts en el web.xml... Hasta la próxima publicación.. Espero que les sirva esta demo... Espero sus comentarios.. xD