Blog4J

Articles et tutoriels sur la plateforme Java EE


Java et le XML

Rédigé le 16 novembre 2007 — Ajouter un commentaire »

Le langage de description de données XML peut s’avérer très utile pour le développeur (sauvegarde de données, compatibilité entre les applications…).

Pour faciliter son utilisation, il existe dans le langage Java de nombreuses API permettant de lire, créer ou modifier des documents XML dans différents formats.

Pour chaque utilisation, le développeur dispose même de plusieurs solutions.

Cet article détaille les différentes API et spécifications proposées par Sun pour le traitement des documents XML (JAXP, JAXB), mais aussi d’autres API plus simples d’utilisation dans certains cas précis (JDOM, ROME…).

 

1. JAXP

1.1. Présentation

JAXP est une spécification de Sun regroupant toutes les API permettant de faciliter le traitement de documents XML. Avec JAXP, il est possible de créer, manipuler et valider des fichiers XML.

L’ensemble de l’API JAXP est composé de 6 fichiers .jar :

jaxp-api.jar

- javax.xml.transform

- javax.xml.parsers
- javax.xml.xpath

- javax.xml.validation

- javax.xml.datatypes

- javax.xml.namespace

sax.jar

- org.xml.sax
- org.xml.sax.helpers

- org.xml.sax.ext

dom.jar

- org.w3c.dom

xercesImpl.jar

 

xalan.jar

