Lazy Loading: Primefaces

Otro sabor de JSF es Primefaces, si bien es una suite bastante nueva, ha tenido bastante aceptación por gran parte de programadores JSF por su fácil utilización y que se integra muy bien con JSF 2.0.

Si bien ya había explicado como realizar lazy loading con ICEfaces (de forma similar tambien se hace con Richfaces) en esta ocasión mostrare como se realiza con Primefaces, que ya trae una funcionalidad especifica para el cometido.

Basandome en la entrada sobre JSF y Spring nada mas me concentrare en implementar la solución sobre el managed bean.



Luego en la pagina xhtml



El resultado sera el siguiente



Puede notarse que al momento de la ejecución es mucho mas rápida que la hechiza en ICEfaces, ya que es propia del framework.

Adjunto codigo fuente para efectos de estudio.

Comentarios (2)

Lazy Loading en ice:dataTable con ICEfaces

¿Que és lazy loading? pues traduciendolo a mi manera en español podria referirse a carga ociosa, es decir carga ociosa de datos. ¿para que se utiliza? sucede que cuando se utiliza un dataTable con JSF siempre se le envia la lista completa de registros que se obtienen de una busqueda en la base de datos y los carga todos de una vez en la tabla para usarlos con un paginador, ¿pero que sucede si tenemos una busqueda de miles de registros? no podemos carga toda esa lista en el dataTable, entonces surge la necesidad de solo traer que necesitamos ver en el paginador por bloques.

Algunos diran que ya existe un articulo en la documentación oficial de ICEfaces para realizar un lazy loading, pero el punto es que es muy dificil de entender ya que agregan otras funcionalidades que estan demas y mi objetivo es simplificar el entendimiento de la técnica.

En esta ocasión utilizare netbeans, tomcat y spring para el acceso a datos.

Utilizare tambien la tabla "Manufacturer" de la base de datos derby "Sample" embebida en netbeans, ya que es la unica que tiene algunos cuantos registros para efectos de prueba.

No entrare en detalle de como configurar un proyecto JSF con ICEfaces ni de como integrarlo con Spring para el acceso a datos, supondre que se ha leido las entradas respectivas.

Suponiendo que ya se ha generado el entity de la tabla Manufacturer creo mi acceso a datos.



Luego la implementación



Luego creo mi configuracion en spring



Ahora la parte fundamental es crear un custom DataModel



Ahora me dedico a crear los managed beans.





Por ultimo el diseño de la página xhtml



El resultado sera el siguiente

A través del trace se puede observar que por cada vez que se cambia de pagina se obtiene el bloque de registros que interesa.

Adjunto el codigo fuente para efectos de estudio.

Comentarios (2)

Manejo de errores y validaciones en Swing

Si bien ya explique como manejar los errores en JSF apoyandonos en Richfaces, en esta ocasión explicare como se realiza en aplicaciones de escritorio utilizando swing. Lo primero es crear el manejador de excepciones que utilizara swing que debe de heredar de la clase EventQueue.



Luego realizamos nuestras excepciones personalizadas heredando de RuntimeException, el objetivo de crear nuestras propias excepciones es para poder categorizarlas y realizar acciones especificas en función de estas.

Para este ejemplo he creado un JFrame llamado FrameException.java el cual contiene el método main, antes de ejecutar el formulario principal de la aplicación se debe configurar el manejador de excepciones.

Luego hago el diseño del formulario


Ahora realizo las validaciones en el boton "Aceptar"

Ahora agrego un error a proposito en el boton "Produce error".


Adjunto el codigo fuente para efectos de estudio.

Comentarios (0)

Manejo de errores y validaciones con JSF 2.0 y Richfaces 4.0

En esta ocasión es desarrollare un ejemplo en el cual se explica la forma en la cual se deben de manejar las excepciones o validaciones personalizadas en una aplicación JSF y con ayuda de Richfaces. La importancia de controlar las excepciones es por el hecho que nuestra aplicación pueda recuperarse por si misma ante cualquier eventualidad como por ejemplo una caida de base de datos. Este ejemplo lo hice en eclipse ya que no tenia un Netbeans a la mano, así que no entrare en detalles sobre como configurar un proyecto web con JSF 2.0 y Richfaces 4.0 sobre eclipse. El ejemplo tratara sobre un simple login de usuario, para el cual he creado la clase User.java
 
