Skip to content
Snippets Groups Projects
Commit e862213e authored by Yvan Peter's avatar Yvan Peter
Browse files

Ajout de la représentation XML

parent c648cf1e
No related branches found
No related tags found
No related merge requests found
......@@ -157,7 +157,7 @@ Ajoutez (et testez) à votre ressource une méthode `getMontantTotal` qui renver
### Renvoyer des données plus complexes
Jusqu'à maintenant, nous avons transmis de simples valeurs numériques prises en charge directement par Jersey dans le corps de la réponse HTTP. Jersey peut faire la même chose avec des classes Java qui respectent les conventions [`JavaBean`](https://fr.wikipedia.org/wiki/JavaBeans), à minima :
- la classe possède un constructeur sans paramètres (constructeur par défaut);
- les propriétés de la classe sont associées à des accesseurs `get`/`set` pour chaque attribut (par. ex pour un attribut `name` --> `getName()`/`setName()`)
- les propriétés de la classe sont associées à des accesseurs `get`/`set` pour chaque attribut (par. ex pour un attribut `name` --> `getName()`/`setName()`).
Pour un objet de ce type, Jersey va renvoyer dans le corps de la requête un objet (JSON par défaut). Chaque propriété de l'objet java sera représenté par une propriété de l'objet JSON.
......@@ -168,11 +168,13 @@ Nous allons ajouter une méthode permettant au client d'avoir la liste des nivea
~~~java
package fr.ulille.iut.tva.dto;
public class InfoTaux {
public class InfoTauxDto {
private String label;
private double taux;
public InfoTaux(String label, double taux) {
public InfoTauxDto() {}
public InfoTauxDto(String label, double taux) {
this.label = label;
this.taux = taux;
}
......@@ -199,11 +201,11 @@ Nous pouvons maintenant utiliser ce DTO pour renvoyer la liste des taux existant
~~~java
@GET
@Path("taux")
public List<InfoTaux> getInfoTaux() {
ArrayList<InfoTaux> result = new ArrayList<InfoTaux>();
@Path("lestaux")
public List<InfoTauxDto> getInfoTaux() {
ArrayList<InfoTauxDto> result = new ArrayList<InfoTauxDto>();
for ( TauxTva t : TauxTva.values() ) {
result.add(new InfoTaux(t.name(), t.taux));
result.add(new InfoTauxDto(t.name(), t.taux));
}
return result;
}
......@@ -220,6 +222,75 @@ Content-Length: 135
~~~
On peut observer que :
- pour chaque propriété de la classe `InfoTaux`, on a une propriété équivalente dans les objets JSON
- pour chaque propriété de la classe `InfoTauxDto`, on a une propriété équivalente dans les objets JSON
- la liste renvoyée en Java a été convertie en tableau d'objets JSON
- Jersey a choisi le type MIME le plus adapté pour le résultat renvoyé dans le corps de la réponse : `Content-Type: application/json`
### Et les autres formats de données ?
Essayez de faire la requête suivante : `curl -i -H "Accept: application/xml" http://localhost:8080/api/v1/tva/lestaux`. Quel résultat obtenez vous ?
Du côté du serveur, vous devriez observer l'erreur suivante :
~~~
GRAVE: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=java.util.List<fr.ulille.iut.tva.dto.InfoTauxDto>
~~~
Ce message indique que Jersey ne sait pas transformer la liste Java dans une représentation `application/xml`. `MessageBodyWriter` est la classe qui devrait être chargée de faire cette transformation (Elle le fait pour JSON).
Pour gérer XML, il faut deux choses. D'abord s'assurer d'avoir les bonnes libraires dans le projet maven (c'est déjà le cas, ici) :
~~~xml
<dependencies>
...
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>3.0.0</version>
<scope>runtime</scope>
</dependency>
...
</dependencies>
~~~
Ces librairies vont nous permettre d'utiliser [JAXB (Java Architecture for XML Binding)](https://javaee.github.io/jaxb-v2/) qui offre les moyens de définir une transformation entre Java et XML. `JAXB` utilise notamment un ensemble d'annotations qui permettent de spécifier comment les attributs d'une classe seront transformés en XML (et inversement).
Ici, nous allons utiliser tous les comportements par défaut de JAXB et nous n'auront besoin que d'une annotation sur notre DTO :
~~~java
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class InfoTauxDto {
...
}
~~~
Nous pouvons maintenant ressayer notre requête précédente avec succès :
~~~xml
HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 356
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><infoTauxDtoes><infoTauxDto><label>NORMAL</label><taux>20.0</taux></infoTauxDto><infoTauxDto><label>INTERMEDIAIRE</label><taux>10.0</taux></infoTauxDto><infoTauxDto><label>REDUIT</label><taux>5.5</taux></infoTauxDto><infoTauxDto><label>PARTICULIER</label><taux>2.1</taux></infoTauxDto></infoTauxDtoes>
~~~
Refaisons notre requête par défaut par acquis de conscience : `curl -i http://localhost:8080/api/v1/tva/lestaux`. Que se passe-t-il ?
Il semble que du coup, notre ressource réponde en priorité en XML, vérifiez qu'elle sait toujours répondre en JSON.
Pour régler ce problème, nous allons spécifier les représentations possibles avec un ordre de préférence (plutôt du JSON) au moyen de l'annotation [@Produces](https://eclipse-ee4j.github.io/jaxrs-api/apidocs/3.0.0/jakarta/ws/rs/Produces.html) :
~~~java
@GET
@Path("lestaux")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<InfoTauxDto> getInfoTaux() {
...
}
~~~
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment