我有一些需要使用REST前端代理的SOAP Web服务。 REST API操作会将1-1映射到它们的SOAP等效项。
例如,对于在http://soapservices/ServiceA上的SOAP Web服务调用操作operation1
,其REST代理将为POST http://restservices/ServiceA/operation1,并具有与参数和返回值完全相同的数据绑定对象。
我将使用Camel将REST调用动态路由到其相应的SOAP端点,并可能执行一些常见的预处理或后期处理。
理想情况下,我想创建一个项目,在其中添加代理的WSDL,使用Maven的cxf-codegen-plugin
生成JAX-WS服务端点接口,并使用服务为服务动态地实例化CxfEndpoint
bean将枚举它们的属性文件。
对于JAX-RS部分,我发现重用生成的SEI非常方便,并且使用了SpringJAXRSServerFactoryBean
,它在应用程序启动时以编程方式设置了resourceClasses
,从中读取了枚举的服务相同的属性文件。
我有一个工作草案项目,但是必须手动更改生成的SEI来添加JAX-RS注释(@Path
,@Consumes
,@Produces
,@Post
等等)看起来很糟糕。
例如:
为此,N通常会生成这样的SEI:
@WebService(...)
@XmlSeeAlso(...)
@SoapBinding(...)
public interface ServiceAPortType {
@WebMethod(operationName="operation1")
@WebResult(...)
public ResponseObject operation1(@WebParam(...) ParamObject param);
}
我有一个yml文件:
services:
- service: ServiceA
config:
address: http://soapservices/ServiceA
serviceClass: ServiceAPortType.class
- service: ServiceB
config:
address: http://soapservices/ServiceB
serviceClass: ServiceBPortType.class
然后为客户端注册CxfEndpoint
:
@PostConstruct
public void registerSOAPClients(){
Map<String, Object> values = (Map<String, Object>) ws.getConfig(); // "ws" injected with @ConfigurationProperties
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(CxfEndpoint.class);
for (Map.Entry<String, Object> val : values.entrySet()) {
bdb.addPropertyValue(val.getKey(), val.getValue());
}
beanFactory.registerBeanDefinition(ws.getService(), bdb.getBeanDefinition());
}
JAX-RS部分是需要手动调整生成的SEI的部分,以添加@Path
,@Consumes
和各种注释以使SpringJAXRSServerFactoryBean
使用它们:
@Bean
public SpringJAXRSServerFactoryBean jaxRSfactoryBean() throws ClassNotFoundException {
SpringJAXRSServerFactoryBean bean = new SpringJAXRSServerFactoryBean();
bean.setAddress("/restservices");
bean.setResourceClasses(jaxRSAnnotatedSEIs); // jaxRSAnnotatedSEIs injected from yml serviceClass
return bean;
}
骆驼路线非常简单,遵循以下原则:
from("cxfrs:bean:jaxRSfactoryBean?providers=#jsonProvider")
.setHeader("serviceName", getServiceFromURI())
.setHeader("operationName", getOperationFromURI())
.toD("cxf:bean:${header.serviceName}Service?")
.transform().simple("${body.get(0)}")
.marshal().json(JsonLibrary.Jackson)
.end();
有什么办法可以自动添加这些批注,以使生成的源保持未经编辑,或者从SOAP WSDL或现有的JAX-WS SEI生成JAX-RS SEI?还是有其他更清洁的方法?我愿意接受其他方法,只要它们不涉及对生成的源进行手动修改并且仅依赖属性文件来枚举和配置服务即可。