简体   繁体   English

当请求元素不以“请求”结尾时,spring-ws 生成的 wsdl 无效

[英]Invalid wsdl generated by spring-ws when the request element doesn't end with 'Request'

I must prepare a webservice to accept anan already defined wsdl structure.我必须准备一个 web 服务来接受一个已经定义的 wsdl 结构。 I followed the tutorial found here , with source code for the test project downloadable here .我按照此处找到的教程进行操作,其中包含可在此处下载的测试项目的源代码。

For xsd like this:对于这样的 xsd:

<xs:element name="getCountryRequest">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Wsdl operation for request returned by application is OK, looks like this:应用程序返回的请求的wsdl操作是OK的,看起来像这样:

<wsdl:binding name="CountriesPortSoap11" type="tns:CountriesPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getCountry">
        <soap:operation soapAction=""/>
        <wsdl:input name="getCountryRequest">
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output name="getCountryResponse">
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

But when I change the xsd to (no 'Request' in element name):但是当我将 xsd 更改为(元素名称中没有“请求”)时:

<xs:element name="getCountry">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

the wsdl is invalid, and has no <input> specified: wsdl 无效,并且没有指定<input>

<wsdl:binding name="CountriesPortSoap11" type="tns:CountriesPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getCountry">
        <soap:operation soapAction=""/>
        <wsdl:output name="getCountryResponse">
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

How can I fix that?我该如何解决? How can I make a Request -less element appear properly as soap operation input in wsdl?如何使无Request元素正确显示为 wsdl 中的 soap 操作输入?

According to official Spring WS documentation , the Request/Response suffix are the default ones used to automatically determine request/response and as such generate the expected WSDL.根据Spring WS 官方文档,Request/Response 后缀是用于自动确定请求/响应并因此生成预期 WSDL 的默认后缀。

The DefaultWsdl11Definition which builds a WSDL from a XSD schema.从 XSD 架构构建 WSDL 的 DefaultWsdl11Definition。 This definition iterates over all element elements found in the schema, and creates a message for all elements.此定义遍历在模式中找到的所有元素元素,并为所有元素创建一条消息。 Next, it creates WSDL operation for all messages that end with the defined request or response suffix.接下来,它为所有以定义的请求或响应后缀结尾的消息创建 WSDL 操作。 The default request suffix is Request;默认请求后缀为Request; the default response suffix is Response, though these can be changed by setting the requestSuffix and responseSuffix properties, respectively.默认响应后缀是 Response,尽管可以分别通过设置 requestSuffix 和 responseSuffix 属性来更改这些后缀。

You can hence, in the mentioned example code, change the suffix in the WebServiceConfig configuration class, defaultWsdl11Definition method, adding the following method invocation:因此,您可以在上述示例代码中,更改WebServiceConfig配置类中的后缀defaultWsdl11Definition方法,添加以下方法调用:

wsdl11Definition.setRequestSuffix("your-new-prefix-here");

You can, for instance, set it to Req instead of Request , the build will then automatically generate a new GetCountryReq class, code of ApplicationTests and CountryEndpoint would then need to be manually adapted, removing compilation errors (as they would still point to the previously existing GetCountryRequest class) but also making sure to change the localPart = "getCountryReq" attribute of the @PayloadRoot annotation in the CountryEndPoint class.例如,您可以将其设置为Req而不是Request ,然后构建将自动生成一个新的GetCountryReq类,然后需要手动调整ApplicationTestsCountryEndpoint的代码,消除编译错误(因为它们仍然指向以前的现有的GetCountryRequest类),但还要确保更改CountryEndPoint类中@PayloadRoot注释的localPart = "getCountryReq"属性。

I tried it and build went fine and WSDL was updated accordingly.我试过了,构建很顺利,WSDL 也相应地更新了。

That's about changing the default suffix to another suffix.那是关于将默认后缀更改为另一个后缀。 But what about changing it to an empty suffix?但是如何将其更改为空后缀呢?

wsdl11Definition.setRequestSuffix("");

Exception: suffix must not be empty.例外:后缀不能为空。 Spring does not support it.春天不支持它。 According to this thread :根据这个线程

