martedì 24 settembre 2013

Java esempio completo creazione xml con JAX-B

In questa classe vediamo un esempio completo di generazione completa dell'xml.
In particolare abbiamo:
  • generazione di attributi a livello di nodo padre e di nodi figli;
  • liste WRAPPED oppure no sia di semplici valori che di oggetti (se si aggiunge l'annotation @XmlElementWrapper si racchiude una collection di valori dentro un nodo "padre")
L'unico punto che mi rimane da capire meglio riguarda proprio la generazione degli attributi su un singolo nodo di un xml.
Bisogna per fare ciò creare una classe che rappresenta il nostro nodo con attributi, e gli attributi saranno proprietà di questa classe, solo che verranno annotati con @XMLAttribute.
Il problema è che se definisco questi attributi come campi pubblici nessun problema, se invece decido di esporli come proprietà con getter e setter ho il seguente errore nella creazione dell'xml :

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions

dove le 2 illegal annotation sono proprio quelle messe nei set delle property del bean usato per mappare l'attributo.

Di seguito riporto l'xml che si vuole ottenere:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persona nota="test">
    <nome>carlo</nome>
    <cogn>resi</cogn>
    <info cf="dsdfsdfsd" age="35"/>
    <lista>abc</lista>
    <lista>def</lista>
    <lista>ghi</lista>
    <contenitore>
        <elemento>abc</elemento>
        <elemento>def</elemento>
        <elemento>ghi</elemento>
    </contenitore>
    <elemento>
        <codice>001</codice>
        <descrizione>A01</descrizione>
    </elemento>
    <elemento>
        <codice>002</codice>
        <descrizione>A02</descrizione>
    </elemento>
    <elemento>
        <codice>003</codice>
        <descrizione>A03</descrizione>
    </elemento>
    <contenitoreCodici>
        <elemento>
            <codice>001</codice>
            <descrizione>A01</descrizione>
        </elemento>
        <elemento>
            <codice>002</codice>
            <descrizione>A02</descrizione>
        </elemento>
        <elemento>
            <codice>003</codice>
            <descrizione>A03</descrizione>
        </elemento>
    </contenitoreCodici>
</persona>


Classe Persona.java


package it.prova;
import java.util.Collection;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name="persona")
@XmlType(name="persona",propOrder={"nome","cognome","info","campiVari","campiVari2","listaNotWrapped","listaWrapped"})
public class Persona {
 private String nome;
 private String cognome;
 private String nota;
 private Info info;
 private Collection campiVari;
 private Collection campiVari2;
 private Collection listaNotWrapped;
 private Collection listaWrapped;
 @XmlElement(name="elemento")
 public Collection getListaNotWrapped() {
  return listaNotWrapped;
 }
 public void setListaNotWrapped(Collection listaNotWrapped) {
  this.listaNotWrapped = listaNotWrapped;
 }
 
 @XmlElementWrapper(name="contenitoreCodici")
 @XmlElement(name="elemento")
 public Collection getListaWrapped() {
  return listaWrapped;
 }
 public void setListaWrapped(Collection listaWrapped) {
  this.listaWrapped = listaWrapped;
 }
 @XmlElementWrapper(name="contenitore")
 @XmlElement(name="elemento")
 public Collection getCampiVari2() {
  return campiVari2;
 }
 public void setCampiVari2(Collection campiVari2) {
  this.campiVari2 = campiVari2;
 }
 @XmlElement(name="lista")
 public Collection getCampiVari() {
  return campiVari;
 }
 public void setCampiVari(Collection campiVari) {
  this.campiVari = campiVari;
 }
 @XmlElement(name="info")
 public Info getInfo() {
  return info;
 }
 public void setInfo(Info info) {
  this.info = info;
 }
 @XmlAttribute(name="nota")
 public String getNota() {
  return nota;
 }
 public void setNota(String nota) {
  this.nota = nota;
 }
 @XmlElement(name="nome")
 public String getNome() {
  return nome;
 }
 public void setNome(String nome) {
  this.nome = nome;
 }
 @XmlElement(name="cogn")
 public String getCognome() {
  return cognome;
 }
 public void setCognome(String cognome) {
  this.cognome = cognome;
 }
}


Classe Info.java (per gli attributi)

package it.prova;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Info {
 @XmlAttribute(name="age")
 public String eta;
 @XmlAttribute(name="cf")
 public String cf;
// cosi' non funziona!! 
// private String eta;
// private String cf;
// @XmlAttribute(name="age")
// public String getEta() {
//  return eta;
// }
// public void setEta(String eta) {
//  this.eta = eta;
// }
// @XmlAttribute(name="cf")
// public String getCf() {
//  return cf;
// }
// public void setCf(String cf) {
//  this.cf = cf;
// }
// 
}


