Tuesday, January 27, 2015

FileUpload con Primefaces

FileUpload con Primefaces


goto.png
Si queremos subir imagenes a nuestra aplicación usaremos el componente FileUpload
Debemos realizar los siguientes pasos:

Agregar al archivo web.xml


   <filter>
       <filter-name>PrimeFaces FileUpload Filter</filter-name>
       <filter-class>
           org.primefaces.webapp.filter.FileUploadFilter
       </filter-class>
   </filter>
   <filter-mapping>
       <filter-name>PrimeFaces FileUpload Filter</filter-name>
       <servlet-name>Faces Servlet</servlet-name>
   </filter-mapping>


s.png


Crear dentro de resources el directorio donde deseamos almacenar las imagenes
En este ejemplo: resources/fotos/clinicas y agregue una imagen llamada fotos.png que se usará como imagen inicial.
f.png




En JSFUtil u otro @Named Beans que usemos agregamos tres métodos uno para obtener el path de la aplicación web , otro para obtener el path relativo a /fotos/clinicas y el otro para copiar los archivos.
/*
    devuelve el path de la aplicacion
    */
   public static String getPath() {
       try {
           ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
                   .getExternalContext().getContext();
           return ctx.getRealPath("/");


       } catch (Exception e) {


           addErrorMessage("getPath() " + e.getLocalizedMessage());
       }
       return null;


   }

/*
    devuelve un hashmap con la ruta de fotos clinicas y el url para las imagenes
    */
   public static HashMap<String, String> getMapPathFotosClinica() {
       try {
           HashMap<String, String> map = new HashMap<String, String>();
          
           String path = getPath() + "resources/fotos/clinicas/";
           map.put("path", path);
           map.put("url", "/resources/fotos/clinicas/");
           return map;
       } catch (Exception e) {


           addErrorMessage(" getMapPathFotosClinica() " + e.getLocalizedMessage());
       }
       return null;


   }


    /*
    devuelve un hashmap con la ruta de fotos clinicas y el url para las imagenes
    */
   public static String getPathFotosClinica() {
       try {             
       
           String path = getPath() + "resources/fotos/clinicas/";
return path;
       } catch (Exception e) {


           addErrorMessage("getPathFotosClinica() " + e.getLocalizedMessage());
       }
       return null;


   }



   /*
    copia un archivo generalmente cuando se usa el fileupload
    fileName: nombre del archivo a copiar
    in: Es el InputStream
    destination: ruta donde se guardara el archivo
 
    */
   public static Boolean copyFile(String fileName, InputStream in, String destination) {
       try {


           // write the inputStream to a FileOutputStream
           OutputStream out = new FileOutputStream(new File(destination + fileName));


           int read = 0;
           byte[] bytes = new byte[1024];


           while ((read = in.read(bytes)) != -1) {
               out.write(bytes, 0, read);
           }


           in.close();
           out.flush();
           out.close();


           return true;
       } catch (IOException e) {
           JSFUtil.addErrorMessage("copyFile() " + e.getLocalizedMessage());
       }
       return false;
   }
Mostrare dos formas para manejar la imagen , una atraves del path incluyendo el url
En el Controller agregar dos atributos.


private String imagenURL ="/resources/fotos/clinicas/foto.png";
private String imagen="foto.png";


Nota: Recuerde que en el directorio /resources/fotos/clinicas se agrego una imagen llamada fotos.png.


crear el método  handleFileUpload() que se encarga de guardar el archivo


En este obtenemos la ruta del directorio /fotos/clinicas/
   public void handleFileUpload(FileUploadEvent event) {
       try {


           UploadedFile file = event.getFile();
//application code
           String destination;


           HashMap<String, String> map = JSFUtil.getPathFotosClinica();


           destination = map.get("path");
           if (destination == null) {
               JSFUtil.addErrorMessage(rf.getMensajeArb("warning.noseobtuvopath"));
           } else {
               imagenURL = map.get("url") + file.getFileName();
               imagen = file.getFileName();
               if (JSFUtil.copyFile(file.getFileName(), file.getInputstream(), destination)) {                  
               }
           }


       } catch (Exception e) {
           JSFUtil.addErrorMessage("handleFileUpload()" + e.getLocalizedMessage());
       }


   }




En la pagina xhtml agregamos el componente.
Colocamos dos <h:graphicImage en el primero usamos el url completo y en el segundo solo el nombre de la imagen.
y.png
 <p:panelGrid id="fotos" columns="1">
             <h:graphicImage value="#{clinicasController.imagenURL}" height="100" width="100"/>
           <h:graphicImage value="/resources/fotos/clinicas/#{clinicasController.imagen}" height="100" width="100"/>
         <p:fileUpload auto="true" label="Foto" fileUploadListener="#{clinicasController.handleFileUpload}" update=":form:growl,:form:fotos"/>
                          
                        </p:panelGrid>


