martes, 24 de agosto de 2010

Revelando el misterio de los Web Services en Java - Parte I

Al parecer el hecho de saber de web Services en Java es todo un lujo.. Existe poca información clara al respecto y por lo general los programadores java no saben por donde empezar cuando se les habla de web services. Es por la necesidad de tener información realmente útil y fácil de entender que nace este post .. Realmente considero que este artículo les va ser de mucha ayuda cuando requieran empezar con el uso de los Servicios Web en Java.

Personalmente aún no he tenido la oportunidad de participar en proyectos donde requieran el uso de los web services, con lo cúal aprendería mucho más del uso de estos.

Empezaremos este artículo viendo de forma general la gran importancia que tienen los Servicios Web.

Servicio Web.-  en inglés Web Service, es un conjunto de protocolos y estándares que sirven para intercambiar datos entre diferentes aplicaciones, pudiendo estar desarrolladas en distintos lenguajes de programación y siendo ejecutadas en diferentes plataformas.  En relación a ello nace el concepto de SOA (Arquitectura Orientada a Servicios).


ws.png

Pues bien, una vez conocida la definición empezaremos a implementarlo en Java. Es en este punto en donde empiezan nuestras interrogantes.
  •  ¿Es mejor AXIS2 o JAXWS?
  • ¿Cómo genero el ws a partir del wdsl o de las clases Java?
  • ....
Pues bien empezaremos a resolver nuestras dudas.

Con respecto a a nuestra primera interrogante de ¿Qué elegir, Axis2 o JAXWS?

Empezaremos haciendo una comparativa entre los frameworks que podemos utilizar para el desarrollo de un ws, ya sea Axis2 o JAXWS. Existen otras opciones pero son poco conocidas aún.

Ventajas  y desventajas del uso de ambos:

  • Con Axis2 necesitamos tener instalado al menos la versión 1.4 del jdk, mientras que para JAXWS al menos necesitamos la versión 1.5 como mínimo. Este puede ser un factor determinante, en el caso de que nuestro servidor de aplicaciones utilice la versión 1.4 y no podamos migrar a una versión posterior.

  • Si generamos el WS a partir de las clases Java, no existen muchas diferencias entre una y otra solución.Aunque el archivo .wsdl que genera Axis2 es bastante engorroso y complicado de analizar (hay que tenerlo en cuenta a la hora de que alguien tenga que crear una aplicación cliente que se conecte a nuestro WS a partir del wsdl que nosotros le proporcionemos).

  • Si la estructura de los mensajes SOAP es más compleja, o deseas generar tu mismo el wsdl para tener más control sobre los mensajes SOAP (cosa que se recomienda), es preferible utilizar JAXWS. El código que genera Axis2 es realmente “infumable”. Genera clases hasta por las puras clases de estilo clase_1, clase_2, así como un montón de clases anidadas. No sé si todo esto habrá cambiado en las versiones posteriores, pero desde luego en la versión que conosco(1.3), la legibilidad y reutilización del código era penosa. El código generado esta lleno de warnings. En fin todo bastante engorroso. Sin embargo en JAXWS, al utilizar anotaciones, todo queda mucho más límpio y claro. Desde luego, este punto es el que me hizo preferir JAXWS antes que Axis2.

  • JAXWS al ser de Sun, podríamos decir que es más estandar que Axis2 que es de Apache
En conclusión, recomiendo usar JAX-WS a menos de que el servidor tenga la versión 1.4.x del jdk y no se pueda migrar, en dicho caso es recomendable usar Axis2. Sin embargo, si el servidor tiene 1.5.x o superior de jdk no existe mejor opción que usar JAX-WS.
Para descargar Axis2 visitar : apache.org/axis2
Para descargar JAX-WS visitar: jax-ws.dev.java.net

Este post continuará ....

lunes, 16 de agosto de 2010

Cambiando el Skin (Look & Feel) a nuestros aplicativos Java

Otra vez vuelvo al ruedo .. estos últimos meses me he encontrado saturado a causa de la Universidad. Pues bien, ahora cuento con algo de tiempo y me he decidido por publicar un nuevo artículo, esta vez trataré sobre el uso de skins en aplicativos Java.
Esto a partir del proyecto que presentamos con unos amigos en la U,que a manera de anécdota lo programamos 2 personas en 4 días .. dejando, como siempre, todo para el final xD.

Volviendo a nuestro tema principal, empezaremos definiendo skin, luego mostraremos una serie de Screenshots de como se vería nuestro aplicativo java aplicandoles otros skins y por último la implementación.

Skin.- También llamado theme, tema o tapiz, son una serie de elementos gráficos que, al aplicarse sobre un determinado software, modifican su apariencia visual externa.
Estos elementos son independientes de la propia aplicación, con lo que esta puede tener, entre sus opciones, varias de estas pieles o ninguna, mostrando una apariencia estándar o más vistosa.

Diseño Visual Común de Java Swing

uni1.png

El diseño visual por default de una aplicación Java es la siguiente.





















Pero esta no es la única forma de presentar tu aplicativo Java Swing. Existen también las siguientes formas y muchas otras más:


Implementación:
En esta ocasión haremos que nuestra aplicación tome la apariencia del uso de Mac. Para que quede de la siguiente manera:
uni2.png


Se ve mucho mejor no...
Pues ahora explicaremos los pasos para llevarlo a cabo.
Primero tenemos que descargar la librería (.jar) liquidlnf
Segundo añadir la librería liquidlnf.jar a nuestra aplicación.
Por último, modificar el Main de nuestra aplicación de la siguiente forma.