Classe Campi.java ( qui abbiamo i campi della lista composta da oggetti )


package it.prova;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Campi {
 private String codice;
 private String descrizione;
 public Campi(){
  
 }
 public Campi(String codice,String descrizione){
  this.codice=codice;
  this.descrizione=descrizione;
 }
 public String getCodice() {
  return codice;
 }
 public void setCodice(String codice) {
  this.codice = codice;
 }
 public String getDescrizione() {
  return descrizione;
 }
 public void setDescrizione(String descrizione) {
  this.descrizione = descrizione;
 }
}



Classe GenerateXml.java per la generazione dell'xml


package it.prova;
import java.io.File;
import java.io.FileWriter;
import java.util.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class GenerateXml {
 public static void main(String[] args) throws Exception{
  File f=new File("out/test.xml");
  Persona p=new Persona();
  p.setCognome("resi");
  p.setNome("carlo");
  p.setNota("test");
  Info i=new Info();
  i.cf="dsdfsdfsd";
  i.eta="35";
//  i.setCf("sdfsdsdf");
//  i.setEta("33");
  p.setInfo(i);
  List l=new ArrayList();
  l.add("abc");
  l.add("def");
  l.add("ghi");
  p.setCampiVari(l);
  p.setCampiVari2(l);
  List listaCampi=new ArrayList();
  listaCampi.add(new Campi("001", "A01"));
  listaCampi.add(new Campi("002", "A02"));
  listaCampi.add(new Campi("003", "A03"));
  p.setListaWrapped(listaCampi);
  p.setListaNotWrapped(listaCampi);
  JAXBContext jc=JAXBContext.newInstance(Persona.class);
  Marshaller m=jc.createMarshaller();
   m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
         FileWriter fw=new FileWriter(f);
         m.marshal(p, fw);
         fw.flush();
 }
}

Java validare xml con xsd usando JAX-B

Per validare un file xml con un xsd occorre procedere in questo modo.
  1. Per prima cosa dall'xsd si genera la classe java corrisponente (tramite il comando xjc.exe );
  2. Quindi i file di input xml in ingresso vengono validati rispetto all'xsd fornito tentando di parsare il file nell'oggetto ottenuto al punto 1
Questo è il codice usato in un esempio (INPUT è un oggetto Java complesso annotato via jax-b ed ottenuto dall'operazione compiuta al punto 1).
Il metodo prende in input il file con l'xsd e l'xml con i dati.

import java.io.*;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
public static boolean valida(File xsd,File fileOrigine) {
try
    {
 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
 Schema schema = schemaFactory.newSchema(dtd); 
 JAXBContext jc=JAXBContext.newInstance(INPUT.class);
 Unmarshaller um = jc.createUnmarshaller();
 um.setSchema(schema);
 INPUT i=(INPUT) um.unmarshal(fileOrigine);
        return true;
    }
catch(Exception ex){
          ex.printStackTrace();
   return false;
  }
 }


venerdì 20 settembre 2013

Export runnable jar in modalità package oppure extract

Nel caso in cui da Eclipse si voglia esportare in un unico jar sia il codice della nostra applicazione sia quello delle librerie utilizzate da essa, si può procedere in 3 modi:
  • Extract required libraries into generated jar;
  • Package required libraries into generated jar;
  • Copy required libraries into a sub-folder next to the generated JAR.
Il terzo modo è intuitivo, tutti i jar sono inseriti in una cartella a fianco del jar principale.

Nel primo caso (EXTRACT) il contenuto dei jar viene esploso dentro il jar (Eclipse correttamente avvisa che trattandosi di un repackaging di jar esterni potrebbero esserci problemi di licenza).
In questo caso nel manifest del jar abbiamo la seguente situazione:

Main-Class: classe con il nostro main

Nel secondo caso (package) i jar sono inseriti all'interno del jar esportato, e il manifest risulta modificato in questo modo:

Manifest-Version: 1.0
Rsrc-Class-Path: ./ logback-core-1.0.9.jar commons-lang-2.6.jar logbac
 k-classic-1.0.9.jar slf4j-api-1.7.2.jar log4j-1.2.17.jar commons-code
 c-1.6.jar....[lista di tutti i jar utilizzati]
Class-Path: .
Rsrc-Main-Class:classe con il nostro main
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader


Le differenze principali tra i 2 approcci sono:
  1. Usando la modalità package crescono le dimensioni del jar ;
  2. Usando la modalità extract si potrebbe incappare in problemi di licenza sw;
  3. Usando la modalità extract se si aggiorna un jar esterno bisogna rieffettuare il pacchetto, nel caso invece della modalità package basta sostituire il jar interno. 






mercoledì 28 agosto 2013

Java 7 try with resources

Con Java 7 è stato introdotto il concetto di try with resources.
Essendo comune il problema di chiudere le risorse utilizzate , siano esse connessioni al db piuttosto che BufferedReader etc. etc., Java 7 introduce questa feature proprio per risolvere  queste mancanze.
Vediamo un esempio:

public static void main(String[] args) {
 String url="jdbc:mysql://localhost:3306/";
 String db="addressBook";
 String username="root";
 String password="admin";
 try(Connection connection=DriverManager.getConnection(url+db,username,password)){
     System.out.println("Connessione ok!!!");
 }
 catch(Exception ex){
     ex.printStackTrace();
 }
}

Come possiamo vedere dopo il try, ma prima dell'inizio del blocco try con le parentesi graffe, è creata la connessione.
Automaticamente sarà chiusa alla fine del programma da Java, senza necessità di farlo esplicitamente.
Si possono usare anche con più risorse, scrivendole di seguito alla prima. L'unica regola è che le varie risorse devono essere separate da ; tranne l'ultima.

Esempio:

try (FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw)) {
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }


