GET 请求因 JAX-RS 失败:找不到 MessageBodyWriter 类型的响应对象:java.util.ArrayList 媒体类型:text/html
GET request fails with JAX-RS: Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: text/html
我正在使用 JEE7 使用 JAX-RS 构建示例客户端服务器。我正在使用 Wildfly 10.1
我关注了 this 视频中的那个人。这是在应用程序服务器上运行的 war 的代码:
boundary
包裹包含服务
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);
}
}
和资源
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 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 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;
}
}
父包包含我实现的 Jax-RS 应用程序 class,希望正确:
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));
}
}
现在我正在尝试执行这样的 GET 请求
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);
鸡在哪里
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;
}
}
我收到错误:
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.access0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=19=]0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.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)
我做错了什么?
据我所知,客户端需要 mediatype text/html。但是 objectmapper 不知道如何为数组列表编写 html。
您希望 xml 或 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));
}
}
另一种解决方案是在请求中设置正确的请求内容类型:
获取 Header:
Accept: application/json
POST Header:
Accept: application/json
Content-Type: application/json
Accept header 表示响应应采用哪种格式。
Content-Type header 表示请求负载的格式。
内容类型:
HTML --> text/html
JSON --> application/json
XML --> application/xml
编辑:我认为 Post 有同样的问题。我们现在告诉方法,它们将 json 作为输入数据,将 return json 作为输出数据(产生)。
但是请求中真的设置了那些数据吗? post 你可以如何构建 post.
要匹配这些方法,请求中需要有这两个 header:
Accept: application/json
表示客户期望的格式。
这应该与设置输出格式的服务中的 @Produces
匹配。
Content-Type: application/json
这是我认为缺少的那个 POST 有效载荷的格式,这应该与服务器输入相匹配 @Consumes
我正在使用 JEE7 使用 JAX-RS 构建示例客户端服务器。我正在使用 Wildfly 10.1
我关注了 this 视频中的那个人。这是在应用程序服务器上运行的 war 的代码:
boundary
包裹包含服务
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);
}
}
和资源
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 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 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;
}
}
父包包含我实现的 Jax-RS 应用程序 class,希望正确:
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));
}
}
现在我正在尝试执行这样的 GET 请求
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);
鸡在哪里
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;
}
}
我收到错误:
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.access0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access[=19=]0(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.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)
我做错了什么?
据我所知,客户端需要 mediatype text/html。但是 objectmapper 不知道如何为数组列表编写 html。 您希望 xml 或 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));
}
}
另一种解决方案是在请求中设置正确的请求内容类型: 获取 Header:
Accept: application/json
POST Header:
Accept: application/json
Content-Type: application/json
Accept header 表示响应应采用哪种格式。 Content-Type header 表示请求负载的格式。
内容类型:
HTML --> text/html
JSON --> application/json
XML --> application/xml
编辑:我认为 Post 有同样的问题。我们现在告诉方法,它们将 json 作为输入数据,将 return json 作为输出数据(产生)。
但是请求中真的设置了那些数据吗? post 你可以如何构建 post.
要匹配这些方法,请求中需要有这两个 header:
Accept: application/json
表示客户期望的格式。
这应该与设置输出格式的服务中的 @Produces
匹配。
Content-Type: application/json
这是我认为缺少的那个 POST 有效载荷的格式,这应该与服务器输入相匹配 @Consumes