Qui è presente la secondo parte dell’introduzione a Spring OXM

Come spiegato prima Spring OXM grazie alle sue interfacce, offre una facilità di utilizzo che per esempio si trasforma nella possibilità di utilizzare più tecnologie per gestire i file xml. Tra le quali:

  • jaxb2
  • xmlbeans
  • jibx
  • castor

Offrendo perciò ampia libertà allo sviluppatore di scegliere la tecnologia che ritiene più adatta, oppure di cambiare in corso d’opera tecnologia, con un semplicissimo cambiamento nei file di configurazione.

La scelta all’interno del mio progetto è caduta su jaxb2, sia perchè meglio documentato per la fase di start-up sia perchè è abbastanza affidabile.

1 – Per cominciare è necessario configurare il pom.xml aggiungendo le seguenti dipendenze

<!– Parte Dedicata alle dipendenze per la parte di OXM–>
<!– Con spring version pari a 3.0.0 –>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>

2 – Configurare l’applicationContext.xml (nel mio progetto è presente all’interno di classpath:META-INF/spring/)

In grassetto appaiono le parti aggiunte alla definizione del tag BEANS

<beans xmlns=”http://www.springframework.org/schema/beans&#8221;

…….

xmlns:oxm=”http://www.springframework.org/schema/oxm&#8221;

xsi:schemaLocation=”http://www.springframework.org/schema/oxm

http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd“>

3 – Dichiarare sempre nell’applicationContext nuovi bean che ci permetteranno di utilizzare Spring OXM

<!– Parte Legata all’OXM –>

<bean id=”oxMapper” class=”it.mcr.gestionefir.util.oxm.service.OxMapperImpl”>

<property name=”marshaller” ref=”jaxbMarshaller” />

<property name=”unmarshaller” ref=”jaxbMarshaller” />

</bean>

<oxm:jaxb2-marshaller id=”jaxbMarshaller”>

<oxm:class-to-be-bound name=”it.mcr.gestionefir.util.oxm.beans.DipendenzaQualificaOxm” />

<oxm:class-to-be-bound name=”it.mcr.gestionefir.util.oxm.beans.QualificaOxm” />

</oxm:jaxb2-marshaller>

<bean id=”gestoreDipendenzaQualificaOxm” class=”it.mcr.gestionefir.util.oxm.service.GestoreDipendenzaQualifica” />

  • Il bean “oxMapper” mi permette di definire una classe che implementa l’interfaccia “OxMapper” contenente i due metodi per eseguire il marshaller e unmarshaller di spring oxm, queste due proprietà sono state innestate da un secondo bean “jaxbMarshaller”;
  • jaxbMarshaller” implementa la chiamata alla libreria jaxb ed inoltre permette di definire i bean (POJO) che devono essere utilizzati per effettuare la trasformazione/lettura in xml;
  • Il terzo bean “gestoreDipendenzaQualificaOxm” definize una classe di servizio che mi permette di definire un gestore per gli oggetti OXM creati in modo che siano creati e gestiti come singleton, per evitare di rubare troppe risorse nel caso di più chiamate all’oggetto.

4 – La classe OxMapperImpl, presente qui sotto presenta le parti fondamentali della classe, in grassetto sono presenti le parti più interessanti che permettono di scrivere e leggere un xml.

@Service(“oxMapper”)

public class OxMapperImpl implements OxMapper {

private static final Log LOG = LogFactory.getLog(OxMapperImpl.class);

private static final String urlApplicationContext = “META-INF//spring//applicationContext.xml”;

private static final String urlFolderSpring = “src//main//resources//META-INF//spring//”;

private static final String urlClasspathSpringOXM = “classpath:META-INF//spring//”;

private Marshaller marshaller;

private Unmarshaller unmarshaller;

protected ClassPathXmlApplicationContext getClassPathXmlApplicationContext() {

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(urlApplicationContext);

System.out.println(context.CLASSPATH_URL_PREFIX);

return context;

}

public void writeObjectToXml(Object object, String filename) throws IOException {

FileOutputStream fos = null;

File file =  new File(urlFolderSpring+filename);

try {

fos = new FileOutputStream(file);

marshaller.marshal(object, new StreamResult(fos));

} catch (XmlMappingException e) {

System.err.println(“Xml-Serialization failed due to an XmlMappingException.”+ e);

} catch (IOException e) {

System.err.println(“Xml-Serialization failed due to an IOException.”+ e);

} finally {

if (fos != null) { fos.close(); }

}

}

public Object readObjectFromXml(String filename) throws IOException {

System.out.println(“sono dentro readObjectFromXml: “+filename);

FileInputStream fis = null;

ClassPathXmlApplicationContext context = getClassPathXmlApplicationContext();

Resource resource = context.getResource(urlClasspathSpringOXM+filename);

try {

fis = new FileInputStream(resource.getFile());

return unmarshaller.unmarshal(new StreamSource(fis));

} catch (IOException e) {

System.err.println(“Xml-Deserialization failed due to an IOException.”+e);

} finally {

if (fis != null) { fis.close();  }

}

return null;

}

}

