JEE, RESTEasy, JSON et jQuery et erreur 415

Dans le cadre du projet que j’effectue pour le monitorat en entreprise, ex-doctorat-conseil (sur lequel je reviendrai plus précisément dans un prochain billet), je développe une application complète en JEE. Dans le but de permettre la pérennisation du projet, un accès REST est mis en place et le format de données utilisé est JSON.

Aujourd’hui, mon problème venait de l’utilisation de JSON/jQuery pour poster (i.e., requête HTTP de type POST) des objets en JSON sur le serveur.

Prenons un exemple simple de type HelloWorld pour la mise en place d’un accès REST sur un serveur web de type Tomcat.

[java]
import javax.ws.rs.GET;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;

@Path("/helloworld")
public class HelloWorldResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON})
@Produces({ MediaType.APPLICATION_JSON})
public MyObject postJSONMess(final MyObject obj) {
//traitement de l’objet et retour de la réponse.
}
}
[/java]

L’objet obj est une instance d’un bean classique dans lequel certaines annotations nécessaires au mapping objet-JSON sont ajoutés :

[java]
@XmlRootElement(name = "myobject")
@XmlAccessorType(XmlAccessType.FIELD)
public class Question implements Serializable {

private static final long serialVersionUID = 1L;
@Basic
@XmlElement
public Integer id;

@Basic
@XmlElement
public String content;

//+getters/setters
}
[/java]

La ressource est accessible à l’adresse /helloworld sur le serveur (annotation @Path). L’annotation @Consumes est utilisée pour spécifier le type MIME accepté par la ressource REST. Noter que l’annotation, ici, est appliquée à la méthode mais peut être appliquée à une classe entière. A contrario, l’annotation @Produces informe sur le format de données renvoyé au client. Dans l’exemple et pour le projet, le format utilisé est JSON.

Coté client, pour une meilleure « expérience utilisateur », j’utilise jQuery et la ressource est invoquée via une requête POST en AJAX. Synthétiquement, voici à quoi ça ressemble :

[javascript]
var data ={"myobject":{"id":-1, "content": content}};
$.ajax({
type: "POST",
url: "/helloworld/",
data: data,
dataType: "json",
success: function(j) {
//traiement en cas succès
}
});
[/javascript]

Malheureusement, pour chaque requête POST envoyée par le client au serveur, ce dernier renvoyait toujours une erreur de type 415. Un coup d’oeil sur la doc de la spécification JAX-RS permet d’identifier le problème :

If a resource is unable to consume the MIME type of a client request, the JAX-RS runtime sends back an HTTP 415 (“Unsupported Media Type”) error.

Avant toute modification du code (qui me semble correct), je teste manuellement l’invocation de la ressource en POST (avec avec HTTP4e, ou tout simplement avec curl) et, étrangement, tout fonctionne pour le mieux.

Un coup de WireShark pour voir ce qui est posté réellement avec jQuery, et on remarque très facilement que celui-ci n’envoie absolument pas du JSON mais une requête HTTP POST dans laquelle la partie BODY contient la concaténation des paramêtres : id=1&content=content. En clair, jQuery n’envoie pas du JSON.

Pour contrer ce problème et après pas mal de tests, il suffit simplement de modifier la requête AJAX pour y rajouter manuellement le champ headers et ainsi spécifier que le client envoie des requête HTTP contenant du JSON. Aussi, il est nécessaire de sérialiser notre objet javascript data au format JSON. Pour cela, j’utilise jquery-json, un plugin jQuery qui ajoute plusieurs méthodes à l’objet jQuery $ pour faciliter l’utilisation du format avec notamment la méthode toJSON.

[javascript]
var data ={"myobject":{"id":-1, "content": content}};
$.ajax({
headers:{"Content-Type":"application/json"}
type: "POST",
url: "/helloworld/",
data: $.toJSON(data),
dataType: "json",
success: function(j) {
//traiement en cas succès
}
});
[/javascript]

Clairement, je ne sais pas pourquoi jQuery agit de cette manière. JSON est pourtant un format largement utilisé dans l’API de jQuery. Je vais cependant jeter un oeil et voir si c’est bien la meilleure solution/ une solution viable.

Hello World!

Tout bon apprentissage en informatique se doit de commencer par ce fameux « Hello World! ». Donc ce post n’a pas grand intérêt hormis annoncer la couleur des prochains. Dans ce blog, j’essaierai de partager mes activités de recherches en tant que doctorant en informatique ainsi que toute autre chose susceptible de toucher, de près de ou de loin, à ce que j’apprécie.

Bonne lecture…