Notiamo nell'esempio di recupero connessione che abbiamo utilizzato JDBC 4.0 ; con questa libreria non è più necessario  cercare il driver per la connessione al db tramite l'istruzione Class.forName utilizzata nelle precedenti versioni.
L'importante è che il driver sia nel classpath, se c'è la JVM lo trova da solo e ci risparmia un ulteriore passaggio nel codice , dove bisognava per altro indicare il nome esatto del driver utilizzato (nel caso di Mysql  com.mysql.jdbc.Driver).

martedì 27 agosto 2013

h:panelGrid dare uno stile alle colonne

L' h:panelGrid di JSF si renderizza come una tabella HTML.
Non è possibile utilizzare tuttavia attributi come il colspan, se vogliamo farlo dobbiamo comunque utilizzare una table html.
Ci viene però incontro l'attributo columnClasses che consente di associare ad ogni colonna uno stile css diverso.
All'interno del columnClasses definiamo, separati dal carattere ',' , tanti stili quante sono le colonne del panelgrid.
Esempio:



<h:panelGrid columns="4"  columnClasses="cella1,cella2,cella3,cella4">
<h:outputLabel value="Tipo Persona" style="font-weight:bold" />
.....altre colonnne 
</h:panelGrid>
<style type="text/css">
 .cella1{
 width:15%;
 white-space: nowrap;
   
 }
 .cella2{
 width:35%;
   
 }
.cella3{
 width:15%;
 }
.cella4{
 width:35%;
}
</style> 

giovedì 22 agosto 2013

JSF 2.0 debug online component tree e scoped library

 E' possibile in maniera molto semplice effettuare un debug della struttura della pagina jsf renderizzata e dei componenti presenti nei vari scope (view,request,session).
Per effettuare tale operazione per prima cosa dobbiamo aggiungere nel web.xml il seguente parametro di contesto:


<context-param>
    <param-name>javax.faces.FACELETS_DEVELOPMENT</param-name>
    <param-value>true</param-value>
</context-param>


Quindi nelle pagine di nostro interesse dobbiamo importare la libreria delle facelets (il namespace è xmlns:ui="http://java.sun.com/jsf/facelets" da aggiungere all'interno del nodo html).

E definire il seguente tag:


 <ui:debug hotkey="x" />

Il valore da assegnare all'hotkey è a nostra scelta. Quindi premendo la combinazione di tasti CTRL+SHIFT+X vedremo apparire una finestra di debug con le informazioni ricercate, molto utile per avere a runtime un'evidenza dei dati presenti sulla pagina e negli scope.
Se non si specifica nessun valore per l'hotkey la finestra di debug apparirà una volta premuta la combinazione di tasti CTRL+SHIFT+D.

mercoledì 21 agosto 2013

Jquery accedere ad una cella di una tabella

Per accedere al contenuto di una cella di una tabella html e ad esempio effettuare un test sul valore presente in una certa posizione si può fare così:


var a=$("#datiB").find("tr:eq(1)").find("td:eq(2)").html().substring(2,3);



In questo caso stiamo assegnando alla variabile a la stringa di testo presa dalla tabella con id datiB, nella seconda riga e nella terza colonna. Del valore presente nella stringa interna prendiamo il 3 carattere.