Сервер Spring-WS SOAP с существующим WSDL не находит конечную точку - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь разработать быстрый SOAP сервер для использования во время тестирования с использованием Spring-Boot и Spring-WS. Сначала это контракт, так как у меня есть существующие файлы WSDL и XSD, и мои классы java генерируются во время сборки из них. Однако, когда я отправляю запрос через curl или SOAPUI, я получаю следующую ошибку:

$ curl --header "content-type: text/xml" -d @request.xml http://localhost:8080/ws

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode>SOAP-ENV:Server</faultcode>
      <faultstring xml:lang="en">No adapter for endpoint [public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation com.meanwhileinhell.mock.soap.MockVolumeChargingEndpoint.getAmount(java.lang.String,long,java.util.List&lt;org.csapi.schema.parlayx.payment.v3_0.Property&gt;) throws org.csapi.wsdl.parlayx.common.v3_0.faults.ServiceException,org.csapi.wsdl.parlayx.common.v3_0.faults.PolicyException]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?</faultstring>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

(Основные моменты: No adapter for endpoint [...] Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?

Ответ на этот вопрос - да моя конечная точка помечена @Endpoint. Полная настройка ниже:

build.gradle

plugins {
    id 'org.springframework.boot'
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-log4j2'
    }
}

version = '0.0.1-SNAPSHOT'

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web-services")
    compile("wsdl4j:wsdl4j:1.6.1")
    compile("org.glassfish.jaxb:jaxb-xjc:2.2.11")
    compile('javax.xml.soap:javax.xml.soap-api:1.4.0')
    compile('com.sun.xml.messaging.saaj:saaj-impl:1.5.1')
    compile project(':meanwhile-in-hell-volume-charging-v3-1-wsdl')

    testCompile("org.springframework.boot:spring-boot-starter-test")
}

MockSoapConfig. java

package com.meanwhileinhell.mock.soap.config;

import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;

@EnableWs
@Configuration
public class MockSoapConfig extends WsConfigurerAdapter {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(final ApplicationContext applicationContext) {
        MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
        messageDispatcherServlet.setApplicationContext(applicationContext);
        messageDispatcherServlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(messageDispatcherServlet, "/ws/*");
    }
}

MockVolumeChargingEndpoint. java

package com.meanwhileinhell.mock.soap;

import java.util.List;

import org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation;
import org.csapi.schema.parlayx.bpxg.common.v3_1.ObjectFactory;
import org.csapi.schema.parlayx.payment.v3_0.Property;
import org.csapi.wsdl.parlayx.common.v3_0.faults.PolicyException;
import org.csapi.wsdl.parlayx.common.v3_0.faults.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import generated.org.csapi.wsdl.parlayx.bpxg.payment.volume_charging.v3_1._interface.VolumeCharging;

@Endpoint
public class MockVolumeChargingEndpoint implements VolumeCharging {
    private static final Logger logger = LoggerFactory.getLogger(MockVolumeChargingEndpoint.class);

    private static final String NAMESPACE = "http://www.csapi.org/wsdl/parlayx/bpxg/payment/volume_charging/v3_1/service";

    @Autowired
    public MockVolumeChargingEndpoint() {
    }

    @Override
    @PayloadRoot(namespace = NAMESPACE, localPart = "getAmount")
    @ResponsePayload
    public ChargingInformation getAmount(final String endUserIdentifier,
                                         final long volume,
                                         final List<Property> parameters) throws
                                                                          ServiceException,
                                                                          PolicyException {

        logger.debug("GetAmount for endUserIdentifier=[{}], volume=[{}], properties=[{}]",
                     endUserIdentifier,
                     volume,
                     parameters);

        ObjectFactory objectFactory = new ObjectFactory();
        return objectFactory.createChargingInformation();
    }
}

Это сгенерированный интерфейс, который я реализую: VolumeCharging. java

package generated.org.csapi.wsdl.parlayx.bpxg.payment.volume_charging.v3_1._interface;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by Apache CXF 3.3.2
 * 2020-01-27T09:24:18.615Z
 * Generated source version: 3.3.2
 *
 */
@WebService(targetNamespace = "http://www.csapi.org/wsdl/parlayx/bpxg/payment/volume_charging/v3_1/interface", name = "VolumeCharging")
@XmlSeeAlso({org.csapi.schema.parlayx.payment.volume_charging.v3_1.local.ObjectFactory.class, org.csapi.schema.parlayx.bpxg.payment.volume_charging.v3_1.local.ObjectFactory.class, org.csapi.schema.parlayx.bpxg.common.v3_1.ObjectFactory.class, org.csapi.schema.parlayx.common.v3_1.ObjectFactory.class, org.csapi.schema.parlayx.payment.v3_0.ObjectFactory.class})
public interface VolumeCharging {

