我正在尝试为现有的SOAP服务构建一个mock。该服务有几个方法,既使用byte[]
形式的MTOM上载,又使用SoapHeaders提交其余信息。此外,该服务使用SoapActions来标识端点操作。我无法修改服务。我使用wsdl2java生成API对象
终点:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
import org.springframework.ws.soap.server.endpoint.annotation.SoapHeader;
@Endpoint
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class RenderJobEndpoint {
...
@SoapAction(value = NAMESPACE_URI + "CreateJob")
@ResponsePayload
public RenderJobInfo createJob(@RequestPayload RenderJobCreateJobData parameters,
@SoapHeader("{http://www.someservice.com/serviceName/}"}fileName") SoapHeaderElement fileNameElement) {
String fileName = fileNameElement.getText();
return service.doStuff(parameters, fileName);
}
...
}
XSD文件
<xs:element name="RenderJobCreateJobData">
<xs:complexType>
<xs:sequence>
<xs:element name="data" type="q3:StreamBody"
xmlns:q3="http://schemas.microsoft.com/Message" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="fileHash" nillable="true" type="xs:base64Binary" />
<xs:element name="fileName" nillable="true" type="xs:string" />
<xs:element name="fileOptions" nillable="true" type="xs:string" />
fileHash、fileName和fileOptions是标头。在我的Mock中,我不需要所有的。我尝试将它们全部添加到方法的签名中,但没有任何更改。
WebServiceConfig
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurationSupport {
// ******************************** MTOM ***********************************************
@Bean
@Override
public DefaultMethodEndpointAdapter defaultMethodEndpointAdapter() {
List<MethodArgumentResolver> argumentResolvers = new ArrayList<>();
argumentResolvers.add(soapMethodArgumentResolver());
argumentResolvers.add(methodProcessor());
List<MethodReturnValueHandler> returnValueHandlers = new ArrayList<>();
returnValueHandlers.add(methodProcessor());
DefaultMethodEndpointAdapter adapter = new DefaultMethodEndpointAdapter();
adapter.setMethodArgumentResolvers(argumentResolvers);
adapter.setMethodReturnValueHandlers(returnValueHandlers);
return adapter;
}
@Bean
public SoapMethodArgumentResolver soapMethodArgumentResolver() {
return new SoapMethodArgumentResolver();
}
@Bean
public MarshallingPayloadMethodProcessor methodProcessor() {
return new MarshallingPayloadMethodProcessor(marshaller());
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath("com.mockservice.service.apidata");
jaxb2Marshaller.setMtomEnabled(true);
jaxb2Marshaller.setProcessExternalEntities(true);
return jaxb2Marshaller;
}
// ******************************** MTOM END ***********************************************
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean<>(servlet, "/ws/*");
}
@Bean(name = "RenderEngine")
public Wsdl11Definition wsdl11Definition() {
SimpleWsdl11Definition simpleWsdl11Definition = new SimpleWsdl11Definition();
simpleWsdl11Definition.setWsdl(new ClassPathResource("someFile.wsdl"));
return simpleWsdl11Definition;
}
@Bean
public CommonsXsdSchemaCollection xsdSchemaCollection() {
return new CommonsXsdSchemaCollection(
new ClassPathResource("someFile.xsd"));
}
@Override
public void addInterceptors(final List<EndpointInterceptor> interceptors) {
interceptors.add(new MockEndpointInterceptor());
}
}
我遵循了官方的Spring文档以允许MTOM处理,并重写了DefaultMethodEndpointAdapter。我通过了一个启用了MTOM的Marshaller。我读到过,为了允许SoapHeaders,还应该使用SoapMethodArgumentResolver,所以我做到了。
我的终结点不能同时使用MTOM和SoapHeader。当我从端点方法中删除SoapHeaders时,端点可以工作,有效负载是正确的,但标头被忽略。当我不重写DefaultMethodEndpointAdapterSoapHeaders时,但MTOM负载为0字节。
当我保持代码原样时,会发生以下情况:
- SoapMessageDispatcher|端点映射。。。将请求映射到端点。。。(查找终结点(
- SoapMessageDispatcher|正在测试端点适配器(失败(
- throws java.lang.IollegalStateException:端点没有适配器
有关于如何解决它的线索吗?
版本
- spring-boot-starter web服务:2.2.4.RELEASE
我通过添加另一个方法参数解析程序解决了同样的问题。这是的工作解决方案
@Bean
DefaultMethodEndpointAdapter defaultMethodEndpointAdapter(MarshallingPayloadMethodProcessor methodProcessor) {
DefaultMethodEndpointAdapter adapter = new DefaultMethodEndpointAdapter();
List<MethodArgumentResolver> argumentResolvers = new ArrayList<>();
argumentResolvers.add(soapHeaderElementMethodArgumentResolver());
argumentResolvers.add(soapMethodArgumentResolver());
argumentResolvers.add(methodProcessor);
adapter.setMethodArgumentResolvers(argumentResolvers);
adapter.setMethodReturnValueHandlers(Collections.singletonList(methodProcessor));
return adapter;
}