将生成的 REST 服务接口实现绑定到 servlet

Bind generated REST service interface implementation to servlet

我有一个 wadl 文件,我从中使用 wadl2java 工具为 REST 服务生成对象和接口。我有这些接口的实现,到目前为止一切都很好。我还在 web.xml 中配置了 servlet,但我无法让它工作。现在我的网站 xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>com.foo.ws.RestServiceImpl</param-value>               
        </init-param>    
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

生成的rest界面如下所示:

package com.foo.schemas;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.foo.schemas.BarRequest;
import com.foo.schemas.BarResponse;
import com.foo.schemas.FooRequest;
import com.foo.schemas.FooResponse;

@Path("services")
public interface RestService {

    @POST
    @Consumes("application/xml")
    @Produces("application/xml")
    BarResponse getBar(BarRequest barRequest);

    @POST
    @Consumes("application/xml")
    @Produces("application/xml")
    FooResponse getFoo(FooRequest fooRequest);
}

它的实现:

package com.foo.ws;

import org.glassfish.jersey.server.ResourceConfig;
import com.foo.RestService;
import com.foo.schemas.BarRequest;
import com.foo.schemas.BarResponse;
import com.foo.schemas.FooRequest;
import com.foo.schemas.FooResponse;

public class RestServiceImpl extends ResourceConfig implements RestService {
    public RestServiceImpl () {
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(RestServiceImpl.class).to(RestService.class);
            }
        });
    }

    @Override
    BarResponse getBar(BarRequest barRequest) {
        // Implementation omitted...
    }

    @Override
    FooResponse getFoo(FooRequest FooRequest) {
        // Implementation omitted...
    }
}

我认为这看起来不错,但是当我启动 Web 服务时,我得到以下 HTTP ERROR 503:

Problem accessing /my-web-service/. Reason:

org.glassfish.jersey.server.model.ModelValidationException: Validation of    
the application resource model has failed during application initialization.
[[FATAL] A resource model has ambiguous (sub-)resource method for HTTP 
method POST and input mime-types as defined by"@Consumes" and "@Produces" 
annotations at Java methods public com.foo.schemas.BarResponse 
com.foo.ws.RestServiceImpl.getBar(com.foo.schemas.BarRequest) and public 
com.foo.schemas.FooResponse 
com.foo.ws.RestServiceImpl.getFoo(com.foo.schemas.FooRequest) at matching 
regular expression /services. These two methods produces and consumes 
exactly the same mime-types and therefore their invocation as a resource 
methods will always fail.; 
source='org.glassfish.jersey.server.model.RuntimeResource@5690c2a8'

看起来接口和实现之间的绑定是正确的,但我不太明白为什么会出现这个错误?是的,@Consumes@Produces 注释使用相同的 MIME-types 定义方法,但这是 wadl2java 生成接口的方式?我不知道如何解决这个问题,servlet 或 wadl2java 工具是否有任何配置错误?我不知道,任何帮助都非常感谢,因为我坚持这个。

编辑 - 添加了 wadl 文件

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns:foo="http://schemas.foo.com" 
         xsi:schemaLocation="http://wadl.dev.java.net/2009/02    http://www.w3.org/Submission/wadl/wadl.xsd" 
         xmlns="http://wadl.dev.java.net/2009/02">
<doc xml:lang="en">This wadl describes....</doc>
<grammars>
    <include href="foo.xsd"/>
</grammars>
<resources base="/foo">
    <resource path="services">
        <method id="getBar" name="POST">
            <doc xml:lang="en">Get all bars.</doc>
            <request>
                <representation mediaType="application/xml">
                    <param required="true" style="plain" id="barRequest" name="barRequest" type="foo:BarRequest"/>
                </representation>
            </request>
            <response status="200">
                <representation mediaType="application/xml">
                    <param required="true" style="plain" id="barResponse" name="barResponse" type="foo:BarResponse"/>
                </representation>
            </response>
        </method>
        <method id="getFoo" name="POST">
            <doc xml:lang="en">Get all foos.</doc>
            <request>
                <representation mediaType="application/xml">
                    <param required="true" style="plain" id="fooRequest" name="fooRequest" type="foo:FooRequest"/>
                </representation>
            </request>
            <response status="200">
                <representation mediaType="application/xml">
                    <param required="true" style="plain" id="fooResponse" name="fooResponse" type="foo:FooResponse"/>
                </representation>
            </response>
        </method>
    </resource>
</resources>

问题是w.r.t如何公开资源。

  1. 公开了 2 个 POST 方法,都在监听路径“/services”。
  2. 这两种方法使用和生产相同的 MimeType

问题 - 如果此资源被命中。然后 Jersey 将无法理解要调用哪个 API 以获得结果。 是 getBar() 还是 getFoo()

现在,更改取决于预期是什么(根据要求,需要调用 API 以及何时调用)。 您必须相应地修改 WADL 以确保每个资源侦听唯一的 path/consume/produce 类型。

@Path("services")
public interface RestService {

    @POST
    @Consumes("application/xml")
    @Produces("application/xml")
    BarResponse getBar(BarRequest barRequest);

    @POST
    @Consumes("application/xml")
    @Produces("application/xml")
    FooResponse getFoo(FooRequest fooRequest);
}