如何将未将BindingProvider子类化的对象显式转换为BindingProvider对象?

时间:2015-08-13 10:39:14

标签: java web-services java-ee jax-ws soap-client

我有一个Web服务,我使用客户端API中的服务接口对象操作SOAP头。

我需要将端口对象输入到BindingProvider对象中。但我的port对象并没有直接子类化该类。那么JVM怎么可能不抱怨?

它也有效。没有ClassCastException的运行时错误

代码段:

    public SearchDocument getSearchDocumentService(String wsdlUri, AuthBean auth){
    SearchDocument_Service serv = null;
    serv = SearchDocument_Service.getServiceInstance(wsdlUri);
    SearchDocument searchDoc = serv.getSearchDocument();

    populateAuthAndHandlerInfo((BindingProvider)searchDoc, auth);//how is it that jvm doesn't complain here
    return searchDoc;
    }

    private void populateAuthAndHandlerInfo(BindingProvider port, AuthBean auth) {
    Binding binding = port.getBinding();
              List<Handler> handlerList = binding.getHandlerChain();
              handlerList.add(new EDMSSoapAuthHandler());
              binding.setHandlerChain(handlerList);
        Map<String, Object> context = port.getRequestContext();
        context.put("clientAuthInfo", auth);
        }

SearchDocument.java:

    @WebService(name = "SearchDocument", targetNamespace = "http://services.abc.com/Technology/SearchDocument/service/v1")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface SearchDocument {


    /**
     * 
     * @param body
     * @return
     *     returns com.abc.technology.search.document.client.v1.SearchOnMetadataResponse
     * @throws AbcServiceException
     * @throws AbcInvalidMessageException
     * @throws AbcProducerApplicationException
     */
    @WebMethod(action = "http://services.abc.com/Technology/SearchDocument/service/v1/soap11/SearchDocument/searchOnMetadata")
    @WebResult(name = "SearchOnMetadataResponse", targetNamespace = "http://services.abc.com/Technology/SearchDocument/contract/v1", partName = "body")
    public SearchOnMetadataResponse searchOnMetadata(
        @WebParam(name = "SearchOnMetadata", targetNamespace = "http://services.abc.com/Technology/SearchDocument/contract/v1", partName = "body")
        SearchOnMetadataRequest body)
        throws AbcInvalidMessageException, AbcProducerApplicationException, AbcServiceException
    ;

}

1 个答案:

答案 0 :(得分:4)

有几种方法可以回答您的问题。

从高层来看

  

但我的port对象并没有直接子类化该类。那么JVM怎么可能不抱怨呢?

嗯... SearchDocument是一个界面。所以,当你打电话

SearchDocument searchDoc = serv.getSearchDocument();

然后searchDoc是实现接口的给定类型的实例,但它没有指定这个具体类是什么。它可以是任何东西,包括实现SearchDocumentBindingProvider的具体类,因为它们都是接口,任何给定类型都可以同时实现多个接口。 所以这种必须这里发生了什么,对吗?

来自JAX WS规范

查看JAXWS规范可能会进一步启发您。你可以在https://jcp.org/en/jsr/detail?id=224下载它,但我会在第4.2.3章为你引用一些小块:

  

代理在运行时提供对服务端点接口的访问,而无需静态生成存根类。请参阅java.lang.reflect.Proxy   有关JDK支持的动态代理的更多信息

     

...

     

一致性(实现BindingProvider):代理实例必须实现javax-.xml.ws.BindingProvider

     

...

     

使用Service实例的getPort方法创建代理:T getPort(Class sei)返回指定SEI的代理

现在很容易将这些碎片重新组合在一起。

什么是java.lang.reflect.Proxy

在JVM中,有一个用于创建代理对象的API。 Proxy对象(实例)是JVM中的一种特殊的野兽,可以在运行时动态创建,并且每个代理都可以符合任何给定的接口。它类似于在运行时创建Class,而不是在编译时创建Proxy,而无需编写其java源文件。当然,存在各种限制,但也存在许多可能性。

一个是对JVM说:&#34;嘿,给我一个SearchDocument对象,同时实现接口BindingProviderProxy&#34;。 JVM也是如此。它会返回一个对象,其具体类为InvocationHandler(通常为Proxy $ x,其中x为数字),并且是专门为实现这两个接口而设计的。

如果你想知道这在这一点上是否有用,那么不是没有,因为创建一个没有实现的类型是没有意义的。但是,有一种方法可以通过你编程的getPort提供实现和行为(确切地说是另一种讨论)。

所以,在这一点上,我们从规范得到的是,如果我们在javax.xml.ws.Service上调用BindingProvider,那么结果必须是一个JDK代理,它必须实现{{1} }。

回到你的案例

我敢打赌,正是在您致电:SearchDocument_Service时会发生什么,它最终调用getPort方法,并确保结果实现BindingProvider,因为JAXWS说它必须这样做,以及您的SearchDocument&#34;业务&#34;界面,因为它对你有用。