Basically, the problem is this:基本上,问题是这样的:
We have to differentiate which schema elements are wsdl messages, and which aren't.我们必须区分哪些模式元素是 wsdl 消息,哪些不是。
Of all wsdl messages, we have to figure out which are input (request) messages.在所有 wsdl 消息中,我们必须找出哪些是输入(请求)消息。
Of all wsdl messages, we have to figure out which are output (response) messages.在所有 wsdl 消息中,我们必须找出哪些是输出(响应)消息。

The DefaultWsdl11Definition figures this out by suffixes. DefaultWsdl11Definition 通过后缀解决这个问题。 Or, more specifically, it delegates to a SuffixBasedMessagesProvider and SuffixBasedPortTypesProvider to do so.或者,更具体地说,它委托给 SuffixBasedMessagesProvider 和 SuffixBasedPortTypesProvider 来执行此操作。
So if you have some other preferred way of determining what makes an input/output message, you will have to write your own messagesprovider and or porttypesprovider.因此,如果您有一些其他首选方法来确定什么构成输入/输出消息,您将必须编写自己的消息提供程序和/或端口类型提供程序。

Simply put: there is no generic way for Spring-WS to determine what makes up a request and a response, rather than using suffixes.简单地说:Spring-WS 没有通用的方法来确定什么构成了请求和响应,而不是使用后缀。

Note: the poster of this message was Arjen Poutsma, author of the DefaultWsdl11Definition class (according to javadocs), the component which handles the automatic mapping based on these suffix conventions.注意:此消息的发布者是DefaultWsdl11Definition类(根据 javadocs)的作者 Arjen Poutsma,该组件处理基于这些后缀约定的自动映射。

But he leaves an open door: writing your own SuffixBasedMessagesProvider and SuffixBasedPortTypesProvider .但他敞开了大门:编写您自己的SuffixBasedMessagesProviderSuffixBasedPortTypesProvider However, he also left everything as private in the DefaultWsdl11Definition (where these providers are instantiated), hence you would also need to write (copy) your own WSDL11 definition mapper.但是,他还在DefaultWsdl11Definition (实例化这些提供程序的地方)中将所有内容都保留为私有,因此您还需要编写(复制)自己的 WSDL11 定义映射器。

Here is the process I followed then:这是我当时遵循的过程:

  • Create your own CustomSuffixBasedMessagesProvider, overriding the setRequestSuffix method and removing the check on empty suffix, in the isMessageElement method you would need to handle the new mapping创建您自己的 CustomSuffixBasedMessagesProvider,覆盖setRequestSuffix方法并删除对空后缀的检查,在isMessageElement方法中您需要处理新映射
  • Create your own CustomSuffixBasedPortTypesProvider, overriding the setRequestSuffix method and removing the check on empty suffix, in the getOperationName and isInputMessage methods you would need to handle the new mapping创建您自己的 CustomSuffixBasedPortTypesProvider,覆盖setRequestSuffix方法并删除对空后缀的检查,在您需要处理新映射的getOperationNameisInputMessage方法中
  • Create your own CustomWsdl11Definition as a copy of the existing DefaultWsdl11Definition and instantiating your own providers created above创建您自己的 CustomWsdl11Definition 作为现有 DefaultWsdl11Definition 的副本并实例化上面创建的您自己的提供程序
  • Change the WebServiceConfig class, defaultWsdl11Definition method, to use your own CustomWsdl11Definition in order to apply the whole customization.更改WebServiceConfigdefaultWsdl11Definition方法,以使用您自己的 CustomWsdl11Definition 以应用整个自定义。

