我正在使用CXF rest客户端,该客户端适用于简单的数据类型(例如:字符串,整数)。但是,当我尝试使用自定义对象时,得到以下信息:
Exception in thread "main" org.apache.cxf.interceptor.Fault: .No message body writer found for class : class com.company.datatype.normal.MyObject.
at org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter.handleMessage(ClientProxyImpl.java:523)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.doChainedInvocation(ClientProxyImpl.java:438)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.invoke(ClientProxyImpl.java:177)
at $Proxy13.execute(Unknown Source)
at com.company.JaxTestClient.main(JaxTestClient.java:26)
Caused by: org.apache.cxf.jaxrs.client.ClientWebApplicationException: .No message body writer found for class : class com.company.datatype.normal.MyObject.
at org.apache.cxf.jaxrs.client.AbstractClient.reportMessageHandlerProblem(AbstractClient.java:491)
at org.apache.cxf.jaxrs.client.AbstractClient.writeBody(AbstractClient.java:401)
at org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter.handleMessage(ClientProxyImpl.java:515)
... 5 more
我这样称呼它:
JaxExample jaxExample = JAXRSClientFactory.create( "http://localhost:8111/", JaxExample.class );
MyObject before = ...
MyObject after = jaxExample.execute( before );
这是界面中的方法:
@POST
@Path( "execute" )
@Produces( "application/json" )
MyObject execute( MyObject myObject );
restlet库通过将XStream依赖项添加到您的路径“非常有效”来非常简单地完成此操作。CXF是否类似?
编辑#1:
我已为这是一个功能完善的CXF问题管理系统在这里。我只能希望这会得到关注。
它不是开箱即用的,但是CXF确实支持JSON绑定到其他服务。请参阅此处的cxf jax-rs
json文档。
您仍然需要做一些最小的配置来使提供程序可用,并且如果您想对JSON的形成方式有更多的控制,就需要熟悉Jettison。
编辑: 每个评论请求,这是一些代码。我没有很多经验,但是以下代码在快速测试系统中作为示例。
//TestApi parts
@GET
@Path ( "test" )
@Produces ( "application/json" )
public Demo getDemo () {
Demo d = new Demo ();
d.id = 1;
d.name = "test";
return d;
}
//client config for a TestApi interface
List providers = new ArrayList ();
JSONProvider jsonProvider = new JSONProvider ();
Map<String, String> map = new HashMap<String, String> ();
map.put ( "http://www.myserviceapi.com", "myapi" );
jsonProvider.setNamespaceMap ( map );
providers.add ( jsonProvider );
TestApi proxy = JAXRSClientFactory.create ( url, TestApi.class,
providers, true );
Demo d = proxy.getDemo ();
if ( d != null ) {
System.out.println ( d.id + ":" + d.name );
}
//the Demo class
@XmlRootElement ( name = "demo", namespace = "http://www.myserviceapi.com" )
@XmlType ( name = "demo", namespace = "http://www.myserviceapi.com",
propOrder = { "name", "id" } )
@XmlAccessorType ( XmlAccessType.FIELD )
public class Demo {
public String name;
public int id;
}
笔记:
作为示例,这有点脏,但是希望可以帮助您。
Edit2: 基于xstream以避免jaxb的消息正文编写器的示例。
@Produces ( "application/json" )
@Consumes ( "application/json" )
@Provider
public class XstreamJsonProvider implements MessageBodyReader<Object>,
MessageBodyWriter<Object> {
@Override
public boolean isWriteable ( Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
return MediaType.APPLICATION_JSON_TYPE.equals ( mediaType )
&& type.equals ( Demo.class );
}
@Override
public long getSize ( Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
// I'm being lazy - should compute the actual size
return -1;
}
@Override
public void writeTo ( Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream )
throws IOException, WebApplicationException {
// deal with thread safe use of xstream, etc.
XStream xstream = new XStream ( new JettisonMappedXmlDriver () );
xstream.setMode ( XStream.NO_REFERENCES );
// add safer encoding, error handling, etc.
xstream.toXML ( t, entityStream );
}
@Override
public boolean isReadable ( Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType ) {
return MediaType.APPLICATION_JSON_TYPE.equals ( mediaType )
&& type.equals ( Demo.class );
}
@Override
public Object readFrom ( Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream )
throws IOException, WebApplicationException {
// add error handling, etc.
XStream xstream = new XStream ( new JettisonMappedXmlDriver () );
return xstream.fromXML ( entityStream );
}
}
//now your client just needs this
List providers = new ArrayList ();
XstreamJsonProvider jsonProvider = new XstreamJsonProvider ();
providers.add ( jsonProvider );
TestApi proxy = JAXRSClientFactory.create ( url, TestApi.class,
providers, true );
Demo d = proxy.getDemo ();
if ( d != null ) {
System.out.println ( d.id + ":" + d.name );
}
该示例代码缺少可靠的媒体类型支持,错误处理,线程安全性等部分。但是,它应该以最少的代码解决jaxb问题。
编辑3-服务器端配置示例 如前所述,我的服务器端是spring配置的。这是一个示例配置,可用于连接提供程序:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<jaxrs:server id="TestApi">
<jaxrs:serviceBeans>
<ref bean="testApi" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean id="xstreamJsonProvider" class="webtests.rest.XstreamJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="testApi" class="webtests.rest.TestApi">
</bean>
</beans>
我还注意到,在我使用的最新版本的cxf中,媒体类型有所不同,因此,上面xstream消息正文阅读器/编写器上的示例需要对isWritable /
isReadable进行快速修改,以将其更改为:
return MediaType.APPLICATION_JSON_TYPE.getType ().equals ( mediaType.getType () )
&& MediaType.APPLICATION_JSON_TYPE.getSubtype ().equals ( mediaType.getSubtype () )
&& type.equals ( Demo.class );
编辑4-非弹簧配置 使用您选择的servlet容器进行配置
org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
至少有两个init参数:
jaxrs.serviceClasses
jaxrs.providers
其中,serviceClasses是要绑定的服务实现的空格分隔列表,例如上面提到的TestApi,provider是消息主体提供程序的空格分隔列表,例如上面提到的XstreamJsonProvider。在tomcat中,您可以将以下内容添加到web.xml:
<servlet>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
<init-param>
<param-name>jaxrs.serviceClasses</param-name>
<param-value>webtests.rest.TestApi</param-value>
</init-param>
<init-param>
<param-name>jaxrs.providers</param-name>
<param-value>webtests.rest.XstreamJsonProvider</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
这几乎是没有弹簧即可运行它的最快方法。如果不使用servlet容器,则需要使用XstreamJsonProvider的实例配置JAXRSServerFactoryBean.setProviders并通过JAXRSServerFactoryBean.setResourceProvider方法设置服务实现。检查CXFNonSpringJaxrsServlet.init方法以查看在servlet容器中设置时它们如何执行。
无论您遇到什么情况,这都应该使您能够前进。
问题内容: 当我尝试返回List时,没有找到响应类ArrayList的消息正文编写器。 我有如下代码: 请帮我。提前致谢 问题答案: 要返回列表,最好将其包装到带注释的容器中,并将该列表作为字段添加到该容器中,并标记为。 像这样:
问题内容: 我正在使用Jersey来构建REST服务,并希望返回XML。 但是我的尝试失败,但有以下异常: javax.ws.rs.WebApplicationException:com.sun.jersey.api.MessageException:Java类java.util.ArrayList和Java类型类java.util.ArrayList和MIME媒体类型text / xml的消息正
我的构建路径中有jersey-client-2.25.1,我知道它有默认的提供者来转换javax。ws。rs.core。表单到应用程序/x-www-Form-urlencoded。 但对于此代码: 我不断得到: 我不应该按照这个注册一个MultiPart类。
我正试图让Jersey支持GSON,为此我了解到我需要实现一个自定义的MessageBodyWriter和MessageBodyReader。 现在我的问题是我找不到这两个接口的任何明确定义。 从文档中: 支持将Java类型转换为流的提供程序的契约。要添加MessageBodyWriter实现,请使用@Provider注释实现类。MessageBodyWriter实现可以使用Produces注释以
问题内容: 在尝试找出我的问题之后,我终于决定问您如何解决我的问题。我见过不同的人有相同的问题,我尝试了所有建议他们做的事情,但没有任何帮助解决我的问题。所以基本上我有一个使用Jersey进行构建的RESTful服务。对于我的客户,我想返回JSON格式的对象。我通读了不同的教程,并决定使用jersey- json-1.8库是有意义的。我像往常一样将所有内容添加到我的项目中,并尝试运行它,但是每次调
问题内容: 我正在测试RESTful服务,当我执行RESTful服务时,尽管我的类路径(WEB-INF / lib)中包含以下jar,但是却遇到异常,但我没有使用Maven,而我的JDK版本是1.5。有关此问题的其他问题无助于解决问题。 程式码片段 web.xml 罐子清单 异常堆栈 我该如何解决这个问题? 问题答案: 确保您的项目中没有多个Jersey版本。在您提供的列表中,有3个不同版本(1.