J'implémente une architecture client/serveur de base utilisant les services REST pour la première fois. Cette fois, je complique les choses en incluant plus de classes et de services avec des objets de classe de partage en tant que paramètres entre le client et le serveur. J'exécute le serveur sur ApacheTomcat7. Il s'exécute avec succès. Lorsque j'exécute mon client, cela me donne l'erreur: javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
J'ai essayé de déboguer mon code, il semble que je ne reçoive/envoie pas de réponse. Je sais que ce n’est pas une bonne idée de partager tous les cours ici, mais je n’ai pas le choix, c’est beaucoup de perte de temps. Toute aide serait appréciée. Merci d'avance.
Voici ma classe ImageProgress. Cette classe est présente sur le serveur et le client.
@XmlRootElement
public class ImageProgress{
private String name;
public ImageProgress( String image_name){
this.name = image_name;
}
public String getName() {
return name;
}
public void setName( String name ){
this.name = name;
}
}
HPCResponse est la classe dont l'objet sera renvoyé au client en tant que réponse du serveur. HPCResponse renverra fondamentalement l'objet ImageProgress qui me donnera le résultat souhaité.
@XmlRootElement
public class HPCResponse
{
private ImageProgress imgProgress;
public ImageProgress getImgProgress() {
return imgProgress;
}
public void setImgProgress(ImageProgress imgProgress) {
this.imgProgress = imgProgress;
}
}
Vous trouverez ci-dessous la classe de service du serveur nommé HpcService, qui renvoie l'objet de HPCResponse en réponse. Comme vous pouvez le voir, la méthode startAnalysing accepte l’objet de HPCInfo. La description de HPCInfo est également donnée ci-dessous.
@Path( "/hpc" )
@Consumes( MediaType.APPLICATION_XML )
@Produces( MediaType.APPLICATION_XML )
public class HpcService{
public HPCInfo hpcInfo;
public HPCResponse hpcResponse;
@POST
@Path( "/analyze" )
public HPCResponse startAnalysing(HPCInfo _hpcInfo){
System.out.println( "Started Analyzing..." );
hpcInfo = _hpcInfo;
hpcInfo.getImagePath();
hpcResponse = new HPCResponse();
ImageProgress iProg = new ImageProgress(hpcInfo.getImagePath());
hpcResponse.setImgProgress(iProg);
System.out.println("Returning response...");
return hpcResponse;
}
}
La classe HPCInfo est également à la fois client et serveur. Classe HPCInfo:
@XmlRootElement
public class HPCInfo
{
private String imagePath = "";
public String getImagePath(){
return imagePath;
}
public void setImagePath( String imagePath ){
this.imagePath = imagePath;
}
}
Et enfin, c’est mon client qui appelle HPCService.
public class TestClient {
private static String webServiceURI = "http://localhost:8080/TestServer123";
public static void main(String[] args) {
String input = "ABNKidney.scn";
ClientConfig clientConfig = new ClientConfig();
Client client = ClientBuilder.newClient(clientConfig);
URI serviceURI = UriBuilder.fromUri(webServiceURI).build();
WebTarget webTarget = client.target(serviceURI);
HPCInfo info = new HPCInfo();
info.setImagePath(input);
webTarget = webTarget.path("test").path("hpc").path("analyze");
HPCResponse hResponse = webTarget.request().accept(MediaType.APPLICATION_XML).post(Entity.entity(info, MediaType.APPLICATION_XML), HPCResponse.class);
}
}
Voici la description complète de l'erreur que j'obtiens:
javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.Java:968)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.Java:795)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.Java:91)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.Java:683)
at org.glassfish.jersey.internal.Errors.process(Errors.Java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.Java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.Java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.Java:424)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.Java:679)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.Java:435)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.Java:338)
at com.TestClient.main(TestClient.Java:34)
Une façon de déboguer des choses comme celle-ci est de créer une simple variable ExceptionMapper
pour intercepter les exceptions qui ne sont pas mappées. Lorsqu'il n'y a pas de mappeur, l'exception va souvent remonter jusqu'au niveau du conteneur, ce qui nous donne simplement une erreur générique du serveur 500 (qui, la plupart du temps, est d'une aide minime).
@Provider
public class DebugExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
exception.printStackTrace();
return Response.serverError().entity(exception.getMessage()).build();
}
}
Ensuite, enregistrez simplement le mappeur. Lorsque vous exécutez un test simple avec votre classe ImageProgress
, lorsque l'exception est levée, la trace de pile est imprimée et vous pouvez voir le message d'exception.
... ImageProgress n'a pas de constructeur par défaut sans argument
Ajoutez donc simplement un constructeur par défaut (constructeur sans argument) à la classe ImageProgress
. Ceci est une exigence avec les modèles JAXB.
Ajoutez cette ligne de code avant class HPCResponse
:
@XmlAccessorType(XmlAccessType.FIELD)