However, empty suffix comes with a bit of challenge, since it would be fine for any element (that is, every element has an empty suffix).然而,空后缀会带来一些挑战,因为它适用于任何元素(也就是说,每个元素都有一个空后缀)。 That's why I mentioned the isMessageElement , isInputMessage and getOperationName handling: on growing WSDLs, you may easily end up on harcoding the mapping (for GetCountry request, GetCountryResponse is the response) or passing a properties/map (as suggested in the thread mentioned above), but again repeating most of your XSD again in your WebServiceConfig configuration class, making it hard to maintain, troubleshoot, share.这就是我提到isMessageElementisInputMessagegetOperationName处理的原因:在增长的 WSDL 中,您可能很容易最终对映射进行硬编码(对于 GetCountry 请求,GetCountryResponse 是响应)或传递属性/映射(如上述线程中所建议的) ,但在WebServiceConfig配置类中再次重复大部分 XSD,使其难以维护、故障排除和共享。

So, I would really suggest not to take this journey and either stick to the default suffix (if possible) or create a new one, but avoid empty suffix (they are not allowed by the library after all).所以,我真的建议不要走这条路,要么坚持默认后缀(如果可能),要么创建一个新后缀,但要避免空后缀(毕竟库不允许)。

But since I took the journey, here is the working solution:但自从我踏上旅程后,这里是可行的解决方案:

The MySuffixBasedMessagesProvider custom class (imports removed for brevity): MySuffixBasedMessagesProvider自定义类(为简洁起见删除了导入):

package hello;

public class MySuffixBasedMessagesProvider extends SuffixBasedMessagesProvider {

    protected String requestSuffix = DEFAULT_REQUEST_SUFFIX;

    public String getRequestSuffix() {
        return this.requestSuffix;
    }

    public void setRequestSuffix(String requestSuffix) {
        this.requestSuffix = requestSuffix;
    }

    @Override
    protected boolean isMessageElement(Element element) {
        if (isMessageElement0(element)) {
            String elementName = getElementName(element);
            Assert.hasText(elementName, "Element has no name");
            return elementName.endsWith(getResponseSuffix())
                    || (getRequestSuffix().isEmpty() ? true : elementName.endsWith(getRequestSuffix()))
                    || elementName.endsWith(getFaultSuffix());
        }
        return false;
    }

    protected boolean isMessageElement0(Element element) {
        return "element".equals(element.getLocalName())
                && "http://www.w3.org/2001/XMLSchema".equals(element.getNamespaceURI());
    }
}

The MySuffixBasedPortTypesProvider custom class (imports removed for brevity): MySuffixBasedPortTypesProvider自定义类(为简洁起见删除了导入):

package hello;

public class MySuffixBasedPortTypesProvider extends SuffixBasedPortTypesProvider {

    private String requestSuffix = DEFAULT_REQUEST_SUFFIX;

    public String getRequestSuffix() {
        return requestSuffix;
    }

    public void setRequestSuffix(String requestSuffix) {
        this.requestSuffix = requestSuffix;
    }

    @Override
    protected String getOperationName(Message message) {
        String messageName = getMessageName(message);
        String result = null;
        if (messageName != null) {
            if (messageName.endsWith(getResponseSuffix())) {
                result = messageName.substring(0, messageName.length() - getResponseSuffix().length());
            } else if (messageName.endsWith(getFaultSuffix())) {
                result = messageName.substring(0, messageName.length() - getFaultSuffix().length());
            } else if (messageName.endsWith(getRequestSuffix())) {
                result = messageName.substring(0, messageName.length() - getRequestSuffix().length());
            }
        }
        return result;
    }

    @Override
    protected boolean isInputMessage(Message message) {
        String messageName = getMessageName(message);

        return messageName != null && !messageName.endsWith(getResponseSuffix());
    }

    private String getMessageName(Message message) {
        return message.getQName().getLocalPart();
    }

}

The MyWsdl11Definition custom class (essentially a copy of the Default one, just instantiating the classes above, imports removed for brevity): MyWsdl11Definition自定义类(本质上是默认类的副本,只是实例化上面的类,为简洁起见删除了导入):

package hello;

public class MyWsdl11Definition implements Wsdl11Definition, InitializingBean {

    private final InliningXsdSchemaTypesProvider typesProvider = new InliningXsdSchemaTypesProvider();

    private final SuffixBasedMessagesProvider messagesProvider = new MySuffixBasedMessagesProvider();