package pedro.rios.main;

import com.birosoft.liquid.LiquidLookAndFeel;
import javax.swing.UIManager;

/**
 *
 * @author Pedro.Rios
 * @date 16/08/10
 */
public class Main{

   public static void main(String[] args) {
       try {
            //líneas para el cambio visual
            UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel");
            LiquidLookAndFeel.setLiquidDecorations(true, "panther");
            //LiquidLookAndFeel.setShowTableGrids(true);

            Principal tuFrame= new Principal();
            tuFrame.setVisible(true);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

/*
Para Otros temas:
swing.installedlafs = motif,windows,metal,mac,liquid
swing.installedlaf.motif.name = CDE/Motif
swing.installedlaf.motif.class = com.sun.java.swing.plaf.motif.MotifLookAndFeel
swing.installedlaf.windows.name = Windows
swing.installedlaf.windows.class = com.sun.java.swing.plaf.windows.WindowsLookAndFeel
swing.installedlaf.metal.name = Metal
swing.installedlaf.metal.class = javax.swing.plaf.metal.MetalLookAndFeel
swing.installedlaf.mac.name = Mac
swing.installedlaf.mac.class = com.sun.java.swing.plaf.mac.MacLookAndFeel
swing.installedlaf.liquid.name = Liquid
swing.installedlaf.liquid.class = com.birosoft.liquid.LiquidLookAndFeel
swing.defaultlaf=com.birosoft.liquid.LiquidLookAndFeel
*/


Ahora podemos apreciar lo fácil que es.. xD .. 2 líneas y listo. Espero les sirva para su desarrollo, se despide de ustedes y hasta la próxima publicación .... edisonjc7.

Demo Completa

miércoles, 30 de junio de 2010

Interceptores con Spring AOP

Hola a todos de nuevo.. estos días me he encontrado bastante ocupado por los parciales en la U y viendo trámites para sacar mi licencia de conducir (brevete) que ia sale :d. Ahora que todo está tranquilo en el trabajo me he animado por escribir un poco más acerca de Spring AOP, en este caso con sus Interceptores.  Estoy también analizando las propuestas que hacen en sus comentarios para futuros post.

Bueno había ya realizado un artículo en donde explicaba la forma de realizar métodos transaccionales con Spring AOP en transacciones-con-hibernate-y-Spring-AOP .
Ahora más bien veremos de lo que se tratan los interceptores y su utilidad en la bitácora de las aplicaciones en conjunto con log4j. Para empezar teóricamente definiremos el concepto de interceptor.


AOP son las siglas en ingles de Programación orientada al aspecto (Aspect Oriented Programming). Además, como sabemos la definición más simple de AOP es “una manera de eliminar codigo duplicado”. Un ejemplo práctico para la utilidad del AOP, es generar un interceptor, que inspeccionará el codigo que se va a ejecutar, permitiendo por lo tanto realizar ciertas acciones como : trazas cuando el método es llamado (bitácora), modificar los objetos devueltos o envio de notificaciones.


¿Qué es un interceptor?

Vimos hasta ahora que con Spring podemos delegar la creación de objetos, e inyectarles dependencias. Además, sabemos que usamos interfaces para castear los objetos que nos devuelve o inyecta Spring, de forma tal de poder lograr una real independencia de las implementaciones.
¿Qué pasaría entonces si, en tiempo de ejecución, se pudieran crear clases que intercepten los llamados y realicen acciones adicionales? Es decir, el poder agregar comportamiento en tiempo de ejecución, sin tocar el código.
Este es el concepto de los interceptores. Un interceptor es una clase que cumple con cierta interfaz, y su objetivo es "interponerse" en la ejecución de un método. Así, un interceptor es capaz de ejecutarse antes de un método dado, realizar acciones, y luego continuar con la ejecución normal (o abortarla).
Este tipo de concepto se conoce como Programación Orientado a Aspectos.

Un interceptor muy útil, por ejemplo, podría ser de log: algo que intercepte todas las llamadas a los objetos de Negocio y deje registrado la hora de la invocación, los parámetros, el valor de retorno, etc.


Configurando Nuestro Interceptor
Para configurar el Spring AOP con interceptor, nuestra aplicación deberá contar con las siguientes librerías:
  • spring.jar
  • log4j-1.2.14.jar
  • commons-logging-1.1.jar
  • cglib-2.1.jar
  • aopalliance.jar
  • aspectjrt.jar
  • aopalliance.jar
Todos estos y algunos más los puedes obtener en la siguiente dirección  download lib .

Configurando el applicationContext.xml

<beans xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
              ">
 
<!-- *********** INI :  DATASOURCE CONFIGURATION ************ -->    
    <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>   

 <!-- *********** INI : IBATIS CONFIGURATION  ************* -->   
   
     <!-- SqlMap setup for iBATIS Database Layer -->
    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation">
            <value>classpath:/gob/minedu/capacitacion/persistency/ibatis/sql-map-config-cxa.xml</value>
        </property>
        <property name="dataSource"><ref local="dataSource"/></property>     
    </bean> 

<!-- ************ INI: INTERCEPTOR DAO  ************** -->
<aop:config  proxy-target-class="true"> 
      <aop:pointcut id="businessOperation" expression="execution(* gob.minedu.capacitacion.*.dao.ibatisImpl.*.*(..))"/>
      <aop:advisor advice-ref="logInterceptor" pointcut-ref="businessOperation"/> 
</aop:config>

<bean id="logInterceptor" class="gob.minedu.shared.common.util.LogInterceptor"/>

<import resource="application-service.xml"/>

</beans>

Explicaremos lo relevante para este artículo.. las otras partes del applicationContext.xml han sido explicadas en anteriores artículos. Analizando la configuración del interceptor.

  • En vista de que no existe un TransactionManager es necesario poner proxy-target-class="true".

  • aop:pointcut : Punto de corte definido por patrones de nombres o expresiones regulares. La estructura de la expresión depende de la estructura de nuestra aplicación.

  • aop:advisor advice-ref="logInterceptor", referencia a la clase que implementa el aspecto. Se insertan en la aplicación en los Puntos de Corte.
Implementación de la clase interceptora LogInterceptor.java

package gob.minedu.shared.common.util;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;


/**
 * @author Pedro.Rios
 *
 */
public class LogInterceptor implements MethodInterceptor {
 private static final Logger log = Logger.getLogger(LogInterceptor.class);
 
 public Object invoke (MethodInvocation metodo) throws Throwable {
  
 log.debug("INI DAO: Clase Invocada "+metodo.getMethod().getDeclaringClass().getSimpleName() +" Metodo solicitado "+metodo.getMethod().getName());
 
 //Generamos la lista de argumentos que recibe el metodo separados por una coma   
    String arguments = new String();               
    for (int i = 0; i < metodo.getArguments().length; i++) {   
        arguments += metodo.getArguments()[i] + " ,";                
    }   
       
    // el metodo recibe al menos un argumento quitamos el espacio y la coma del final   
    if (arguments.length()> 0) {   
        arguments = arguments.substring(0, arguments.length() - 2);   
    }   
    log.debug("Argumentos: "+arguments);
 
 Object obj = metodo.proceed();
 log.debug ("FIN DAO: El método ha devuelto : "+obj);
 return obj;
 }
}
Definición del archivo log4j.properties
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.stdout.threshold=DEBUG

log4j.logger.org.ibatis=INFO
log4j.logger.org.apache=INFO
log4j.logger.org.springframework=INFO

#Sql: log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Connection=INFO
#Resultado sql: log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.ResultSet=INFO

Si no sabes como configurar el log4j y donde ubicar el archivo.properties puedes ver el web.xml del artículo  http://periospino.blogspot.com/2010/03/integrando-struts-spring-ibatis.html 
Con eso es suficiente para integrar Spring con Log4j.
De todas formas ya se viene un artículo explicando al detalle el uso de Log4j.

Para mayor informacíón:

Bueno amigos me despido y hasta la próxima publicación... Espero sus comentarios.

jueves, 3 de junio de 2010

Usando javaMail - API de envio de correos en Java

En el mundo del desarrollo de Sistemas de Información siempre existe la necesidad de enviar correos de distintas formas y maneras. En mi experiencia  profesional he necesitado de este medio en distintas ocasiones, como por ejemplo:


  • Al registrarse un usuario en el sistema de ventas, en el acto se le envía un email al usuario pidiéndole que confirme la existencia de su correo electrónico o también se le puede enviar el catálogo con los distintos productos que ofrece la empresa.

  •  Correos masivos a los distintos usuarios de nuestra base de datos.

  • Programar el envío automático de correos, en una especie de campaña de ventas.
Como podemos observar, en la actualidad, la importancia de el envío de correos desde el aplicativo tiene una importancia vital para la ejecución de las distintas estrategias de marketing y fidelización de clientes trazadas por las diferentes empresas.


Por esta razón, la siguiente pregunta cae por su propio peso : ¿Cómo podemos enviar correos electrónicos desde Java?

correos.jpg

Empezaremos este artículo definiendo al API JavaMail.

JavaMail se trata de una librería desarrollada por SUN encaminada al envío de correos electrónicos directamente desde tu aplicación Java. El uso de ésta librería es muy sencillo pero detallaremos paso a paso como realizar la instalación y uso de ella.
JavaMail implementa el protocolo SMTP (Simple Mail Transfer Protocol) así como los distintos tipos de conexión con servidores de correo -TLS, SSL, autentificación con usuario y password, etc.

JavaMail no se incluye en la JDK ni en la JRE, sino que debe conseguirse como un paquete externo.


Empezando a armar la Aplicación

Una vez descargado el API, añadimos el archivo mail.jar  v1.4.x a nuestro proyecto y de ser necesario también añadir activation.jar  v1.0.2 .

Pues bien, ahora procederemos a implementar un aplicativo que permita el envío de correos usando el protocolo SMTP de nuestra cuenta en gmail; sin embargo, si contamos con un servidor de correos personal será mucho mejor usar ese (dominio personal).


* Clases y métodos a utilizar

Clase Properties: Ésta clase es la encargada de almacenar las propiedades de la conexión que vamos a establecer con el servidor de correo Saliente SMTP.
Propiedades a utilizar:
  1. Protocolo a utilizar para el envío de correos.
  2. Dirección del servidor de correo.
  3. Indicar si se necesita autenticar o no.
  4. Puerto SMTP.
  5. Valor booleano de habilitación TLS.
  6. Email del emisor del mensaje.
  7. Usuario de acceso al servidor SMTP
Clase Session: De alguna forma representa la conexión con el servidor gmail de correo. Hay que obtenerla pasándole los parámetros de configuración para el servidor de correo - gmail en nuestro caso-.

Clase MimeMessage: Aquí formaremos el mensaje que deseamos enviar.


Clase Transport: Clase para el envío de mensajes.

 
* Aplicativo para el envío de correos

Archivo smtp.properties : Archivo que contiene los parámetros de configuración.Ubicado en el paquete src/resource

#SMTP configuration
mail.transport.protocol=smtp
mail.host=smtp.gmail.com
mail.smtp.auth=true
mail.smtp.port=465
mail.smtp.socketFactory.port=465
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.socketFactory.fallback=false
mail.smtp.quitwait=false
mail.smtp.mail.sender=tuCorreo@gmail.com
mail.user=tuCorreo@gmail.com
mail.password=tuClaveGmail
mail.email=tuCorreo@gmail.com

Clase SMTPConfig.java : Clase reutilizable para el envío de email.
package pedro.rios.mail;

import java.security.Security;
import java.util.Properties;
import java.util.ResourceBundle;

import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


/**
 * @author pedro Rios
 * @date 10/12/09
 * 
 */
public class SMTPConfig {

/**
  * @param titulo : titulo del mensaje
  * @param mensaje : Cuerpo del Mensaje
  * @param paraEmail : Email receptor del mensaje
  * @return true si el envío es conforme y false si no es así.
  */
 
 public static synchronized  boolean sendMail(String titulo, String mensaje, String paraEmail) { 
  boolean envio=false;
  
  try {
   
   //carga del archivo smtp.properties
   final ResourceBundle  props = ResourceBundle.getBundle("resource.smtp");
   
   Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
   
   //Propiedades de la conexion
   Properties propiedades = new Properties();
   propiedades.setProperty("mail.transport.protocol",  props.getString("mail.transport.protocol"));
   propiedades.setProperty("mail.host",props.getString("mail.host"));
   propiedades.put("mail.smtp.auth",props.getString("mail.smtp.auth"));
   propiedades.put("mail.smtp.port",props.getString("mail.smtp.port"));
   propiedades.put("mail.smtp.socketFactory.port",props.getString("mail.smtp.socketFactory.port"));
   propiedades.put("mail.smtp.socketFactory.class",props.getString("mail.smtp.socketFactory.class"));
   propiedades.put("mail.smtp.socketFactory.fallback",props.getString("mail.smtp.socketFactory.fallback"));
   propiedades.put("mail.smtp.mail.sender",props.getString("mail.smtp.mail.sender"));
   
   propiedades.setProperty("mail.smtp.quitwait",props.getString("mail.smtp.quitwait"));
   
   //Preparamos la Sesion autenticando al usuario
   Session session = Session.getDefaultInstance(propiedades,new javax.mail.Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication(){ 
     return new PasswordAuthentication(props.getString("mail.user"),props.getString("mail.password"));
    }
   });
   
   //Preparamos el Mensaje
   MimeMessage message = new MimeMessage(session);
   message.setSender(new InternetAddress(props.getString("mail.email")));
   message.setSubject(titulo);
   message.setContent(mensaje, "text/html; charset=utf-8");
   message.setFrom(new InternetAddress(props.getString("mail.smtp.mail.sender")));
   message.setReplyTo(InternetAddress.parse(props.getString("mail.smtp.mail.sender")));
  
  
   if (paraEmail.indexOf(',') > 0) 
    message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(paraEmail));
   else
    message.setRecipient(Message.RecipientType.TO, new InternetAddress(paraEmail));
   
   //envío del mensaje
   Transport.send(message);
   envio = true;
  
  } catch (Throwable e) {
   envio = false;
   System.out.println(e.getMessage());
   e.printStackTrace();
  
  }finally{
   return envio;
  }
 }
}


Clase de Prueba de envío de correo PruebaMail.java
package pedro.rios.mail;

public class PruebaMail {

