我编写了一个 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");
}
前景服务:
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);
}
经过多次失败尝试(在评论中提到),最终的解决方案是编写一个 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。