问题
I'm building a sample client-server with JAX-RS using JEE7. I'm using Wildfly 10.1
I followed the guy in this video. Here is the code of the war that runs on the application server:
boundary
package contains the 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);
}
}
and the resource
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
package contains the store which is mostly useless in this example
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();
}
}
entity
package contains the entity:
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;
}
}
The parent package contains the Jax-RS application class which I implemented, I hope correctly:
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));
}
}
Now i'm trying to do a GET request like this
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);
where Chicken is
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;
}
}
and I get the error:
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)
What am I doing wrong?
回答1:
As far as I see the client calls for mediatype text/html. But the objectmapper does not know how to write html for an arraylist. What kind of format do you expect xml or 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));
}
}
An other solution would be to set the right requested Content type in the Request: GET Header:
Accept: application/json
POST Header:
Accept: application/json
Content-Type: application/json
The Accept header says in which format the response should be. The Content-Type header says which format the request payload has.
Content Types:
HTML --> text/html
JSON --> application/json
XML --> application/xml
edit: I think the Post has the same issue. We now told the methods that they consume json as input data and return json as output data (produces).
But are those data really set in the request. can you please post how you construct the post.
To match those methods there need to be those two headers in the request:
Accept: application/json
says which format the client expects.
This should match the @Produces
in the service which sets the output format.
Content-Type: application/json
this is the one I think is missing says in which format the POST payload is and this should match the server input @Consumes
来源:https://stackoverflow.com/questions/43833220/get-request-fails-with-jax-rs-could-not-find-messagebodywriter-for-response-obj