 public static void main(String[] args) {
  
  if(SMTPConfig.sendMail("Asunto del Mensaje"," Cuerpo del Mensaje.","destino@gmail.com")){
  
   System.out.println("envío Correcto");
   
  }else System.out.println("envío Fallido");

 }

}


Listo eso es todo. Solo nos queda ejecutar la clase PruebaMail.java ...

Para mayor información les dejo el link para descargar el libro Java Mail en Ejemplos de la Universidad de Málaga. .... Bueno amigos espero sus comentarios.. se despide de ustedes edisonjc7.


martes, 11 de mayo de 2010

Modelación y generación de Scripts MySql con DBDesigner 4

DBDesigner es una herramienta CASE optimizada para mysql de similar funcionalidad que el conocido ERWIN, en lo personal DBDesigner se ha convertido en mi herramienta preferida para el modelamiento  en general de base de datos y generación de Scripts de Base de Datos Mysql en el proceso de análisis e ingeniería de Software.

Tanto si lo que buscas es una herramienta para practicar o para aprender a manejar mysql, como si tus necesidades son más ambiciosas, estás ante uno de los entornos de diseño gráfico de bases de datos más sencillo y a la vez, completo y eficaz del mercado, además ha sido desarrollado y publicado bajo licencia GNU, lo que te permitirá utilizarlo sin limitaciones.

Yo personalmente uso la herramienta para modelar la base de datos en general, generar el script mysql y obtener el diccionario de datos. En dichas opciones la herramienta funciona de maravillas.

Además soporta multitud de opciones que aún no he probado, entre las que se encuentran:
  • Modo consulta.
  • Ingeniería inversa de bases de datos MySQL, Oracle, MSSQL y cualquiera con driver ODBC.
  • Control de versiones.
  • Constructor de queries.

Imagen de DBDesigner
dbdesigner.jpg


Viendo algunas funciones del DBDesigner