A noter que JAXP est inclu dans le JDK depuis la version 1.4. Il est également possible de télécharger l’API séparément (https://jaxp.dev.java.net).

La version actuelle de JAXP est la version 1.3. Elle est composé de l’implémentation plusieurs API (DOM, SAX, XSLT…) :

1.2. DOM (Document Object Model)

1.2.1. Présentation de l’API

DOM est une API permettant de lire mais aussi de créer et modifier un fichier XML.

DOM est une recommandation du W3C (http://www.w3.org).

DOM construit et stocke en mémoire un arbre représentant le document XML dont les nœuds sont les éléments, les attributs et le contenu.

Il sera ensuite possible de parcourir cet arbre en lecture, de créer de nouveaux éléments et attributs et de modifier les éléments existants.

L’inconvénient de DOM est qu’il consomme de la mémoire pour créer et stocker l’arbre.


<livre>

<ISBN></ISBN>

<titre></titre>

<auteur>

<nom></nom>

<prenom></prenom>

</auteur>

<dateParution></ dateParution>

<editeur></editeur>

</livre>

1.2.2. Exemple

Voici le code Java permettant de créer cet arbre DOM :

package exemplejavaxml;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

public class XmlDom

{

public static void createXmlDom() throws ParserConfigurationException

{

// Création d’un nouveau DOM

DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();

DocumentBuilder constructeur = fabrique.newDocumentBuilder();

Document document = constructeur.newDocument();

// Propriétés du DOM

document.setXmlVersion( »1.0″);

document.setXmlStandalone(true);

// Création de l’arborescence du DOM

Element livre = document.createElement( »livre »);

Element isbn = document.createElement( »ISBN »);

livre.appendChild(isbn);

Element titre = document.createElement( »titre »);

livre.appendChild(titre);

Element auteur = document.createElement( »auteur »);

livre.appendChild(auteur);

Element nom = document.createElement( »nom »);

auteur.appendChild(nom);

Element prenom = document.createElement( »prenom »);

auteur.appendChild(prenom);

Element dateParution = document.createElement( »dateParution »);

livre.appendChild(dateParution);

Element editeur = document.createElement( »editeur »);

livre.appendChild(editeur);

document.appendChild(racine);

}

}

Il suffit de créer une fabrique et un constructeur à l’aide des classes DocumentBuilderFactory et DocumentBuilder. A l’aide de ce constructeur, on créé un document auquel on ajoute des éléments.

Modification d’un arbre DOM

Nous allons maintenant modifier cet arbre DOM pour insérer des données à l’intérieur des balises.

Pour cela, il faut ajouter les imports de packages suivants en haut de notre classe :

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;


Dans notre méthode createXmlDom, on récupère la liste des livres et on se place sur le premier livre :

NodeList livreList = document.getElementsByTagName( »livre »);

Node unLivre = livreList.item(0);

On récupère ensuite la liste des nœuds pour ce livre :

NodeList unLivreList = unLivre.getChildNodes();

Pour chaque noeud, on sélectionne l’élément (item) et on définit sa valeur avec la méthode setTextContent.

Node insertIsbn = unLivreList.item(0);

insertIsbn.setTextContent( »2070516173″);

Node insertTitre = unLivreList.item(1);

insertTitre.setTextContent( »Titre du livre »);

NodeList auteurList = unLivreList.item(2).getChildNodes();

Node auteurNom = auteurList.item(0);

auteurNom.setTextContent( »Nom de l’auteur »);

Node auteurPrenom = auteurList.item(1);

auteurPrenom.setTextContent( »Prenom de l’auteur »);

Node insertDateParution = unLivreList.item(3);

insertDateParution.setTextContent( »31/12/2006″);

Node insertEditeur = unLivreList.item(4);

insertEditeur.setTextContent( »Nom de l’éditeur »);

On a vu comment créer un arbre DOM et comment modifier les valeurs de ses éléments, voici maintenant une méthode permettant de sauvegarder cet arbre DOM dans un fichier XML :

public static void saveXml(Document document, String fichier)

{

try

{

Source source = new DOMSource(document);

File file = new File(fichier);

Result resultat = new StreamResult(fichier);

TransformerFactory fabrique = TransformerFactory.newInstance();

Transformer transformer = fabrique.newTransformer();

transformer.setOutputProperty(OutputKeys.INDENT, « yes »);

transformer.setOutputProperty(OutputKeys.ENCODING, « ISO-8859-1″);

transformer.transform(source, resultat);

}catch(Exception e){

e.printStackTrace();

}

}

Il suffit ensuite d’appeler saveXml à la fin de l méthode createXmlDom comme ceci :

saveXml(document, « livres.xml » ) ;

1.3. SAX (Simple Api for Xml)

1.3.1. Présentation

SAX est une API proposée par l’organisme xml.org (http://www.xml.org) permettant la lecture d’un fichier XML.

Il existe une implémentation de cette API dans de nombreux langages (PHP, C++, Perl…).

Le langage Java dispose bien sûr de sa propre implémentation de cette API incluse dans JAXP.

SAX est basé sur un système évènementiel : il est possible d’appeler des méthodes prédéfinies lorsqu’un évènement est détecté lors du parcours du fichier XML (détection du début d’une balise, détection de la fin du document XML…).

Ces méthodes sont celles de l’interface org.xml.sax.ContentHandler, les plus utiles sont les suivantes :

- startDocument : cette méthode est appelée au tout début de l’analyse du document XML.

- startElement : avec cette méthode on peut exécuter des actions pour chaque élément du document XML.

- endElement : à l’inverse, avec cette méthode, il est possible d’exécuter un traitement lorsque la balise de fermeture d’un élément est détecté.

- characters : permet de récupérer le contenu d’une balise.

- endDocument : méthode appellée à la fin de l’analyse du document XML.

1.3.2. Exemple

Voici un exemple d’implémentation de cette interface, elle utilise la classe DefaultHandler qui est une implémentation par défaut de l’interface ContentHandler.

package exemplejavaxml;

import org.xml.sax.Attributes;

import org.xml.sax.Locator;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class MyContentHandler extends DefaultHandler

{

public void setDocumentLocator(Locator locator) {

}

public void startDocument() throws SAXException

{

System.out.println( »\tJe commence à parcourir le document… »);

}

public void endDocument() throws SAXException

{

System.out.println( »\tJ’ai fini de parcourir le document… »);

}

public void startPrefixMapping(String prefix, String uri) throws SAXException {

}

public void endPrefixMapping(String prefix) throws SAXException {

}

public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException

{

System.out.println( »\tL’élément » + localName +  » a été trouvé. »);

System.out.println( »\tIl a  » + new Integer(atts.getLength()).toString() +  » attributs. »);

for( int i=0;i<atts.getLength();i++ )

{

System.out.println( »\t\tL’attribut  » + atts.getLocalName(i) +  » a la valeur  » + atts.getValue(i));

}

}

public void endElement(String uri, String localName, String qName) throws SAXException

{

System.out.println( »\tFin de la balise de l’élément » + localName);

}

public void characters(char[] ch, int start, int length) throws SAXException

{

String contenu = new String(ch,start,length);

System.out.println( »\t\tContenu de cet élément :  » + contenu);

}

public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {

}

public void processingInstruction(String target, String data) throws SAXException {

}

public void skippedEntity(String name) throws SAXException {

}

}

Il faut ensuite créer un parser qui va parcourir le document XML et appeler les méthodes définies dans la classe MyContentHandler.

Un parser est un outil d’analyse syntaxique. Les parsers XML permettent de parcourir, d’analyser et d’obtenir les informations contenues dans les balises XML.

package exemplejavaxml;

import java.io.File;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.ContentHandler;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.helpers.XMLReaderFactory;

public class Main {

public static void main(String[] args) throws ParserConfigurationException

{

String file = new String( »livres.xml »);

XMLReader saxReader = null;

DefaultHandler handler = new MyContentHandler();

SAXParserFactory factory = SAXParserFactory.newInstance();

try

{

SAXParser saxParser = factory.newSAXParser();

saxParser.parse( new File(file), handler);

}

catch (Throwable t)

{

t.printStackTrace();

System.exit (1);

}

System.exit (0);

}

}

Il est possible de tester l’exemple précédent avec le document XML livres.xml :

<livre>

<ISBN>2203340273</ISBN>

<titre>Titre du livre</titre>

<auteur>

<nom>Nom auteur</nom>

<prenom>Prénom auteur</prenom>

</auteur>

<dateParution>31/12/2006</dateParution>

<editeur>Nom éditeur</editeur>

</livre>

Le parser utilisé par défaut par JAXP est Xerces. Il est tout à fait possible d’utiliser un autre parser XML. Pour cela, il faut spécifier une variable d’environnement précisant le parseur à utiliser.

Par exemple, pour utiliser le parser Crimson :

System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.crimson.jaxp.SAXParserFactoryImpl");

Pour conclure, on peut dire que SAX permet de parcourir un document XML de façon très rapide.

L’inconvénient majeur est qu’il ne lit un fichier XML que de façon séquentielle c’est-à-dire au fur et à mesure que les données arrivent.

Par contre, le système évènementiel de SAX permet une lecture rapide et performante (car contrairement à DOM, SAX ne construit pas « l’arbre » du document XML en mémoire).

DOM est donc utile pour créer ou modifier un document XML ou bien pour parcourir des documents de petite taille. SAX, quand à lui, est utile essentiellement pour lire d’importants fichiers XML.

1.4. Validation Xsd

1.4.1. Rappel : qu’est ce que les schemas XSD ?

XSD (Xml Schema Description) permet de définir une structure et un contenu à respecter pour un document Xml. Un fichier xsd est composé d’un ensemble de balises décrivant les balises obligatoires pour un document xml et le type de données que la balise doit contenir.

Voici un exemple d’un schéma XSD simple (validationLivres.xsd) :

<?xml version= »1.0″ encoding= »UTF-8″?>

1) <xs:schema xmlns:xs= »http://www.w3.org/2001/XMLSchema« >

2) <xs:element name= »livre »>

3) <xs:complexType>

