Jakarta ee 以编程方式获取JAX-WSWebService实现的Servlet实例?

Jakarta ee 以编程方式获取JAX-WSWebService实现的Servlet实例?,jakarta-ee,jax-ws,servlet-3.0,jax-ws-customization,Jakarta Ee,Jax Ws,Servlet 3.0,Jax Ws Customization,我正在使用自顶向下的方法处理web服务,使用JAX-WS的wsimport从WSDL生成服务类型和接口。这提供了一个端口类型接口,如下所示,由我实现 /** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.2.4-b01 * Generated source version: 2.2 */ @WebService(name = "ExamplePortType", targetNamespace = "http://e

我正在使用自顶向下的方法处理web服务,使用JAX-WS的wsimport从WSDL生成服务类型和接口。这提供了一个端口类型接口,如下所示,由我实现

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2.4-b01
 * Generated source version: 2.2
 */
@WebService(name = "ExamplePortType", targetNamespace = "http://example.com")
public interface ExamplePortType {

    /**
     * @param example
     * @return java.lang.String
     * @throws ExampleException
     */
    @WebMethod
    @WebResult(name = "exampleResponse", targetNamespace = "http://example.com")
    @RequestWrapper(localName = "sendExample", targetNamespace = "http://example.com", className = "com.example.SendExample")
    @ResponseWrapper(localName = "sendExampleResponse", targetNamespace = "http://example.com", className = "com.example.SendExampleResponse")
    public String sendExample(
        @WebParam(name = "example", targetNamespace = "http://example.com")
        ExampleRequest example)
        throws ExampleException
    ;
}
将此服务添加到应用程序服务器(在我的例子中是Tomcat)的通常方法似乎是将实现类作为servlet添加到web.xml中,并将WSServletContextListener作为侦听器添加。非常粗略地说,在初始化上下文时,侦听器似乎构造了ServletAdapters,它包装了实现bean,并将它们添加到一个由瘦WSServlet调用的WSServletDelegate中。然后,对实现的请求由WSServlet处理,并由委托根据您设置的URL模式传递给bean

有没有一种方法可以通过编程实现上述功能?我想要一个方法,它接受上述接口的一个实例,并向我返回一个Servlet的实例,如果在ServletContext中注册,它将把适当的请求路由到封装的实现。比如:

Servlet exampleServlet = new ServletAdapter().wrap(new ExamplePortTypeImpl());
一个要求是我不能依赖静态配置文件(如web.xml或sunjaxws.xml)。JAX-WS或相关库(如Axis2等)是否提供这种功能

如果事情不清楚,道歉;这是我第一次来这里:)。任何指点都很感激


目前正在使用JAX-WS2.1、Tomcat7和Servlet3.0。

好的,经过大量实验,我已经能够组合出一些有效的东西。为了便于记录,我将把它贴在这里

基本上,我是通过模拟或重新实现JAX-WS如何从它的WSServletContextListener创建它的WSServlet来实现这一点的。不幸的是,我无法找到一个更简单或更好的支持和直接的方法来实现这一点

基本上,我的工厂使用它的WSEndpoint.create()方法创建一个WSEndpoint。create()将我试图包装的WebService实现的类作为输入。大多数其他输入都为null,以鼓励WSEndpoint使用默认值或尝试从实现类中的注释中提取一些配置

然后,我使用一个新的ServletAdapterList()来创建一个ServletAdapter,该ServletAdapter使用先前创建的WSEndpoint。为此,因为我为每个实现类创建一个Servlet,所以适配器的名称无关紧要,可以将其配置为将所有通信发送到实现,而不管URL如何

然后,我使用先前ServletAdapter的单例列表创建一个新的WSServletDelegate()。这里唯一的诀窍是,JAX-WS似乎有一个坏习惯,至少在这一步和下一步中是这样的:在ServletContext的init参数中存储一些值。它也不能正确地进行null检查,即使在参数不在上下文中的情况下,它有默认值可供使用。因此,我还创建了ServletContext的一个虚拟实现,并将其传递到WSServletDelegate构造函数中,使其感觉像是在查找init参数


最后,我创建了一个HttpServlet实现,它将请求转发给WSServletDelegate,类似于WSServlet的方式。由于WSServlet再次将委托对象存储在ServletContext init参数中,因此我发现重新实现其功能比处理现有WSServlet更容易。HttpServlet的这个实现可以像任何普通的Servlet一样接受和处理SOAP Web服务调用。

好的,经过大量的实验,我已经能够组合出一些有效的东西。为了便于记录,我将把它贴在这里

基本上,我是通过模拟或重新实现JAX-WS如何从它的WSServletContextListener创建它的WSServlet来实现这一点的。不幸的是,我无法找到一个更简单或更好的支持和直接的方法来实现这一点

基本上,我的工厂使用它的WSEndpoint.create()方法创建一个WSEndpoint。create()将我试图包装的WebService实现的类作为输入。大多数其他输入都为null,以鼓励WSEndpoint使用默认值或尝试从实现类中的注释中提取一些配置

然后,我使用一个新的ServletAdapterList()来创建一个ServletAdapter,该ServletAdapter使用先前创建的WSEndpoint。为此,因为我为每个实现类创建一个Servlet,所以适配器的名称无关紧要,可以将其配置为将所有通信发送到实现,而不管URL如何

然后,我使用先前ServletAdapter的单例列表创建一个新的WSServletDelegate()。这里唯一的诀窍是,JAX-WS似乎有一个坏习惯,至少在这一步和下一步中是这样的:在ServletContext的init参数中存储一些值。它也不能正确地进行null检查,即使在参数不在上下文中的情况下,它有默认值可供使用。因此,我还创建了ServletContext的一个虚拟实现,并将其传递到WSServletDelegate构造函数中,使其感觉像是在查找init参数


最后,我创建了一个HttpServlet实现,它将请求转发给WSServletDelegate,类似于WSServlet的方式。由于WSServlet再次将委托对象存储在ServletContext init参数中,因此我发现重新实现其功能比处理现有WSServlet更容易。HttpServlet的这个实现可以像任何普通的Servlet一样接受和处理SOAP Web服务调用。

根据Anthop的回答,这是我提出的适合我的代码

//主代码:
最终ServletContextHandler soapContextHandler=createSoapServletContextHandler();
final HandlerList handlers=new HandlerList();
setHandlers(新处理程序[]{soapContextHandler});
server=createServer(端口);
setHandler(handl