  1. Generación del Script Mysql
  2. Para generar los scripts mysql dar clic en File/Export/SQL Create Script.. como muestra la imagen. exportar1.jpg
    Luego se mostrará la siguiente pantalla.
    exportar2.jpg   
  3. Generación del Diccionario de Datos
  4. diccionario1.jpg
diccionario2.jpg


Para mayor información

Bueno me despido de ustedes.. esperando les pueda servir la info proporcionada.. saludos se despide su amigo  edisonjc7.. por fin me toca vacaciones en la chamba xD.. Chauuu!.

sábado, 1 de mayo de 2010

Generación de Ejecutables para proyectos Java Swing

Me encontraba realizando un aplicativo Cliente - Servidor en Java Swing JSE para una entidad educativa, el aplicativo era bastante vistozo y amigable, implementaba el patrón DAO (lo reutilizaba de un proyecto web existente) y base de base de datos Mysql5 centralizada. Cuando por fin terminé el desarrollo del aplicativo necesitaba generar un ejecutable que permita acceder al él sin problemas desde c/u de las PC's cliente. Para ser más precisos este aplicativo constaba de varias librerías como son los jars (ireport, los commons, el jar de conexión y muchos otros más).


Pues buscando en la internet no hacia otra cosa que confundirme aún más, decían que tenía que generar el jar y luego modificar el archivo de manifiesto e incluir las librerías utilizadas; esta forma de generar el archivo ejecutable era bastante rudimentaria y complicada... Hasta que me tope con una herramienta casi milagrosa que me simplificaba la vida totalmente (más aún la de un programador xD) ... Pues con ustedes el plug-in para eclipse Fat Jar.

Lo pueden descargar desde aquí .

Instalación
Para instalarlo deberás copiarlo en la carpeta plugins de tu eclipse. (Lo he probado en la versión Ganymede sin problemas). Reinicias tu eclipse y listo.
Una vez instalado el eclipse te dará la siguiente opción al dar clic derecho sobre el proyecto a generar el ejecutable.

fatjar.jpg


Uso
Su uso es bastante simple y la generación de los ejecutables es del tipo Wizard.

Bueno mis amigos espero sus comentarios.... chau!!! ...y Feliz día del Trabajador les desea su amigo edisonjc7, siempre trabajando xD.

Para mayor información
Tutorial Fat-Jar

viernes, 23 de abril de 2010

Reportes en Excel con JexcelApi

Siempre existe la duda entre los desarrolladores java, de como empezar a tratar documentos Excel desde el lenguaje Java. Sea en la lectura o escritura de los mismos.
El uso masivo de archivos e informes en excel en las distintas empresas.. obligan al desarrollador estar en la capacidad de emitir reportes en excel desde una aplicación Java. Esto permitirá poder combinar la capacidad de información de una base de datos en una presentación amigable y conocida como son los archivos Excel.
Es por ello, la necesidad de dar a conocer JexcelApi  una poderosa herramienta, muy útil para manejar los parámetros y valores de la conocida hoja Excel desde un programa Java. También es necesario dar a conocer que existe el proyecto Jakarta POI para el tratamiento de archivos en formato microsoft.


excel.jpg


JavaEE con JExcelApi - jxl

Para empezar a usar jexcel desde java .. tendremos que colocar la librería jxl.jar a nuestro aplicativo. Dicha librería la podemos descargar desde sourceforge.net . Personalmente recomiendo usar esta API antes que POI para el tratamiento de archivos excel.

Veremos la sintaxis de uso .. mediante un ejemplo de escritura de excel bastante simple.

log.info("Entrando ... reporteCertificados()");
  