4) <xs:sequence>

5) <xs:element name= »isbn » type= »xs:string »/>

<xs:element name= »titre » type= »xs:string »/>

<xs:element name= »auteur » />

<xs:complexType>

<xs:sequence>

<xs:element name= »nom » type= »xs:string »/>

<xs:element name= »prenom » type= »xs:string »/>

</xs:sequence>

</xs:complexType>

<xs:element name= »dateParution » type= »xs:date »/>

<xs:element name= »editeur » type= »xs:string »/>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

1) L’élément schéma définit l’élément racine

2) On définit un élément « livre »

3) On précise que l’élément « livre » est de type complexe, c’est-à-dire qu’il ne s’agit pas d’un type simple tel que string, double…

4) On démarre une séquence : notre élément livre est composé d’une séquence d’autres éléments.

5) On définit les éléments qui composent l’élément « livre ». Ces éléments sont soit de type simple, soit de type complexe. Dans ce cas, il faut décrire une séquence d’éléments composant ce type (comme ici pour l’auteur).

Les différents types de données utilisables avec XSD sont :

  • string
  • boolean
  • float
  • double
  • decimal
  • timeDuration
  • recurringDuration
  • binary
  • uriReference
  • ID
  • IDREF
  • ENTITY
  • NOTATION
  • Qname

