【发布时间】:2015-04-17 11:17:24
【问题描述】:
我编写了一个 CXF REST 服务,它返回配置如下的 application/json:
前景生成器:
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/consume")
public Prospect convertProspectToJson(Prospect prospect,@QueryParam("customerType") String customerType){
//DTO logic goes here
System.out.println("Prospect obj received.."+prospect.getProspectName());
prospect.setCustomerType(customerType);
return prospect;
}
此服务在部署到 JBoss Fuse 时有效。
现在我有一个骆驼路线构建器,如下所示:
public class ServiceRouter extends RouteBuilder {
/* (non-Javadoc)
* @see org.apache.camel.builder.RouteBuilder#configure()
*/
@Override
public void configure() throws Exception {
from("jetty://http://localhost:8182/route/prospect?bindingStyle=SimpleConsumer")
//The Raw type to String conversion is done here. Refer the class for details
//Processor converts the Message from byte[] to String
.process(new ResponseToStringProcessor())
.unmarshal("jsonDataformat") //jsonDataformat - bean in blueprint XML for converting to requested object type
.to("cxfrs://http://localhost:8181/cxf/prospect/consume")
/*1) The above line has the BodyType as Cxf's ResponseImpl instead of Prospect Object
* 2) The below bean accepts type only as Prospect object and hence I get exception */
.to("bean:prospectService?method=doSomething");
}
ProspectService:
public class ProspectService {
public void doSomething(@Body Prospect prospect){
System.out.println("Prospect Service got the request.."+prospect.getCustomerType());
}
}
我在尝试路由到定义的 bean 时遇到以下异常:
org.apache.camel.InvalidPayloadException:没有可用的类型:com.karthik.bo.Prospect 但有值:org.apache.cxf.jaxrs.impl.ResponseImpl@54c96476 类型
如何解决此错误?我不知道如何将 ResponseImpl 转换为我的 POJO。来的痕迹显示:
BodyType:org.apache.cxf.jaxrs.impl.ResponseImpl, Body:{"prospect":{"customerType":"VIP","prospectId":999,"prospectName":"karthik"} }
我尝试将 ResponseImpl 转换为 String(将包含 JSON 有效负载),但我总是以 IOException 流结束。 - 以下转换代码:
public void convert(Exchange exchange){
InputStream is = (InputStream)exchange.getIn().getBody(ResponseImpl.class).getEntity();
String s="";
try {
s = org.apache.commons.io.IOUtils.toString(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("in convertor..."+s);
}
经过多次失败尝试(在cmets中提到),最终的解决方案是编写一个FallBackCoverter如下 - 这并没有抛出Stream closed IOException,无法解释给自己。
@FallbackConverter
public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry){
System.out.println("Checking fall backconverter");
if (ResponseImpl.class.isAssignableFrom(value.getClass())) {
TypeConverter tc = registry.lookup(type, ResponseImpl.class);
if (tc == null && type.getName().equals("com.karthik.bo.Prospect")) {
Prospect prospect=new Prospect();
try(InputStream is = (InputStream)((ResponseImpl)value).getEntity()) {
if(is!=null){
String s = org.apache.commons.io.IOUtils.toString(is);
if(s!=null && s.length()>0){
ObjectMapper mapper = new ObjectMapper();
prospect = mapper.readValue(s, Prospect.class);
}
is.close();
}
} catch (IOException e) {
System.out.println("Exception occured"+e.getMessage());
}
return type.cast(prospect);
}
}
return (T) Void.TYPE;
}
我的路由器被修改为:
from("jetty://http://localhost:8182/route/prospect?bindingStyle=SimpleConsumer")
//The Raw type to String conversion is done here. Refer the class for details
.process(new ResponseToStringProcessor())
.unmarshal("jsonDataformat")
.to("cxfrs://http://localhost:8181/cxf/prospect/consume")
.convertBodyTo(Prospect.class)
.to("bean:prospectService?method=doSomething")
.marshal("jsonDataformat");
如果不确认这是否是唯一的方法,我无法将此标记为解决方案。我的解决方案是在我在 camel-cxf 中发现一个旧的 JIRA 问题后实施的
https://issues.apache.org/jira/browse/CAMEL-3208
为此,我不得不编写一个 FallBackConvertor。
【问题讨论】:
-
我转换以 InputStream 为主体的 ResponseImpl 的几种方法失败了。我尝试了以下操作: 1)在处理方法中,提取 ResponseImpl 并尝试使用 IOUtils.toString() 将 InputStream 转换为 String .. - 抛出 IOException 失败 - 流已关闭 2)尝试调用一个接受 ResponseImpl 作为主体的 bean 组件和尝试与上面相同的转换 - 失败 3) 尝试为此转换编写骆驼的 TypeConvertor - 失败并出现相同的异常 - 流已关闭 以上所有方法都失败了,我不知道为什么要关闭流。
-
唯一对我有帮助的解决方法是 - 编写一个 Fallbacktype 转换器,该转换器执行相同的操作,即使用 jackson 的 ObjectMapper 将 ResponseImpl 转换为 InputStream 以及从 InputStream 转换为 String 以及从 String(Json) 转换为我的 BO。虽然这可行,但我不能接受这是一个有效的解决方案,因为我必须对从 cxfrs:uri 返回的简单 JSON 进行大量转换
标签: apache-camel cxf cxfrs