Luego creo mis mensajes personalizados, ya que es una buena costumbre en cualquier tipo de aplicación ya sea de escritorio, web o incluso de línea de comandos por consola.
 

Luego configuro mis mensajes personalizados en el archivo faces-config.xml
 
Procedo a crear mi Excepcion personalizada para validaciones muy detalladas.
Creo la clase AbstractManagedBean.java para metodos comunes entre los demás managed beans.
Creo un managed bean el cual se encargara exclusivamente de realizar el render de mensajes de sistema.
Ahora creo el managed principal que se encargara de validar el login de usuario.
Por ultimo realizo el diseño de la pagina xhtml.
 
La estructura del proyecto sera la siguiente



El resultado sera el siguiente.



Adjunto el codigo fuente del proyecto para efectos de estudio.

Comentarios (2)

Spring 3.0 y JSF 2.0

Hace poco me había planteado la necesidad de utilizar una capa de servicios potente como EJB 3.0 pero sin utilizar un servidor de aplicaciones sino un simple tomcat, ya que este no es un contenedor de EJB. Así que me decidi por la combinación Spring 3.0 y JSF 2.0, la reseta de implementación JPA 2.0 para Spring utilizare Hibernate. Aca desarrollare un ejemplo de como utilizar las dos tecnologías antes mencionadas. Antes que nada es necesario configurar un datasource el cual accederemos desde spring vía jndi, para el ejemplo accederemos a la base de datos derby que esta embebida con netbeans. En el archivo contex.xml del tomcat creamos el datasource.
 
Ahora procedemos con la capa de acceso a datos generando los entities de las tablas "customer" y "discount_code". Modificamos el archivo persistence.xml que debera quedar de la siguiente manera:
Creare la interfaz con la con la cual las transacciones de spring funcionaran
 
Luego creo la implementación
 
 El siguiente paso es configurar el archivo de spring applicationContex.xml en la ubicación WEB-INF
Ahora vamos con la parte de la vista. Se debe configurar el proyecto web para que JSF pueda interactuar con Spring. Se agregan las siguientes líneas en el archivo web.xml:
 
 Luego se debe configurar el archivo faces-config.xml para que spring pueda realizar inyección de dependencias a través de el lenguaje de extextareasiones de JSF, se debe crear sino existe.
Luego creo el managed bean
 
Por ultimo desplegamos la java.util.Lista "customers" del managed bean en nuestra página xhtml
El resultado sera el siguiente
Adjunto el código fuente para efectos de estudio.

Comentarios (1)opiniones, ¿cual es la tuya?

Swing Beans Binding JSR 295

Siempre me había llamado la atención poder enlazar componentes de swing con algún objeto o lista de objetos de manera similar a como se realiza con JSF. Este no es un tema nuevo ya que se puede realizar desde ya hace bastante pero la mayoria de personas (al menos las que programan aplicaciones de escritorio en java) lo desconocen.

En esta ocasión realizare un ejemplo basandome en la entrada anterior sobre Spring 3.0 e Hibernate, en el cual ya he generado el acceso a datos.

El ejemplo que desarrollare sera un pequeño CRUD e utilizare las herramientas Netbeans 7.0, Spring 3.0 e Hibernate 3.6.7

Mi clase de acceso a datos es la siguiente:

package org.dani.ejemplo.jpa.dao;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import java.util.*;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
 *
 * @author dherrera
 */
public class DerbyDAOImpl extends JpaDaoSupport implements DerbyDAO{

    @Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
    public List getAllProducts() {
        return getJpaTemplate().find("Select p From Product p order by p.productId desc");
    }

    @Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
    public List getAllManufacturer() {
        return getJpaTemplate().find("Select m From Manufacturer m");
    }

    @Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
    public List getAllProductCode() {
        return getJpaTemplate().find("Select p From ProductCode p");
    }

    @Transactional(propagation=Propagation.REQUIRES_NEW,readOnly=false)
    public Product updateProduct(Product p) {
        return getJpaTemplate().merge(p);
    }

    public Integer getNewProductId() {
        javax.persistence.EntityManager em=getJpaTemplate().getEntityManagerFactory().createEntityManager();
        javax.persistence.Query q=em.createQuery("select max(p.productId)+1 from Product p", Integer.class);
        return (Integer) q.getSingleResult();
    }

    @Transactional(propagation=Propagation.REQUIRES_NEW,readOnly=false)
    public Product addProduct(Product p) {
        return updateProduct(p);
    }