1.4.2. Validation avec SAX

Grâce à l’API JAXP, il est possible d’appliquer un schéma xsd à un document XML et ainsi de valider dynamiquement ce document XML.

Voici un exemple de validation XSD réalisé à partir de l’exemple précédent. Il permet de s’assurer que le document livres.xml valide bien le schéma validationLivres.xsd.

package exemplejavaxml;

import java.io.File;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.ContentHandler;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.helpers.XMLReaderFactory;

public class Main {

static final String JAXP_SCHEMA_LANGUAGE = « http://java.sun.com/xml/jaxp/properties/schemaLanguage »;

static final String W3C_XML_SCHEMA = « http://www.w3.org/2001/XMLSchema »;

static final String JAXP_SCHEMA_SOURCE = « http://java.sun.com/xml/jaxp/properties/schemaSource »;

public static void main(String[] args) throws ParserConfigurationException

{

String file = new String( »livres.xml »);

XMLReader saxReader = null;

DefaultHandler handler = new MyContentHandler();

SAXParserFactory factory = SAXParserFactory.newInstance();

factory.setNamespaceAware(true);

factory.setValidating(true);

try

{

SAXParser saxParser = factory.newSAXParser();

saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);

saxParser.setProperty(JAXP_SCHEMA_SOURCE, « validationLivres.xsd »);

saxParser.parse( new File(file), handler);

}

catch (Throwable t)

{

t.printStackTrace();

System.exit (1);

}

System.exit (0);

}

}

Les lignes modifiées sont en gras. Il faut tout d’abord définir les variables relatives aux différents schémas utilisés. Ensuite, il faut préciser à notre SAXParserFactory que le document xml doit être validé. Enfin, Il faut appliquer cette validation au parser SAX.

1.5. Transformations XSL

1.5.1. Présentation

La principale fonction de XSLT est de définir un style à appliquer à des documents XML (c’est en quelques sorte le principe des CSS appliqué au XML).
XSLT utilise le langage d’expressions XPath pour sélectionner une partie d’un document XML à transformer.

L’API JAXP offre un ensemble de classes et de méthodes destinées à appliquer des transformations XSL à un fichier XML.

1.5.2. Exemple

Voici un exemple très simple d’un programme Java qui applique une transformation XSL :

 

package com.javaXml.xslt;