al dar clic en el botón FOTO , seleccionamos una imagen y se carga la  imagen en los dos componentes.
d.png
Solo dejamos una de los dos , esta incluido solo a modo de ejemplo. Recomendaria usar     <h:graphicImage value="/resources/fotos/clinicas/#{clinicasController.imagen}" height="100" width="100"/>


Si ejecutamos el proyecto desde NetBeans IDE, con un proyecto web Maven
lo guarda la imagen en el path /target/nombreproyectoversion/resources/fotos/clinicas
a.png

FileUpload y almacenar la imagen en una base de datos
Si tenemos un campo llamado logoClinica de tipo String en la tabla


Ajustamos el Controller
 @PostConstruct
   public void init() {
       nuevoregistro = false;
       desactivar = true;
       clinicas.setLogoClinica("foto.png");


   }
 @Override
   public String prepararNew() {
       try {
           
           clinicas = new Clinicas();
           clinicas.setLogoClinica(imagen);


       } catch (Exception e) {
           JSFUtil.addErrorMessage(e.getLocalizedMessage());
       }
       return null;
   }

@Override
   public String save() {
       try {
               clinicas = new Clinicas();
              clinicas.setLogoClinica(imagen);
       


@Override
   public String delete() {
       try {
                   clinicas.setLogoClinica(imagen);




Editamos el método  handleFileUpload()
public void handleFileUpload(FileUploadEvent event) {
       try {


           UploadedFile file = event.getFile();
//application code
           String destination;


                 destination = JSFUtil.getPathFotosClinica();
           if (destination == null) {


               JSFUtil.addErrorMessage(rf.getMensajeArb("warning.noseobtuvopath"));
           } else {
               
               clinicas.setLogoClinica(file.getFileName());
               if (JSFUtil.copyFile(file.getFileName(), file.getInputstream(), destination)) {
                  
               }
           }


       } catch (Exception e) {
           JSFUtil.addErrorMessage("handleFileUpload()" + e.getLocalizedMessage());
       }


   }

Monday, January 26, 2015

Búsquedas en JPA utilizando concat y like

Búsquedas en JPA utilizando concat y like

Deseamos tener una página xhtml donde realizamos búsquedas de registros, una tabla tiene los campos (primernombre, segundonombre,apellidopaterno,apellidomaterno).
Queremos buscar por primer nombre, apellido paterno o permitirle al usuario que escriba en una caja el nombre completo, es decir una combinacion de dos campos primernombre y apellidopaterno. Nuestro dialogo de busqueda (basado en Java Server Faces->Primefaces), tendrá una vista similar a esta.
busqueda.png

El código xhtml del diálogo donde se generan los componentes para el <p:outputLabel y el <p:inputText> correspondientes al atributo nombreCompleto que debe ser declarado en el @Named y el metodo buscarNombreCompleto()
s.png


Definiciones en el @Named
@Named
@ViewScoped
public class AdministradoresSistemaSearchController implements Serializable{
 private String nombreCompleto;

public String getNombreCompleto() {
       return nombreCompleto;
   }

   public void setNombreCompleto(String nombreCompleto) {
       this.nombreCompleto = nombreCompleto;
   }
public String buscarNombreCompleto() {
       try {
           administradoresSistema.setPrimerNombre("");
           administradoresSistema.setPrimerNombre("");
           administradoresSistemaList = administradoresSistemaFacade.findByNombreCompletoLike(nombreCompleto);
       } catch (Exception e) {
           JSFUtil.addErrorMessage(e.getLocalizedMessage());
       }
       return "";
   }

En el Facade
Descomponer el texto para separar el nombre y el apellido y colocarle % entre ambos para hacer más genérica la búsqueda.
Esto permitirá buscar por ejemplo
a vill → buscara todos los nombres que inicien con a y el apellido que inicie con vill
aristides v → buscara todos los nombre que inicien con aristides y el apellido inicie con v

   public List<AdministradoresSistema> findByNombreCompletoLike(String nombreCompleto) {
      nombreCompleto = nombreCompleto.trim();
      StringTokenizer st = new StringTokenizer(nombreCompleto);
      String texto="";
      while (st.hasMoreTokens()) {
          if(!texto.equals("")){
              texto+="%";
          }
          texto += " "+st.nextToken();

    }
      nombreCompleto = "%" +texto.trim() + "%";
       Query query = em.createQuery("SELECT a FROM AdministradoresSistema a WHERE CONCAT (lower(a.primerNombre),' ',lower(a.apellidoPaterno)) like ?1");
       query.setParameter(1, nombreCompleto);
      return query.getResultList();

  }