    @Transactional(propagation=Propagation.REQUIRES_NEW,readOnly=false)
    public void deleteProduct(final Product p) {
        getJpaTemplate().remove(getJpaTemplate().getReference(Product.class, p.getProductId()));
    }
}


Obtengo las listas de tipo observable de productos y listas simples para manufacteros y códigos de producto con sus respectivos getters y setters para que los componentes dentro del formulario principal FrameBinding.java puedan accesar a ellas en el contructor del formulario.

public FrameBinding() {
        ctx = new ClassPathXmlApplicationContext("/org/dani/ejemplo/jpa/applicationContext.xml");
        dao = (DerbyDAO) ctx.getBean("dao");
        fillModelTable();
        manufacturers=dao.getAllManufacturer();
        productCodes=dao.getAllProductCode();
        initComponents();
        actions();
    }

    private void fillModelTable() {
        if (products!=null) {
            products.clear();
            products.addAll(dao.getAllProducts());
        }
        else products=ObservableCollections.observableList(dao.getAllProducts());
    }

Antes que nada es necesario modificar el entity Product.java añadiendole lo siguiente:

@Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.removePropertyChangeListener(listener);
    }


Y para cada setter de las propiedades agregar el FirePropertyChange, esto es para efectos de poder utilizar una lista observable para que la tabla siempre pueda saber cuando cambia una propiedad de la lista de productos que utilizamos.

public void setManufacturer(Manufacturer manufacturer) {
        Manufacturer old=this.manufacturer;
        this.manufacturer = manufacturer;
        changeSupport.firePropertyChange("manufacturer", old, manufacturer);
    }


Por ultimo tambien creo una propiedad transient para efectos de utilizarla en un JComboBox como se explicara mas adelante.

public boolean getBooleanAvailable() {
        return available!=null && !available.isEmpty() && available.equals("TRUE");
    }

    
    public void setBooleanAvailable(boolean res) {
        String old=this.available;
        available=res?"TRUE":"FALSE";
        changeSupport.firePropertyChange("booleanAvailable", old, available);
    }


Todo esto es necesario hacerlo ya que en una clase Entity no se puede utilizar la anotación @Bindable antes del nombre de la clase y esta realiza automaticamente lo anterior expuesto y así poder utilizar el pojo en una ObservableList.

El diseño del formulario seria el siguiente:



Luego en vista de diseño del formulario doy clic derecho a la tabla, selecciono propiedades y elijo la sección  "binding" edito la propiedad "elements" y lo lleno con la lista de productos.


Luego realizo de la misma manera el binding de la propiedad "selected" en propiedades>binding de la caja de texto, apunto hacia la propiedad virtual "selected" de la tabla que es de tipo Product y luego selecciono "description"



Luego hago lo mismo con el checkbox solamente que ahora en lugar de apuntar a la propiedad "description" del elemento seleccionado de la tabla lo haré a la propiedad "booleanAvailable".



Luego para los combos se hace similar que una tabla seleccionando la lista que le corresponde a cada jcombobox, por ejemplo para el combo de Manufacturer se selecciona la lista de manufacturers que se encuentra en el formulario para su propiedad elements.



Y para elegir el elemento seleccionado por defecto apuntamos la propiedad virtual "selectedItem" hacia "selected" de la tabla.



Se realiza el mismo procedimiento para el combo de códigos de producto solamente con la variante que se escoge la lista de product_code del formulario.

Se puede jugar con otras propiedades, así como por ejemplo para los botones hice el enlace para la propiedad enable, para que se valide que los botones de Actualizar y borrar solamente esten activos cuando se haya seleccionado un item de la tabla.



Por ultimo agrego el código de CRUD habitual en los demás botones.

private void btnUpdateActionPerformed(java.awt.event.ActionEvent evt) {                                          
        dao.updateProduct(selected);
        fillModelTable();
        javax.swing.JOptionPane.showMessageDialog(this, "Actualizado");
    }                                         

    private void btnNuevoActionPerformed(java.awt.event.ActionEvent evt) {                                         
        Integer id=dao.getNewProductId();
        Product nuevo=new Product();
        nuevo.setProductId(id);
        nuevo.setDescription(txtDescripcion.getText());
        nuevo.setManufacturer((Manufacturer) comboManufacturer.getSelectedItem());
        nuevo.setProductCode((ProductCode) comboProductCode.getSelectedItem());
        nuevo.setBooleanAvailable(checkAvailable.isSelected());
        selected=dao.addProduct(nuevo);
        fillModelTable();
    }                                        

    private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {                                          
        try {
            dao.deleteProduct(selected);
            fillModelTable();
        }
        catch (DataIntegrityViolationException e) {
            javax.swing.JOptionPane.showMessageDialog(this, "El producto tiene orden de compra (tabla PURCHASE_ORDER)");
        }
    }