import java.io.File;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class GoTransfo
{
public static void main(String[] args) throws Exception
{
TransformerFactory fabrique;
StreamSource xml;
StreamSource xslt;
StreamResult dest;
Transformer transformation;

fabrique = TransformerFactory.newInstance();
xml = new StreamSource(new File(«livres.xml »));
xslt = new StreamSource(new File(« transformationLivres.xsl »);
transformation = fabrique.newTransformer(xslt);
dest = new StreamResult(System.out);
transformation.transform(xml, dest);
}
}

 

Il suffit de créer deux instances de la classe StreamSource (une pour le fichier XML, l’autre pour le fichier XSLT). Ensuite, à l’aide de la fabrique TransformerFactory, on applique la transformation. Le résultat sera ici affiché dans la console. Il est possible de tester cet exemple avec le fichier xsl (transformationLivres.xsl) suivant qui affichera le livre dans un tableau :

<?xml version=’1.0′?>
<xsl:stylesheet xmlns:xsl= »http://www.w3.org/TR/WD-xsl »> <xsl:template match= »/ »>
<html>
<body>

<table border= »1″>

<tr>
<th>ISBN</th>

<th>Titre</th>

</tr>
<xsl:for-each select= »livre »>
<tr>
<td><xsl:value-of select= »isbn »/></td>
<td><xsl:value-of select= »titre »/></td>
</tr>
</xsl:for-each>

</table>

</body>
</html>
</xsl:template>
</xsl:stylesheet>

 

2. Autres API pour le traitement des fichiers XML

2.1. JAXB

JAXB permet de réaliser du “DataBinding” des instances d’objets Java et un document XML et inversement : il est aussi possible de « mapper » un schéma XML à une instance de classe. Il est ainsi très facile de sérialiser et déserialiser des objets Java en XML.

Cette nouvelle API permet donc d’accéder plus rapidement à des documents XML à partir du langage Java.

JAXB utilise des schémas pour faire ce lien.

L’avantage de JAXB par rapport à JAXP est de pouvoir accéder et parser des document XML sans avoir de connaissances du langage XML au préalable.

Il n’y a donc pas besoin par exemple de créer un parser SAX.

JAXB est utilisé par JAX-WS (que nous détaillerons plus loin dans cet article) comme modèle de données standard pour les web services.

Le fonctionnement de JAXB est assez simple : un schéma doit décrire les règles de base d’un document XML. C’est en compilant ce schéma que JAXB génère une classe. Il sera ensuite possible d’instancier cette classe et ainsi d’obtenir une instance de classe correspondante au document XML.

Pour utiliser JAXB, il faut avoir téléchargé et installé le Java Web Service Developer Pack. Celui-ci est disponible à l’adresse suivante : http://java.sun.com/webservices/downloads/1.6/index.html.

Une fois le developer pack installé, il est possible de développer des applications utilisant JAXB. Après l’installation, un répertoire est créé avec de nombreux exemples et de la documentation qui vous permettront de réaliser rapidement vos premier exemples avec JAXB.

2.2. JDOM : une API plus simple que DOM

L’API JDOM remplit les mêmes fonctions que DOM.

Cette API ayant été développée spécialement pour le langage Java (contrairement à DOM), son utilisation est simplifiée. JDOM permet donc de manipuler plus facilement un document XML en Java que DOM.

Voici le premier exemple (création du document xml avec DOM) réalisé avec JDOM :

<livre>

<ISBN>2203340273</ISBN>

<titre>Titre du livre</titre>

<auteur>

<nom>Nom auteur</nom>

<prenom>Prénom auteur</prenom>

</auteur>

<dateParution>31/12/2006</dateParution>

<editeur>Nom éditeur</editeur>

</livre>

import java.io.*;
import org.jdom.*;
import org.jdom.output.*;

public class JDOM1
{
Element racine = new Element(« livre »);
org.jdom.Document document = new Document(racine);

public static void main(String[] args)
{
Element isbn = new Element(« isbn »);
racine.addContent(isbn);

Element titre = new Element(« titre« );
racine.addContent(titre);

Element auteur = new Element(« auteur« );
racine.addContent(auteur);

Element nomAuteur = new Element(« nom »);
auteur.addContent(nomAuteur);

Element prenomAuteur = new Element(« prenom »);
auteur.addContent(prenomAuteur);

Element dateParution = new Element(« dateParution« );
racine.addContent(titre);

Element editeur = new Element(« editeur« );
racine.addContent(editeur);

try
{
XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
out.output(document, new FileOutputStream(«livres.xml » ));
}
catch (java.io.IOException e){}

}
}

 

3. Les autres utilisations du XML

3.1. Le XML pour les web services


XML étant un format standard, il est également utilisé pour la technologie des web services que ce soit pour le fichier de description (fichier WSDL) ou pour la communication des données (ex. SOAP).

Le langage Java fournit bien évidement une API permettant de créer des web services basés sur Xml : JAX-WS.

JAX-WS (Java Api for Xml based Web Services) est la toute nouvelle API permettant de créer des web services fournie par Sun. JAX-WS facilite le développement de web services grâce aux annotations qui permettent de générer automatiquement tout le code XML.

JAX-WS est le successeur de JAX-RPC et utilise l’API JAXB.

3.2. ROME : créer vos flux RSS en Java

Une des autres utilisations pratiques du XML est la création de flux d’informations dans un format standard qui peuvent ensuite être manipulés par de nombreux langages et logiciel. Il existe deux types de flux standard RSS et ATOM.

L’API ROME permet, à partir du langage Java, de créer les fichiers XML correspondant à ces deux types de flux. En effet, cette librairie open source offre un ensemble de classes pour générer ou lire des flux RSS et ATOM.

Les formats supportés sont les suivants :

- RSS 0.90

- RSS 0.91 Netscape

- RSS 0.91 Userland

- RSS 0.92

- RSS 0.93

- RSS 0.94

- RSS 1.0

- RSS 2.0

- Atom 0.3

- Atom 1.0

A noter que ROME se base sur l’API JDOM décrite précédemment. Pour créer un flux RSS avec ROME, il faut donc disposer de JDOM. ROME est disponible pour J2SE 1.4 ou supérieur.

String feedGeneralType = « rss_2.0″;

String feedGeneralName = « fluxRSS.xml »;

SyndFeed feedGeneral = new SyndFeedImpl();

feedGeneral.setFeedType(feedGeneralType);

feedGeneral.setTitle( »Test de flux RSS »);

feedGeneral.setLink( »http://www.monSite.com »);

feedGeneral.setDescription( »Description du flux »);

SyndEntry entry;

SyndContent description;

entry = new SyndEntryImpl();

entry.setTitle(“Test de flux”);

entry.setLink( »http://www.monSite.com/article.html”); entry.setPublishedDate(DateParser.parseDate(“31-12-2007”));

description = new SyndContentImpl();

description.setType( »text/plain »);

description.setValue(« Voici la description de notre flux » );

entry.setDescription(description);

entries.add(entry);

Writer writer = new FileWriter(fileName);

SyndFeedOutput output = new SyndFeedOutput();

output.output(feed,writer);

writer.close();

 

4. Conclusion

De nombreuses API permettent de simplifier le traitement des fichiers XML en Java. JAXP, qui est inclus dans le JDK, regroupe toutes les API pour lire, créer, valider ou transformer un document XML mais il en existe d’autres qui peuvent être parfois plus simples. Chaque interface de programmation peut être utilisée dans certains cas précis. SAX sera utile pour lire des documents XML assez volumineux, pour la création ou la modification d’un document XML on pourra utiliser JDOM qui a été créé spécifiquement pour Java, pour valider un document XML ou pour les transformation XSLT on peut utiliser les API fournies avec JAXP…

Pour certaines utilisations du XML, il est possible de se servir d’API spécifiques comme ROME pour les flux RSS par exemple.

A noter qu’il est également possible de manipuler les documents XML autrement avec JAXB (DataBinding).

Catégorisé dans : Java EE

Trackbacks

URL


Questions et commentaires

Les commentaires de ce post en RSS
Aucun commentaire pour le moment.

Un commentaire ? Une question ?


Poste ici :

(obligatoire)
En aucun cas votre adresse ne sera utilisée de maniere frauduleuse. Ce champs sert simplement a éviter le spam.
J'ai un site ou un blog >>

Ce blog est un ensemble de ressources concernant le développement d'applications et de sites web en particulier sur la plateforme Java EE (Struts, JSF).

SERVICES PRO.


Je propose mes services en tant qu'auto entrepreneur
pour du développement de logiciels spécifiques
sur les technologies suivantes :
JSF, Hibernate, EJB, Ajax, Talend, Google App Engine
En savoir plus...

COMMUNAUTÉE BLOG 4J

Liens


 

SYNDICATION

Pour recevoir les derniers tutoriels, articles et tips sur Java EE et le développement web.



Les derniers commentaires

annonces publicitaires