  OutputStream out = null;

  try{

   res.setContentType("application/vnd.ms-excel");
   res.setHeader("Content-disposition", "attachment; filename=\"ParaCertificados.xls\"");
   res.setHeader("Content-type", "application/vnd.ms-excel");
   
   //ini:formato
   WritableFont cabeceraFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD, true);
   WritableFont cuerpoFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false);
   WritableFont domicilioFont = new WritableFont(WritableFont.ARIAL, 9, WritableFont.NO_BOLD, false); 
   
   WritableCellFormat fCabecera = new WritableCellFormat(cabeceraFont);
   fCabecera.setAlignment(Alignment.JUSTIFY);
   fCabecera.setVerticalAlignment(VerticalAlignment.CENTRE);
   fCabecera.setBackground(Colour.CORAL);
   fCabecera.setBorder(Border.ALL,BorderLineStyle.THIN);
   
   WritableCellFormat fCuerpo = new WritableCellFormat(cuerpoFont);
   fCuerpo.setAlignment(Alignment.LEFT);
   fCuerpo.setBorder(Border.ALL,BorderLineStyle.THIN);
   
   WritableCellFormat fCuerpo2 = new WritableCellFormat(domicilioFont);
   fCuerpo2.setAlignment(Alignment.LEFT);
   fCuerpo2.setBorder(Border.ALL,BorderLineStyle.THIN);
   
   //fin:formato
   
   WritableWorkbook w = Workbook.createWorkbook(res.getOutputStream());
   WritableSheet s = w.createSheet("Informe", 0); //Nombre de hoja

   s.setColumnView(0,10);//ini:seteamos el ancho de las columnas 
   s.setColumnView(1,20);
   s.setColumnView(2,20);
   s.setColumnView(3,20);
   s.setColumnView(4,25);
   s.setColumnView(5,10);
   s.setColumnView(6,15);
   s.setColumnView(7,15);
   s.setColumnView(8,10);
   s.setColumnView(9,10);
   s.setColumnView(10,30);
   s.setColumnView(11,20);
   s.setColumnView(12,20);

  //ini: armando el excel
   s.addCell(new Label(0, 0, "Nº",fCabecera)); //añadiendo celdas
   s.addCell(new Label(1, 0, "Nro. Certificado",fCabecera));
   s.addCell(new Label(2, 0, "Apellido Paterno",fCabecera));
   s.addCell(new Label(3, 0, "Apellido Materno",fCabecera));
   s.addCell(new Label(4, 0, "Nombres",fCabecera));
   s.addCell(new Label(5, 0, "DNI",fCabecera));
   s.addCell(new Label(6, 0, "Fecha Inicio",fCabecera));
   s.addCell(new Label(7, 0, "Fecha Fin",fCabecera));
   s.addCell(new Label(8, 0, "Año",fCabecera));
   s.addCell(new Label(9, 0, "Horas",fCabecera));
   s.addCell(new Label(10, 0, "Región",fCabecera));   
 
   List<map> lstData = serviceFactory.getReporteService().getDataReporte(Long.valueOf(IdTaller));
   
   int i=1;
   for(Map map:lstData){
    s.addCell(new Number(0,i, Integer.parseInt(map.get("ORDEN").toString()),fCuerpo));
    s.addCell(new Label(1, i, StringUtils.EMPTY,fCuerpo));
    s.addCell(new Label(2, i, map.get("APE_PAT").toString(),fCuerpo));
    s.addCell(new Label(3, i, map.get("APE_MAT").toString(),fCuerpo));
    s.addCell(new Label(4, i, map.get("NOMBRES").toString(),fCuerpo));
    s.addCell(new Label(5, i, map.get("DNI").toString(),fCuerpo));
    s.addCell(new Label(6, i, map.get("DIA_INI").toString()+ " de "+Utils.getMesLetras(new Integer(map.get("MES_INI").toString())) ,fCuerpo));
    s.addCell(new Label(7, i, map.get("DIA_FIN").toString()+ " de "+Utils.getMesLetras(new Integer(map.get("MES_FIN").toString())),fCuerpo));
    s.addCell(new Label(8, i, map.get("ANIO").toString(),fCuerpo));
    s.addCell(new Label(9, i, map.get("HORAS").toString(),fCuerpo));
    s.addCell(new Label(10, i, map.get("REGION").toString(),fCuerpo2));

    i++;
   }
   //fin:armando el excel
   
   w.write();
   w.close();
   
   
  } catch (Exception ex) {
   log.error(ex.getMessage(),ex);
   sendErrorMessage(req,"errors.excel.load");
  } finally {
   if (out != null)
       out.close();  
  }

  log.info("Saliendo ... reporteCertificados() - Reportes");