    @WebMethod
    @RequestWrapper(localName = "getAmount", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local", className = "org.csapi.schema.parlayx.bpxg.payment.volume_charging.v3_1.local.GetAmount")
    @ResponseWrapper(localName = "getAmountResponse", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local", className = "org.csapi.schema.parlayx.bpxg.payment.volume_charging.v3_1.local.GetAmountResponse")
    @WebResult(name = "result", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local")
    public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation getAmount(

        @WebParam(name = "endUserIdentifier", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local")
        java.lang.String endUserIdentifier,
        @WebParam(name = "volume", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local")
        long volume,
        @WebParam(name = "parameters", targetNamespace = "http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local")
        java.util.List<org.csapi.schema.parlayx.payment.v3_0.Property> parameters
    ) throws org.csapi.wsdl.parlayx.common.v3_0.faults.ServiceException, org.csapi.wsdl.parlayx.common.v3_0.faults.PolicyException;
}

Это пакет SOAP, который я отправляю в своем запросе curl / SOAPUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:mock="http://www.csapi.org/wsdl/parlayx/bpxg/payment/volume_charging/v3_1/service">
    <soapenv:Header/>
    <soapenv:Body>
        <mock:getAmount>
            <mock:endUserIdentifier>TestUserId</mock:endUserIdentifier>
            <mock:volume>123123</mock:volume>
            <mock:parameters>
                <name>ParameterName</name>
                <value>ParameterValue</value>
            </mock:parameters>
        </mock:getAmount>
    </soapenv:Body>
</soapenv:Envelope>

Я просто вижу, почему он не достигает моей конечной точки. Если я изменяю имя getAmount в моем пакете запроса к чему-то, что определенно не реализовано, я получаю сообщение:

No endpoint mapping found for [SaajSoapMessage {http://www.csapi.org/wsdl/parlayx/bpxg/payment/volume_charging/v3_1/service}getTheWeather]

Включая ведение журнала DEBUG для Spring WebServices, я вижу, что мои конечные точки сопоставляются с моей конечной точкой Метод в порядке:

2020-01-28 16:36:35.881 DEBUG 72581 --- [           main] yloadRootAnnotationMethodEndpointMapping : Mapped [{http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local}getAmount] onto endpoint [public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation com.meanwhileinhell.mock.soap.MockVolumeChargingEndpoint.getAmount(java.lang.String,long,java.util.List<org.csapi.schema.parlayx.payment.v3_0.Property>)]


2020-01-28 16:36:58.316 DEBUG 72581 --- [nio-8080-exec-1] .WebServiceMessageReceiverHandlerAdapter : Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection@27ef75ac] at [http://localhost:8080/ws]
2020-01-28 16:36:58.481 DEBUG 72581 --- [nio-8080-exec-1] o.s.ws.server.MessageTracing.received    : Received request [SaajSoapMessage {http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local}getAmount]
2020-01-28 16:36:58.541 DEBUG 72581 --- [nio-8080-exec-1] yloadRootAnnotationMethodEndpointMapping : Looking up endpoint for [{http://www.csapi.org/schema/parlayx/bpxg/payment/volume_charging/v3_1/local}getAmount]
2020-01-28 16:36:58.541 DEBUG 72581 --- [nio-8080-exec-1] o.s.w.soap.server.SoapMessageDispatcher  : Endpoint mapping [org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping@623a8092] maps request to endpoint [public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation com.meanwhileinhell.mock.soap.MockVolumeChargingEndpoint.getAmount(java.lang.String,long,java.util.List<org.csapi.schema.parlayx.payment.v3_0.Property>)]
2020-01-28 16:36:58.544 DEBUG 72581 --- [nio-8080-exec-1] o.s.w.soap.server.SoapMessageDispatcher  : Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter@3571b748]
2020-01-28 16:36:58.547 DEBUG 72581 --- [nio-8080-exec-1] s.e.SoapFaultAnnotationExceptionResolver : Resolving exception from endpoint [public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation com.meanwhileinhell.mock.soap.MockVolumeChargingEndpoint.getAmount(java.lang.String,long,java.util.List<org.csapi.schema.parlayx.payment.v3_0.Property>)]: java.lang.IllegalStateException: No adapter for endpoint [public org.csapi.schema.parlayx.bpxg.common.v3_1.ChargingInformation com.meanwhileinhell.mock.soap.MockVolumeChargingEndpoint.getAmount(java.lang.String,long,java.util.List<org.csapi.schema.parlayx.payment.v3_0.Property>)]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?

Так что может показаться, что моя конечная точка отображается нормально, б но есть проблема с адаптером конечной точки?

1 Ответ

0 голосов
/ 30 января 2020

Необходимо обернуть мои полезные данные в тип JAXBElement для Spring, чтобы адаптеры обработчика сообщений поддерживали конечную точку.

@PayloadRoot(namespace = NAMESPACE, localPart = "getAmount")
@ResponsePayload
public JAXBElement<GetAmountResponse> getAmount(@RequestPayload JAXBElement<GetAmount> request) {
    ...
}
...