5 – I bean pojo utilizzati sono “DipendenzaQualifica” che a sua volta contiene una lista di pojo “Qualifica”

NOTA: nei vari esempi che trovate in giro le annotation vengono messe direttamente sulla dichiarazione dei campi, purtroppo per vari motivi che non sono riuscito a risolvere, questo non mi è stato permesso ed ho dovuto ripiegare inserendoli direttamente nei getters del pojo. Comunque il loro funzionamento è lo stesso

// l’annotation @XmlRootElement permette di definire il nome del tag root, all’interno dell’xml in questo caso sarò lo stesso della classe

@XmlRootElement

public class DipendenzaQualificaOxm {

public DipendenzaQualificaOxm() {}

private String descrizione;

private List<QualificaOxm> listQualificaOxm;

public String toString(){

return “Descrizione file XML: “+descrizione+”Listato degli oggetti: “+listQualificaOxm;

}

// l’annotation @XmlElement(name=”qualifica”) permette di personalizzare il nome del tag corrispondente all’interno dell’xml, infatti senza questo annotation in automatico il tag prende la label del relativo campo pojo.

@XmlElement(name=”qualifica”)

public List<QualificaOxm> getListQualificaOxm() {

return listQualificaOxm;

}

// Getter and Setters

}

6 – Il bean Pojo qualifica

//

//l’annotation @XmlType(propOrder = {“appartenenza”,”formazioneGiocatore”}) permette di organizzare i campi, seguendo un’ordine prestabilito da noi.
@XmlType(propOrder = {“appartenenza”,”formazioneGiocatore”})
@XmlRootElement

public class QualificaOxm {

private int id;

private String name, table, appartenenza;

private Boolean formazioneGiocatore = false;

// l’annotation @XmlAttribute permette di definire una proprieta del pojo come attributo del tag root element,
// senza quest’ultimo la proprietà sarebbe stata trasformata in un elemento dell’xml

@XmlAttribute

public int getId() { return id; }

@XmlAttribute

public String getName() { return name; }

@XmlAttribute public String getTable() { return table; }

@XmlElement(name=”formazioneGiocatorePresente”)
public Boolean getFormazioneGiocatore() {return formazioneGiocatore; }

}

7 – La classe “GestoreDipendenzaQualifica” permette di gestire l’inizializzazione e il caricamento del bean DipendenzaQualifica, in modo che diventi un bean singleton.

@Service(“gestoreDipendenzaQualifica”)

public class GestoreDipendenzaQualifica {

private static String filename = “dipendenzaQualifica-oxm.xml”;

private DipendenzaQualificaOxm dipendenzaQualificaOxmRead;

public void initIstance() throws IOException {

dipendenzaQualificaOxmRead = (DipendenzaQualificaOxm) oxMapper.readObjectFromXml(filename);

}

public DipendenzaQualificaOxm getInstance() throws IOException{

if(dipendenzaQualificaOxmRead == null){

this.initIstance();

}

return dipendenzaQualificaOxmRead;

}

private OxMapper oxMapper;

@Autowired

private void setOxMapper(OxMapper oxMapper){

this.oxMapper = oxMapper;

}

}

8 – Simulazione di una chiamata

Per effettuare una chiamata dovremmo semplicemente effettuare un injection della classe “GestoreDipendenzaQualifica

all’interno della nostra classe obiettivo. Richiamandola nel seguente modo:

DipendenzaQualificaOxm dipendenzaQualificaOxm = null;

try {

dipendenzaQualificaOxm = (DipendenzaQualificaOxm) gestoreDipendenzaQualificaOxm.getInstance();

} catch (Exception e) {

e.printStackTrace();

}

Annunci