return null;




Para Profundizar en el Tema

Bueno espero que les sirva la información proporcionada ... se despide su amigo edisonjc7.. y como dice un amigo ... "seguiremos socializando el conocimiento" xD... chau

viernes, 16 de abril de 2010

Procedures y Cursores en Mysql

Un Stored Procedure o Procedimiento Almacenado es un programa (o función) que se almacena físicamente en una base de datos.Su implementación varía de un manejador de bases de datos a otro. En la mayoría de los casos, no obstante, los stored procedures permiten definir una API (capa de abstracción) para que el gestor de bases de datos interactúe con tablas u otros objetos de la base de datos, en vez de tener un cliente de la aplicación interactuando directamente.
Aunque la mayoría de los gestores de bases de datos existentes brindan soporte para estos procedimientos, existe discusión entre los desarrolladores acerca de las ventajas de su uso.
Por eso empezaremos este post definiendo las ventajas y desventajas del uso de Stored Procedures.
Cabe mencionar que el uso de procedimientos almacenados depende muchas veces de la arquitectura del sistema y del alcance del mismo.

db-java.jpg

Ventajas

Es notorio que existen más ventajas que desventajas en el uso de procedimientos.

  • Es ejecutado directamente en el motor de bases de datos, el cual usualmente corre en un servidor separado. Como tal, posee acceso directo a los datos que necesita manipular y sólo necesita enviar sus resultados de regreso al usuario, deshaciéndose de la sobrecarga resultante de comunicar grandes cantidades de datos salientes y entrantes.

  • Encapsulamiento de un proceso complejo o que podría requerir la ejecución de varias consultas SQL, tales como la manipulación de un gran conjunto de datos para producir un resultado resumido. Esto reduce la necesidad de codificar lógica innecesaria en el programa cliente y tener un mejor manejo de la capa de negocio de nuestra aplicación.

  • Centralización de la definición, al formar parte de la base de datos los procedimientos almacenados están en un lugar centralizado y pueden ser ejecutados por cualquier aplicación que tenga acceso a la misma. Evitando la excesiva declaración de procedimientos de ejecución en el gestor de bases de datos; ya que puede ser perjudicial para el rendimiento del servidor.

  • Reducción del tráfico de red, una sentencia formada por decenas, cientos o incluso miles de líneas de código SQL puede escribirse como un procedimiento almacenado en el servidor y ejecutarse simplemente mediante el nombre de dicho procedimiento.
Desventajas

Como lo mencione en un principio el uso de los procedures depende mucho de la arquitectura y alcance del sistema. En una arquitectura multi-base de datos en donde la información deberá ser manejada en distintos motores de base de datos sea MySql, Postgresql, Oracle, Sql Server, etc.O en una arquitectura en donde querramos migrar después a otro motor de base de datos. No conviene el uso de procedures de ninguna manera.


  • Reducción de la escalabilidad: Los procedimientos almacenados nos esclavizan al motor de base de datos. Para migrar de un gestor de base de datos con muchos procedimientos almacenados a otro, se deberá reescribir casi la totalidad de los mismos. Esto se debe, principalmente, a que los lenguajes de procedimientos almacenados de distintos fabricantes no son compatibles entre sí.