    private final SuffixBasedPortTypesProvider portTypesProvider = new MySuffixBasedPortTypesProvider();

    private final SoapProvider soapProvider = new SoapProvider();

    private final ProviderBasedWsdl4jDefinition delegate = new ProviderBasedWsdl4jDefinition();

    private String serviceName;

    public MyWsdl11Definition() {
        delegate.setTypesProvider(typesProvider);
        delegate.setMessagesProvider(messagesProvider);
        delegate.setPortTypesProvider(portTypesProvider);
        delegate.setBindingsProvider(soapProvider);
        delegate.setServicesProvider(soapProvider);
    }

    public void setTargetNamespace(String targetNamespace) {
        delegate.setTargetNamespace(targetNamespace);
    }

    public void setSchema(XsdSchema schema) {
        typesProvider.setSchema(schema);
    }

    public void setSchemaCollection(XsdSchemaCollection schemaCollection) {
        typesProvider.setSchemaCollection(schemaCollection);
    }

    public void setPortTypeName(String portTypeName) {
        portTypesProvider.setPortTypeName(portTypeName);
    }

    public void setRequestSuffix(String requestSuffix) {
        portTypesProvider.setRequestSuffix(requestSuffix);
        messagesProvider.setRequestSuffix(requestSuffix);
    }

    public void setResponseSuffix(String responseSuffix) {
        portTypesProvider.setResponseSuffix(responseSuffix);
        messagesProvider.setResponseSuffix(responseSuffix);
    }

    public void setFaultSuffix(String faultSuffix) {
        portTypesProvider.setFaultSuffix(faultSuffix);
        messagesProvider.setFaultSuffix(faultSuffix);
    }

    public void setCreateSoap11Binding(boolean createSoap11Binding) {
        soapProvider.setCreateSoap11Binding(createSoap11Binding);
    }

    public void setCreateSoap12Binding(boolean createSoap12Binding) {
        soapProvider.setCreateSoap12Binding(createSoap12Binding);
    }

    public void setSoapActions(Properties soapActions) {
        soapProvider.setSoapActions(soapActions);
    }

    public void setTransportUri(String transportUri) {
        soapProvider.setTransportUri(transportUri);
    }

    public void setLocationUri(String locationUri) {
        soapProvider.setLocationUri(locationUri);
    }

    public void setServiceName(String serviceName) {
        soapProvider.setServiceName(serviceName);
        this.serviceName = serviceName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (!StringUtils.hasText(delegate.getTargetNamespace()) && typesProvider.getSchemaCollection() != null &&
                typesProvider.getSchemaCollection().getXsdSchemas().length > 0) {
            XsdSchema schema = typesProvider.getSchemaCollection().getXsdSchemas()[0];
            setTargetNamespace(schema.getTargetNamespace());
        }
        if (!StringUtils.hasText(serviceName) && StringUtils.hasText(portTypesProvider.getPortTypeName())) {
            soapProvider.setServiceName(portTypesProvider.getPortTypeName() + "Service");
        }
        delegate.afterPropertiesSet();
    }

    @Override
    public Source getSource() {
        return delegate.getSource();
    }

}

Furthermore, the defaultWsdl11Definition method of the WebServiceConfig class would change as following (to use the customization above):此外, WebServiceConfig类的defaultWsdl11Definition方法将更改如下(以使用上面的自定义):

@Bean(name = "countries")
public Wsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    MyWsdl11Definition wsdl11Definition = new MyWsdl11Definition();
    wsdl11Definition.setPortTypeName("CountriesPort");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setRequestSuffix("");
    wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
    wsdl11Definition.setSchema(countriesSchema);
    return wsdl11Definition;
}

Note the wsdl11Definition.setRequestSuffix("");注意wsdl11Definition.setRequestSuffix(""); which effectively sets the suffix at empty.这有效地将后缀设置为空。

After this customization, you can then change the XSD removing the Request suffix, the new GetCountry class would be generated, you would need to manually remove the previously existing GetCountryRequest and fix the compilation errors as mentioned above (test and endpoint class, just don't forget to update the @PayloadRoot annotation as well).自定义完成后,你可以更改XSD去掉Request后缀,会生成新的GetCountry类,你需要手动移除之前存在的GetCountryRequest并修复上面提到的编译错误(测试和端点类,不要'不要忘记更新 @PayloadRoot 注释)。