Aca el ejemplo en tiempo de ejecución.



Adjunto el ejemplo para efectos de estudio.

Comentarios (0)

Spring 3.0 e Hibernate JPA 2.0

Hace unos días me decici a integrar Spring con la implementacion JPA 2.0 de Hibernate. En esta ocasión la versión de spring que usare es la 3.0 de Hibernate 3.6.7 y la base de datos de ejemplo (derby - sample) que se encuentra embebida en Netbeans.

Los jars necesarios para utilizar la implementación JPA de Hibernate, en donde {hibernate-path} es la ruta donde esta descomprimido la distribución final de Hibernate 3.6.7:

{hibernate-path}\lib\jpa\hibernate-jpa-2.0-api-1.0.1.Final.jar
{hibernate-path}\lib\required\antlr-2.7.6.jar
{hibernate-path}\lib\required\commons-collections-3.1.jar
{hibernate-path}\lib\required\dom4j-1.6.1.jar
{hibernate-path}\lib\required\javassist-3.12.0.GA.jar
{hibernate-path}\lib\required\jta-1.1.jar
{hibernate-path}\lib\required\slf4j-api-1.6.1.jar
{hibernate-path}\hibernate3.jar

Como nota aclaratoria es tambien necesario agregar el jar aopalliance.jar para poder utilizar la anotación @Transactional, en este ejemplo no realizaremos un CRUD por esa razón no se incluye.


Y la versión 3.0 de Spring que viene con Netbeans.

Las tablas que utilizare son "Product", "Manufacturer" y "Product_Code", al mapear las tablas con el asistente de Netbeans obtengo sus clases

La unidad de persistencia debera quedar de la siguiente forma:




  
    org.hibernate.ejb.HibernatePersistence
    org.dani.ejemplo.jpa.dao.ProductCode
    org.dani.ejemplo.jpa.dao.Product
    org.dani.ejemplo.jpa.dao.Manufacturer
    
  


Creo el acceso a datos para las tablas.

package org.dani.ejemplo.jpa.dao;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import java.util.*;
/**
 *
 * @author dherrera
 */
public class DerbySampleDAO extends JpaDaoSupport{

    public List getAllProducts() {
        return getJpaTemplate().find("Select p From Product p");
    }
}


Luego procedo a configurar el archivo de configuración de spring



    


    
     
    
        
            
            
        
    
    
        
    


    
    
    
    


    
    

    




Y la forma de uso sera de la siguiente forma:

package org.dani.ejemplo.jpa;

import java.util.List;
import org.dani.ejemplo.jpa.dao.DerbySampleDAO;
import org.dani.ejemplo.jpa.dao.Product;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 * @author dherrera
 */
public class Init {

    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("/org/dani/ejemplo/jpa/applicationContext.xml");
        DerbySampleDAO dao=(DerbySampleDAO) ctx.getBean("dao");
        List list=dao.getAllProducts();
        for(Product product:list)
            System.out.println(product.getDescription());
    }
}

Adjunto el código fuente de ejemplo aca.

Comentarios (0)

Ejecutar un reporte alojado en JasperServer

Tengo ya bastante de no realizar un post en el blog, pero ahora que dispongo de tiempo quiero compartir la forma en como se ejecuta un reporte alojado en Jasper Server, a través de su webservice.


Para efectos de prueba tengo creada una tabla sobre postgresql con la siguiente estructura:
CREATE TABLE contact
(
id serial NOT NULL,
first_name character varying(50),
last_name character varying(50),
CONSTRAINT pk_contact PRIMARY KEY (id)
);