Teniendo en cuenta las ventajas y desventajas es aconsejable no abusar de los procedimientos almacenados y utilizarlos sólo cuando su aplicación sea realmente efectiva y el alcance del sistema este bien definido. Con respecto al uso de los procedures siempre habrá controversia entre los desarrolladores.


Implementación y Sintaxis en Mysql 5

Desde MySQL 5 los procedimientos almacenados empezaron a ser soportados.
Son implementados desde la aplicación mediante CALL nombre_procedure (…parametros).

Voy a poner un par de ejemplos definiendo la sintaxis de creación de un procedure y dentro de él el uso de cursores en mysql. La finalidad de estos procedures es lo de menos, lo que nos interesa es la sintaxis para poder desarrollar nuestros propios procedimientos, con lógica a medida de nuestras necesidades.

Nota: El uso del cursor sirve para recorrer uno por uno los registros del resultado de la select y poder hacer operaciones con ella. Es como recorrer una lista con un for java y hacer operaciones con cada registro.


Ejemplo 1.- Definimos un procedure con 2 parámetros de entrada, variables que nos permitirán el desarrollo de nuestra lógica, el cursor que nos permitirá recorrer uno a uno el resultado de la select, y el retorno de una cadena que será procesada posteriormente por el programa cliente.

-- en esta línea eliminamos el procedure de la base de datos si existe.
DROP PROCEDURE IF EXISTS `nombreBD`.`cur_pagination_SP`;
DELIMITER \\

--definiendo la creación del procedure con 2 parametros de entrada 
CREATE PROCEDURE `nombreBD`.`cur_pagination_SP` ( IN v_id_taller INTEGER,
                                                  IN v_pagination INTEGER )
    READS SQL DATA
BEGIN
--declaración de variables
DECLARE l_last_row INT DEFAULT 0;
DECLARE v_ape_pat VARCHAR(255);
DECLARE contador int default 0;
DECLARE rpt VARCHAR(300) default '';

--declaración del cursor de nombre ´cursor1´
DECLARE cursor1 CURSOR FOR
SELECT u.ape_pat 
FROM tb_usuario u
WHERE NOT EXISTS (
       SELECT * FROM tb_cabecera ci
       WHERE  u.id_usuario = ci.id_usuario and 
              ci.id_capacitacion = v_id_taller
) AND u.is_deleted !=1 and u.perfil in ('E','D')
ORDER BY u.ape_pat ASC;

--Flag que permitirá saber si existen más registros por recorrer
DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_last_row=1;

--abrimos el cursor para empezar a recorrerlo
OPEN cursor1;
c1_loop: LOOP
    -- cada registro se le otorga a la variable 'v_ape_pat'
    FETCH cursor1 INTO v_ape_pat;
        IF (l_last_row=1) THEN
            LEAVE c1_loop;
        END IF;

        --lógica propia de este procedure
        if contador%v_pagination = 0 then
          SET rpt = CONCAT(rpt,substring(v_ape_pat,1,1));
        end if;

        SET contador = contador + 1;

END LOOP c1_loop;

--cerramos el cursor y retornamos el dato que nos interesa en este caso la variable 'rpt'
CLOSE cursor1;
SELECT rpt;

END\\
DELIMITER;



Ejemplo 2.- A diferencia del primer ejemplo veremos como crear dos cursores dentro del mismo procedure.

DROP PROCEDURE IF EXISTS `nombreBD`.`porcentaje_SIS_CAP`;
DELIMITER \\

CREATE PROCEDURE `nombreBD`.`porcentaje_SIS_CAP` ( IN v_id_cabecera INTEGER)
    READS SQL DATA
BEGIN

DECLARE l_last_row INT DEFAULT 0;
DECLARE v_cantidad INT DEFAULT 0;
DECLARE v_total INT DEFAULT 0;
DECLARE v_nota VARCHAR(5) default '';
DECLARE rpt VARCHAR(150) default '';

--declaración del primer cursor
DECLARE cur_total CURSOR FOR
SELECT
    COUNT(*) AS 'CANTIDAD'
FROM tb_cabecera a
INNER JOIN tb_inscripcion c ON a.id_cabecera=c.id_cabecera
WHERE a.id_cabecera = v_id_cabecera
GROUP BY c.nota;

--declaración del segundo cursor
DECLARE cur_calculo CURSOR FOR
SELECT
    c.nota_evalua  AS "NOTA",COUNT(*) AS 'CANTIDAD'
FROM tb_cabecera a
INNER JOIN tb_inscripcion c ON a.id_cabecera=c.id_cabecera
WHERE a.id_cabecera = v_id_cabecera
GROUP BY c.nota
ORDER BY c.nota_evalua ASC;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_last_row=1;

OPEN cur_total;
REPEAT
    FETCH cur_total INTO v_cantidad;
    IF not l_last_row THEN
       SET v_total = v_total + v_cantidad;
    END IF;   
UNTIL l_last_row END REPEAT;

CLOSE cur_total;

SET v_cantidad = 0;
set l_last_row = 0;

OPEN cur_calculo;
c2_loop: LOOP
    FETCH cur_calculo INTO v_nota,v_cantidad;
    IF l_last_row THEN
        LEAVE c2_loop;
    END IF;