Build would then run fine.然后构建将运行良好。 Running the Application main, the generated WSDL would then contain as requested:运行Application main,生成的 WSDL 将按要求包含:

<wsdl:binding name="CountriesPortSoap11" type="tns:CountriesPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getCountry">
  <soap:operation soapAction=""/>
  <wsdl:input name="getCountry">
    <soap:body use="literal"/>
  </wsdl:input>
  <wsdl:output name="getCountryResponse">
    <soap:body use="literal"/>
  </wsdl:output>
</wsdl:operation>
</wsdl:binding>

Hope it helps.希望能帮助到你。 This is a real example of what convention over configuration greatly provides and what instead a small unforeseen change in a framework would then mean in terms of writing code and adding customization.这是一个真实的例子,说明了配置约定极大地提供了什么,而在编写代码和添加自定义方面,框架中的一个小的不可预见的变化将意味着什么。

Spring-WS automatic wsdl exposure feature is based on conventions described at http://docs.spring.io/spring-ws/site/reference/html/server.html#server-automatic-wsdl-exposure Spring-WS 自动 wsdl 公开功能基于http://docs.spring.io/spring-ws/site/reference/html/server.html#server-automatic-wsdl-exposure中描述的约定

The tutorial you use as a starting point is using annotations instead of namespace, but there should be a way to specify requestSuffix and responseSuffix properties mentioned in the documentation.您用作起点的教程使用注释而不是名称空间,但应该有一种方法来指定文档中提到的 requestSuffix 和 responseSuffix 属性。 However I am afraid that you can not keep them blank.但是,恐怕您不能将它们留空。

Alternatively you can expose manually written WSDL.或者,您可以公开手动编写的 WSDL。 I suggest to do that since you have wsdl given from the beginning.我建议这样做,因为您从一开始就给出了 wsdl。

There is simpler way.有更简单的方法。 In place of DefaultWsdl11Definition use ProviderBasedWsdl4jDefinition and set all default providers but one - in place of SuffixBasedPortTypesProvider use something like this:代替 DefaultWsdl11Definition 使用 ProviderBasedWsdl4jDefinition 并设置所有默认提供者,但一个 - 代替 SuffixBasedPortTypesProvider 使用这样的东西:

public class DelphiStylePortTypesProvider extends AbstractPortTypesProvider {

    @Override
    protected String getOperationName(Message msg) {
        if (isInputMessage(msg)) {
            return msg.getQName().getLocalPart();
        }
        if (isOutputMessage(msg)) {
            return msg.getQName().getLocalPart().replace("Response", "");
        }
        return "";
    }

    @Override
    protected boolean isInputMessage(Message msg) {
        return !msg.getQName().getLocalPart().endsWith("Response");
    }

    @Override
    protected boolean isOutputMessage(Message msg) {
        return msg.getQName().getLocalPart().endsWith("Response");
    }

    @Override
    protected boolean isFaultMessage(Message msg) {
        return false;
    }

}

In @EnableWs configuration class:@EnableWs配置类中:

@Bean(WSDL_SCHEMA_NAME)
public ProviderBasedWsdl4jDefinition providerBasedWsdl4jDefinition(XsdSchema xsdSchema) {
    var wsdl4jDefinition = new ProviderBasedWsdl4jDefinition();
    wsdl4jDefinition.setTargetNamespace(WSDL_TARGET_NAMESPACE);

    var suffixBasedPortTypesProvider = new CustomPortTypesProvider();
    suffixBasedPortTypesProvider.setPortTypeName(WSDL_PORT_TYPE_NAME);
    wsdl4jDefinition.setPortTypesProvider(suffixBasedPortTypesProvider);

    var inliningXsdSchemaTypesProvider = new InliningXsdSchemaTypesProvider();
    inliningXsdSchemaTypesProvider.setSchema(xsdSchema);
    wsdl4jDefinition.setTypesProvider(inliningXsdSchemaTypesProvider);

    wsdl4jDefinition.setMessagesProvider(new CustomMessagesProvider());

    var soapProvider = new SoapProvider();
    soapProvider.setLocationUri(WSDL_SCHEMA_URI);
    soapProvider.setServiceName(WSDL_SCHEMA_NAME);
    wsdl4jDefinition.setBindingsProvider(soapProvider);
    wsdl4jDefinition.setServicesProvider(soapProvider);

    return wsdl4jDefinition;
}

