我的Jersey REST服务设置如下:
@GET
@Path(ResourceConstants.PATH_START_BATCH)
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public ServiceResponse startBatch(@QueryParam(ResourceConstants.PARAM_BATCH_ID) String batchId)
{
ServiceResponse serviceResponse = new ServiceResponse();
try
{
// will throw exception on error
this.processorService.startBatch(batchId);
Map<String, String> responseDetails = serviceResponse.getResponseDetails();
responseDetails.put("success", "success");
return serviceResponse;
}
catch (Exception ex)
{
Map<String, String> responseDetails = serviceResponse.getResponseDetails();
responseDetails.put("Failure", "Failed to start with exception " + ex.getMessage());
throw WebServiceException.generate(ex, serviceResponse);
}
finally
{
logger.debug("Exit startBatch");
}
}
ServiceResponse看起来像这样:
@XmlRootElement
public class ServiceResponse implements Serializable
{
private static final long serialVersionUID = 1L;
private HashMap<String, String> responseDetails;
public ServiceResponse()
{
this.setResponseDetails(new HashMap<String, String>());
}
public HashMap<String, String> getResponseDetails()
{
return responseDetails;
}
public void setResponseDetails(HashMap<String, String> responseDetails)
{
this.responseDetails = responseDetails;
}
}
我写了一个看起来像这样的小测试客户端:
public class ProcessorClient
{
public static void main(String[] args)
{
String batchId = "472539";
Client client = ClientBuilder.newClient();
client.register(JacksonFeature.class);
WebTarget webTarget = client.target("http://localhost:8080/")
.path(ResourceConstants.PATH_START_BATCH)
.queryParam("batchId", batchId);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
Response response = invocationBuilder.get();
int responseStatus = response.getStatus();
ServiceResponse serviceResponse = response.readEntity(ServiceResponse.class);
serviceResponse.getResponseDetails();
}
}
运行客户端工作正常,正文中的XML被解组到ServiceResponse对象中。但是,当我们改变时:
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
为:
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
我们收到错误。我使用Maven并包含以下依赖项:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.4</version>
</dependency>
如上所示我正在客户端注册JacksonFeature。但是,我必须遗漏一些东西。我还没有找到使用杰克逊和泽西2.x的任何好的方法/例子。缺少什么,以便客户端可以从响应正文中的json字符串创建ServiceResponse对象?
错误:
Exception in thread "main" javax.ws.rs.ProcessingException: Error reading entity from input stream.
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:867)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.ScopedJaxrsResponse.access$001(ScopedJaxrsResponse.java:56)
at org.glassfish.jersey.client.ScopedJaxrsResponse$1.call(ScopedJaxrsResponse.java:77)
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:397)
at org.glassfish.jersey.client.ScopedJaxrsResponse.readEntity(ScopedJaxrsResponse.java:74)
at ca.shaw.tno.oss.dvc.processor.client.ProcessorClient.main(ProcessorClient.java:36)
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
at [Source: org.glassfish.jersey.message.internal.EntityInputStream@7ce5b708; line: 1, column: 21] (through reference chain: ca.shaw.tno.oss.dvc.common.webresource.ServiceResponse["responseDetails"])
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:44)
at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:13)
at org.codehaus.jackson.map.deser.std.MapDeserializer._readAndBind(MapDeserializer.java:319)
at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:249)
at org.codehaus.jackson.map.deser.std.MapDeserializer.deserialize(MapDeserializer.java:33)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:299)
at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:414)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:697)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315)
at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:419)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:239)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:211)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)
... 10 more
修改
这里是请求JSON时从浏览器返回的响应正文:
{"responseDetails":{"entry":[{"key":"Failure","value":"Failed to start with exception Could not find batch with ID=abc"}]}}