SET rpt = CONCAT(rpt,'&',v_nota,'-',v_cantidad,'-',(v_cantidad/v_total)*100,'-',v_total);

END LOOP c2_loop;
CLOSE cur_calculo;

SELECT rpt;

END\\
DELIMITER;


Espero que les pueda servir este post para la mejor toma de decisiones, al momento de definir la arquitectura de su aplicación. Saludos a todos.... se despide su amigo edisonjc7 .. no sin antes dejarles un regalillo para los amantes del mysql .. jeje xD..

Un regalillo para todos los seguidores de Mysql

La biblia del Mysql - Download

Manual de Referencia en Español - Download


jueves, 8 de abril de 2010

Desarrollador Java Certificado por Sun Microsystems - SCJP

Empezare este post planteando la siguiente pregunta : ¿Para qué nos sirve esta certificación? ...

Java es el lenguaje de moda, todas las empresas están reclutando analistas/programadores en Java. Hace algunos años no había mucha gente con estos conocimientos, por lo que colocarse en el mundo laboral era relativamente fácil. Ahora hay mucha gente preparada y esta certificación puede diferenciar tu Hoja de Vida frente a la de los demás.

Además el hecho de prepararse para esta certificación te dará nuevos conocimientos y te permitirá acreditar esos conocimientos con un cartón.

En resumen, la certificación Java junto con un buen currículum te otorgará la llave para realizar muchas entrevistas de trabajo, y acceder a un buen salario.



Por dónde empezar?

  • Primero adquirir el voucher .- Es un documento digital, que tiene un número que lo identifica, cuando adquieres el voucher lo único que interesa es dicho número. En el Perú te puedes contactar con la empresa CJAVA, un asociado de negocios de Sun, para adquirir tu voucher. Se sabe que el costo normal  del voucher es de 300$ según la web de Sun; pero aveces existen promociones, como ejemplo puedo indicar que accedí a un voucher con la opción retake(doble) por la suma de 150$. Es por ello la importancia de ponerse en contacto con CJAVA. email de contacto: elizabeth.bazalar@cjavaperu.com

  • Registrarse en Prometric.- Una vez que accedes al código del voucher, tienes que registrarte y programar tu examen en la web de Prometric (Centro para la aplicación de exámenes de Certificación Internacional en Tecnologías).

  • Rendir el examen.- Vas a la institución donde has programado el examen 30 minutos antes con tu DNI, firmas algunos documentos que indican las politicas del examen y al culminar te entregan tu reporte que indica si has aprobado o no y los temas del examen con un porcentage de evaluación sobre cada uno de ellos.

  • Solo Si aprobaste deberás validar tu dirección desde CertManager para que te envíen el certificado. Por último solo te queda esperar el certificado xD.

Cómo Prepararme?
Primero debes tener en cuenta que el SCJP es requisito para todas las demás certificaciones Java. Por ello su obtención es crucial. Código del examen 310-055 ó 310-065.


Libros altamente Recomendables.
Para rendir el examen deberás conocer los siguientes aspectos:
  • Language Fundamentals
  • Declarations and Access Control
  • Object Orientation
  • Assignments
  • Operators
  • Flow Control, Exceptions, and Assertions
  • Strings, I/O, Formatting, and Parsing
  • Generics and Collections
  • Inner Classes
  • Threads
  • The java.lang and java.util Packages

Otros apuntes: Es recomendable rendir el examen en inglés para evitar problemas en la traducción. El examen según veo puede ser como sigue bien 210 minutos / 72 preguntas / 59% pass score o bien 180 minutos / 60 preguntas / 55% pass score.

Acá les dejo los libros con los que me preparé para rendir el SCJP con éxito ... Bueno mis estimados javeros hasta la próxima publicación y espero consigan la ansiada certificación. xD saludos..

Download

Download

jueves, 1 de abril de 2010

Existe web hosting para java?.. en la internet

Me encontraba realizando un trabajo en condición de freelance.. cuando surgió la interrogante.. existe web hosting para java? en la nube ... Buscando en la web y por referencias de algunos contactos me tope con dailyrazor.com ...

Pues me puse a averiguar cual era el servicio que brindaban y viendolo bien respondia a mis expectativas de colgar un aplicativo web con Struts,Spring, Ibatis,Quartz, JavaMail y Log4j...

Pues nos animamos en adquirir el plan  Developer Hosting - Java Hosting - Private Tomcat Plans; y para que el servidor web respondió lo suficientemente bien como para estar satisfechos con la compra.



Por qué nos animamos adquirir el servicio en dailyrazor.com

  • Private Tomcat 5.x/6.x, JDK 1.5/1.6, Java 5/6, J2EE, JSP/Servlets support
  • Struts, Spring, JSF, Hiberenate, All Tomcat Frameworks supported
  • Tomcat Manager, Tomcat Admin, JNDI, JDBC, JavaMail, Log4J, WAR File Deployment Supported
  • Start/Stop Tomcat via SSH or Web based Console
  • MySQL, PostgreSQL, MS SQL Server Database supported on all plans
  • Host multiple Java web applications, domains, and JSP/Servlets sites
  • PHP, Perl, Python, CGI languages supported!
  • Panel de Control bastante amigable

Parte del Panel de Control:



Para mayor información sobre el plan adquirido dailyrazor.com/java/private_tomcat

Espero les sea útil esta info... se despide su amigo edisonjc7... ahora saldré con unos amigos a disfrutar de los feriados por semana Santa.. Saludos xD

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