private static class CustomMessagesProvider extends SuffixBasedMessagesProvider {
    private static final String[] REQUEST_ELEMENTS =
            new String[] {"requestOne", "requestTwo"};

    @Override
    protected boolean isMessageElement(Element element) {
        if (super.isMessageElement(element)) {
            return true;
        } else {
            boolean isElement = "element".equals(element.getLocalName()) &&
                    "http://www.w3.org/2001/XMLSchema".equals(element.getNamespaceURI());
            String elementName = getElementName(element);
            return isElement && Arrays.asList(REQUEST_ELEMENTS).contains(elementName);
        }
    }
}

private static class CustomPortTypesProvider extends SuffixBasedPortTypesProvider {
    @Override
    protected String getOperationName(Message message) {
        String messageName = message.getQName().getLocalPart();
        if (isInputMessage(message)) {
            return messageName;
        } else if (isOutputMessage(message)) {
            return messageName.substring(0, messageName.length() - getResponseSuffix().length());
        } else if (isFaultMessage(message)) {
            return messageName.substring(0, messageName.length() - getFaultSuffix().length());
        }
        return null;
    }

    @Override
    protected boolean isInputMessage(Message message) {
        String messageName = message.getQName().getLocalPart();
        return !messageName.endsWith(getResponseSuffix()) && !messageName.endsWith(getFaultSuffix());
    }
}

I guess the best solution is to write a WSDL file which is you need.我想最好的解决方案是编写一个您需要的 WSDL 文件。 In my viewpoint creation of custom WSDL from XSD file with a request name and response name other than Spring Convention is unroutable.在我看来,使用除 Spring Convention 以外的请求名称和响应名称从 XSD 文件创建自定义 WSDL 是不可路由的。 So it is better to create WSDL and import it to the project and then generate your class from it.所以最好创建 WSDL 并将其导入项目,然后从中生成您的类。

I had the same error.我有同样的错误。 My setup was as follows:我的设置如下:

Generation of classes from an existing XSD file using the mavenjaxb2-maven-plugin使用 mavenjaxb2-maven-plugin从现有 XSD 文件生成类

<!-- SOAP -->
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.5.0</version>
    <executions>
        <execution>
            <id>xjc</id>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- The package of your generated sources -->
        <packageName>com.company</packageName>
        <addGeneratedAnnotation>true</addGeneratedAnnotation>
        <quiet>true</quiet>
        <sources>
            <source>${project.basedir}/src/main/resources/file.xsd</source>
        </sources>
    </configuration>
</plugin>

The handler method:处理程序方法:

@PayloadRoot(namespace = "URI", localPart = "LOCAL_PART")
@ResponsePayload
public JAXBElement<StatusResponse> retrieveNextStatesRequest(@RequestPayload Request request) {
    // Logic
    return new Response();
}

Thejaxb2-maven-plugin however has no possibility to add a XmlRoot annotation.然而,jaxb2-maven-plugin不可能添加XmlRoot注释。 However it provides an ObjectFactory to generate instances wrapped in JAXBElement instances.但是,它提供了一个 ObjectFactory 来生成包装在JAXBElement实例中的实例。

So when changes the method accordingly the SOAP requests now work as expected:因此,当相应地更改方法时,SOAP 请求现在可以按预期工作:

@PayloadRoot(namespace = "URI", localPart = "LOCAL_PART")
@ResponsePayload
public Response retrieveNextStatesRequest(@RequestPayload Request request) {
    // Logic
    return new ObjectFactory.createResponse(new Response());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM