【问题标题】:Spring-WS Server with MTOM and SoapHeaders带有 MTOM 和 SoapHeaders 的 Spring-WS 服务器
【发布时间】:2020-08-14 12:37:31
【问题描述】:

我正在尝试为现有的 SOAP 服务构建一个模拟。该服务有几种方法,既使用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" />

fileHashfileNamefileOptions 是标题。在我的 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。我read 表示,为了允许 SoapHeaders 也应该使用 SoapMethodArgumentResolver,所以我这样做了。

我的端点不适用于 MTOM 和 SoapHeaders。当我从端点方法中删除 SoapHeaders 时,端点工作,有效负载正确但标题被忽略。当我不覆盖 DefaultMethodEndpointAdapter SoapHeaders 工作时,但 MTOM 有效负载为 0 字节。

当我保持原样时,会发生以下情况:

  • SoapMessageDispatcher |端点映射...将请求映射到端点...(找到端点)
  • SoapMessageDispatcher |测试端点适配器(失败)
  • 抛出 java.lang.IllegalStateException: No adapter for endpoint

关于如何解决它的任何线索?

版本

  • spring-boot-starter-web-services: 2.2.4.RELEASE

【问题讨论】:

    标签: java spring-boot soap spring-ws mtom


    【解决方案1】:

    我通过添加另一个方法参数解析器解决了同样的问题。这是有效的解决方案

    @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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-04
      • 2016-09-28
      • 1970-01-01
      • 2020-02-18
      • 2013-01-12
      • 1970-01-01
      • 2012-02-29
      • 2014-05-26
      相关资源
      最近更新 更多