CREATE TABLE address
(
id serial NOT NULL,
street character varying(50),
fk_contact integer NOT NULL,
CONSTRAINT pk_address PRIMARY KEY (id),
CONSTRAINT address_contact FOREIGN KEY (fk_contact)
REFERENCES contact (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE TABLE phone
(
id serial NOT NULL,
"number" character varying(10),
fk_contact integer NOT NULL,
CONSTRAINT pk_phone PRIMARY KEY (id),
CONSTRAINT phone_contact FOREIGN KEY (fk_contact)
REFERENCES contact (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
Y he creado el siguiente reporte a traves de iReport:
















<br> <band height="79" splitType="Stretch"><br> <staticText><br> <reportElement x="181" y="31" width="192" height="20"/><br> <textElement textAlignment="Center"/><br> <text><![CDATA[REPORTE DE PRUEBA]]></text><br> </staticText><br> </band><br>










































Luego de subir y configurar debidamente el reporte en Jasper Server (leer la documentacion de Jasper Server) procedemos a crear el cliente.

Antes que nada debemos de tener claro todas las librerias que se requiren para el cometido, yo las he tomado de mi instalación de iReport 4.1.1, tomaremos como base que es la ruta de instalación de iReport en nuestro equipo que le llamare {ireport-install} , tambien se necesitan dos librerias alojadas de la instalación del Jasper Server en el tomcat o servidor de aplicaciones donde se encuentre a esta ruta le denominare {js-install}


{ireport-install}/ireport/modules/ext/js_activation-1.1.jar
{ireport-install}/ireport/modules/ext/js_axis-1.4patched.jar
{ireport-install}/ireport/modules/ext/js_commons-codec-1.3.jar
{ireport-install}/ireport/modules/ext/js_commons-discovery-0.2.jar
{ireport-install}/ireport/modules/ext/js_commons-httpclient-3.1.jar
{ireport-install}/ireport/modules/ext/js_jasperserver-common-ws-3.5.0.jar
{ireport-install}/ireport/modules/ext/js_jaxrpc.jar
{ireport-install}/ireport/modules/ext/js_mail-1.4.jar
{ireport-install}/ireport/modules/ext/js_saaj-api-1.3.jar
{ireport-install}/ireport/modules/ext/js_wsdl4j-1.5.1.jar
{ireport-install}/ireport/modules/com-jaspersoft-ireport-jasperserver.jar
{ireport-install}/ireport/modules/com-jaspersoft-ireport.jar
{ireport-install}/ireport/modules/ext/jasperreports-4.1.1.jar
{ireport-install}/platform9/lib/org-openide-util.jar
{ireport-install}/ide10/modules/ext/xerces-2.8.0.jar
{js-install}/WEB-INF/lib/jasperserver-api-metadata-4.1.0.jar
{js-install}/WEB-INF/lib/jasperserver-api-metadata-impl-4.1.0.jar


Yo me cree una libreria en netbeans la cual denomine JSClient en el cual inclui todos esos jars. Procedi a crear mi clase JasperServerClient.java:
package org.dani.jasper.server.ws.client;

import com.jaspersoft.ireport.jasperserver.JServer;
import com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.ResourceDescriptor;
import net.sf.jasperreports.engine.JasperPrint;
/**
*
* @author Daniel Alberto
*/
public class JasperServerClient {

private static String WEBSERVICE_URL="http://localhost:8080/jasperserver/services/repository";
private static String USER="jasperadmin";
private static String PASS="jasperadmin";

private JServer server;

public JasperServerClient() {
server=new JServer();
server.setUrl(JasperServerClient.WEBSERVICE_URL);
server.setUsername(JasperServerClient.USER);
server.setPassword(JasperServerClient.PASS);
}

public JasperPrint runReport(String uri,java.util.Map parameters) throws Exception {
ResourceDescriptor rd=new ResourceDescriptor();
rd.setWsType(ResourceDescriptor.TYPE_REPORTUNIT);
rd.setUriString(uri);
return server.getWSClient().runReport(rd, parameters);
}
}


Luego utilizo el cliente:
package org.dani.jasper.server.client;

import org.dani.jasper.server.ws.client.JasperServerClient;
import java.util.*;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;

/**
*
* @author Daniel Alberto
*/
public class Principal {

private JasperServerClient client=new JasperServerClient();

public static void main(String[] args) throws Exception {
Principal p=new Principal();
p.runReportQuery();
}

public void runReportQuery() throws Exception {
String report="/reports/report_query";
Map params=new HashMap();
params.put("id", 1);
JasperPrint print=client.runReport(report, params);
JasperViewer.viewReport(print);
}

}


Si aparece una advertencia en tiempo de ejecucion que dice: ADVERTENCIA: NetBeans implementation of Preferences not found: java.lang.Exception, hacer caso omiso.

Luego se mostrar el reporte de forma satisfactoria. Pueden descargar el ejemplo a traves de este link.

Comentarios (2)