2017-05-07 1 views
1

Je construis un exemple client-serveur avec JAX-RS en utilisant JEE7. J'utilise Wildfly 10.1La requête GET échoue avec JAX-RS: Impossible de trouver MessageBodyWriter pour l'objet de réponse de type: java.util.ArrayList de type de média: text/html

J'ai suivi le gars en vidéo this. Voici le code de la guerre qui fonctionne sur le serveur d'application: package

boundary contient le package de service

package pl.devcrowd.virtual.business.chickens.boundary; 

import java.util.List; 

import javax.ejb.Stateless; 
import javax.inject.Inject; 

import pl.devcrowd.virtual.business.chickens.controls.ChickenStore; 
import pl.devcrowd.virtual.business.chickens.entity.Chicken; 

@Stateless 
public class ChickenService { 

    @Inject 
    ChickenStore cs; 

    public List<Chicken> getAllChickens() { 
     return this.cs.all(); 
    } 

    public void save(Chicken chicken) { 
     this.cs.save(chicken); 
    } 
} 

et la ressource

package pl.devcrowd.virtual.business.chickens.boundary; 

import java.util.List; 

import javax.inject.Inject; 
import javax.json.JsonObject; 
import javax.ws.rs.GET; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 

import pl.devcrowd.virtual.business.chickens.entity.Chicken; 

@Path("chickens") 
public class ChickensResource { 

    @Inject 
    ChickenService cs; 

    @GET 
    public List<Chicken> chickens() { 
     return cs.getAllChickens(); 
    } 

    @POST 
    public void save(JsonObject chicken) { 
     String name = chicken.getString("name"); 
     int age = chicken.getInt("age"); 
     cs.save(new Chicken(name, age)); 
    } 
} 

control contient le magasin qui est la plupart du temps inutile dans cet exemple

package pl.devcrowd.virtual.business.chickens.controls; 

import java.util.List; 

import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import pl.devcrowd.virtual.business.chickens.entity.Chicken; 

public class ChickenStore { 

    @PersistenceContext 
    EntityManager em; 

    public void save(Chicken chicken) { 
     em.merge(chicken); 
    } 

    public List<Chicken> all() { 
     return this.em 
       .createNamedQuery("all", Chicken.class) 
       .getResultList(); 
    } 
} 

package entity contient l'entité:

package pl.devcrowd.virtual.business.chickens.entity; 

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.NamedQuery; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement 
@Entity 
@NamedQuery(name="all", query = "SELECT c FROM Chicken C") 
public class Chicken { 

    @Id 
    @GeneratedValue 
    private long id; 
    private String name; 
    private int age; 

    public Chicken() {} 

    public Chicken(String name, int age) { 
     this.name = name; 
     this.age = age; 
    } 
} 

Le package parent contient le JAX-RS classe d'application que je mis en œuvre, je l'espère bien:

package pl.devcrowd.virtual.business; 

import java.util.Arrays; 
import java.util.HashSet; 
import java.util.Set; 

import javax.ws.rs.ApplicationPath; 
import javax.ws.rs.core.Application; 

import pl.devcrowd.virtual.business.chickens.boundary.ChickensResource; 

/** 
* Configures a JAX-RS endpoint. Delete this class, if you are not exposing 
* JAX-RS resources in your application. 
* 
* @author airhacks.com 
*/ 
@ApplicationPath("resources") 
public class JAXRSConfiguration extends Application { 
    public Set<Class<?>> getClasses() { 
     return new HashSet<Class<?>>(Arrays.asList(ChickensResource.class)); 
    } 
} 

Maintenant, je suis en train de faire une requête GET comme ce

RestClient get = RestClient.create().method("GET") 
     .host("http://localhost:8080/DevCrowd") 
     .path("resources/chickens"); 
GluonObservableList<Chicken> sample = DataProvider.retrieveList(
     get.createListDataReader(Chicken.class)); 
System.out.println(sample); 

où poulet est

public class Chicken { 

    private String name; 
    private int age; 

    public Chicken(String name, int age) { 
     this.name = name; 
     this.age = age; 
    } 

    public int getAge() { 
     return age; 
    } 

    public void setAge(int age) { 
     this.age = age; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

et je reçois l'erreur:

05:59:17,019 ERROR [org.jboss.resteasy.resteasy_jaxrs.i18n] (default task-3) RESTEASY002005: Failed executing GET /chickens: org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: text/html 
    at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:66) 
    at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:473) 
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:422) 
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209) 
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221) 
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) 
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) 
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) 
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) 
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) 
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) 
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) 
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) 
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

Qu'est-ce que je fais mal?

Répondre

1

Pour autant que je vois les appels client pour mediatype text/html. Mais l'objectmapper ne sait pas comment écrire html pour un arraylist. Quel type de format attendez-vous xml ou json?

@Path("chickens") 
public class ChickensResource { 

    @Inject 
    ChickenService cs; 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<Chicken> chickens() { 
     return cs.getAllChickens(); 
    } 

    @POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.APPLICATION_JSON) 
    public void save(JsonObject chicken) { 
     String name = chicken.getString("name"); 
     int age = chicken.getInt("age"); 
     cs.save(new Chicken(name, age)); 
    } 
} 

Une autre solution serait de mettre le droit demandé le type de contenu dans la demande: GET tête:

Accept: application/json 

POST-tête:

Accept: application/json 
Content-Type: application/json 

L'en-tête Accept dit dans lequel formater la réponse devrait être. L'en-tête Content-Type indique le format de la charge utile de requête.

types de contenu:

HTML --> text/html 
JSON --> application/json 
XML --> application/xml 

modifier: Je pense que le message a la même question. Nous avons maintenant dit aux méthodes qu'ils consommaient json comme données d'entrée et renvoyaient json comme données de sortie (produit).

Mais ces données sont-elles réellement définies dans la requête? Pouvez-vous s'il vous plaît poster comment vous construisez le poste.

Pour correspondre à ces méthodes, ces deux en-têtes doivent figurer dans la requête: Accept: application/json indique le format attendu par le client. Cela doit correspondre au @Produces du service qui définit le format de sortie. Content-Type: application/json c'est celui que je pense manque indique dans quel format la charge POST est et cela doit correspondre à l'entrée du serveur @Consumes

+0

J'ai ajouté le '@ Consumes' et' @ Produces'. GET fonctionne maintenant et je reçois une liste vide '[]' comme je devrais! Merci! Maintenant, j'ai un problème avec POST: 'Impossible d'exécuter: javax.ws.rs.NotSupportedException: RESTEASY003065: Impossible de consommer le type de contenu'. Je peux poser une nouvelle question au sujet du POST parce que celui-ci visait à faire fonctionner GET, mais avez-vous une idée du problème? Client ou serveur? Je comprends ce que signifie l'erreur, pas pourquoi cela se produit ou comment y remédier. – Mark