[jbossws-issues] [JBoss JIRA] Updated: (JBWS-3131) CLONE -JBossWS is picking the wrong binding when both Soap1.1 and Soap1.2 bindings are provided for a port

Fernando Rubbo (JIRA) jira-events at lists.jboss.org
Tue Sep 21 13:21:29 EDT 2010


     [ https://jira.jboss.org/browse/JBWS-3131?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Fernando Rubbo updated JBWS-3131:
---------------------------------

    Attachment: NfeStatusServico2.wsdl
                NfeStatusServico21.wsdl


NfeStatusServico2.wsdl is the original file
NfeStatusServico21.wsdl is the modified file.

The only difference between these files are the name of the port on line 72

Original line
     <wsdl:port name="NfeStatusServico2Soap" binding="tns:NfeStatusServico2Soap">
Modified line
     <wsdl:port name="NfeStatusServico2Soap1" binding="tns:NfeStatusServico2Soap">

> CLONE -JBossWS is picking the wrong binding when both Soap1.1 and Soap1.2 bindings are provided for a port
> ----------------------------------------------------------------------------------------------------------
>
>                 Key: JBWS-3131
>                 URL: https://jira.jboss.org/browse/JBWS-3131
>             Project: JBoss Web Services
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: jbossws-native
>    Affects Versions:  jbossws-native-3.0.2, jbossws-native-3.4.0
>         Environment: AS 4.x, AS 5.x
>            Reporter: Fernando Rubbo
>            Assignee: Alessio Soldano
>         Attachments: NfeStatusServico2.wsdl, NfeStatusServico21.wsdl
>
>
> I've cloned this issue because it was closed and I was not able to reopen it.
> The bug is on class org.jboss.ws.metadata.builder.MetaDataBuilder in initEndpointBinding(..) method. Below the explanation of the bug and the patch to fix the problem.
>  protected void initEndpointBinding(WSDLEndpoint wsdlEndpoint, EndpointMetaData epMetaData)
>  {
>       WSDLDefinitions wsdlDefinitions = wsdlEndpoint.getWsdlService().getWsdlDefinitions();
>       //WSDLInterface wsdlInterface = wsdlEndpoint.getInterface();
>       //WSDLBinding wsdlBinding = wsdlDefinitions.getBindingByInterfaceName(wsdlInterface.getName());
>       /* BEGIN PATCH */
>       /*
>        * Both commented lines above were replaced by the piece of code below.
>        *
>        * CAUSE: Once an interface may have more than one binding and once, at this point of the code,
>        * we already know which binding to use (it is inside of the wsdlEndpoint), we can simple get the binding
>        * of wsdlEndpoint INSTEAD of trying to guess which binding the user would like to use.
>        *
>        * NOTE: This bug is used to be intermittent because it depends on the name given for the binding. The bindings property
>        * inside of WSDLBinding is a LinkedHashMap in which the key is the binding Name. Once the method wsdlDefinitions.getBindingByInterfaceName(..)
>        * is called it iterates over bindings proprety and gets the last binding associated to the given interface. Note that we
>        * MUST NOT get the last one. We know what binding we would like to use.
>        *
>        * KNOWN ISSUE: This issue was already submitted in the past (https://jira.jboss.org/browse/JBWS-2278?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#issue-tabs)
>        * but it seems that it was closed because the developer did not understood exactly what the problem was about. Moreover
>        * it seems that up until now it was not fixed yet. Even in the newest version of the jbossws-core.
>        */
>       WSDLBinding wsdlBinding;
>       final QName binding = wsdlEndpoint.getBinding();
>       if(binding!=null){
>           wsdlBinding = wsdlDefinitions.getBinding(binding);
>       }else{
>           // These lines are here only for backward compatibility. Supose a case which wsdlEndpoint does
>           // not contain a binding associated. In this case, it will keep doing as it did before.
>           WSDLInterface wsdlInterface = wsdlEndpoint.getInterface();
>           wsdlBinding = wsdlDefinitions.getBindingByInterfaceName(wsdlInterface.getName());
>       }
>       /* END PATCH */
>       String bindingType = wsdlBinding.getType();
>       if (Constants.NS_SOAP11.equals(bindingType))
>       {
>         epMetaData.setBindingId(Constants.SOAP11HTTP_BINDING);
>       }
>       else if (Constants.NS_SOAP12.equals(bindingType))
>       {
>         epMetaData.setBindingId(Constants.SOAP12HTTP_BINDING);
>       }
>  }
> The WSDL file which can be used to reproduce the this issue:
> <?xml version="1.0" encoding="utf-8"?>
> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
>   <wsdl:types>
>     <s:schema elementFormDefault="qualified" targetNamespace="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
>       <s:element name="nfeDadosMsg">
>         <s:complexType mixed="true">
>           <s:sequence>
>             <s:any />
>           </s:sequence>
>         </s:complexType>
>       </s:element>
>       <s:element name="nfeStatusServicoNF2Result">
>         <s:complexType mixed="true">
>           <s:sequence>
>             <s:any />
>           </s:sequence>
>         </s:complexType>
>       </s:element>
>       <s:element name="nfeCabecMsg" type="tns:nfeCabecMsg" />
>       <s:complexType name="nfeCabecMsg">
>         <s:sequence>
>           <s:element minOccurs="0" maxOccurs="1" name="versaoDados" type="s:string" />
>           <s:element minOccurs="0" maxOccurs="1" name="cUF" type="s:string" />
>         </s:sequence>
>         <s:anyAttribute />
>       </s:complexType>
>     </s:schema>
>   </wsdl:types>
>   <wsdl:message name="nfeStatusServicoNF2SoapIn">
>     <wsdl:part name="nfeDadosMsg" element="tns:nfeDadosMsg" />
>   </wsdl:message>
>   <wsdl:message name="nfeStatusServicoNF2SoapOut">
>     <wsdl:part name="nfeStatusServicoNF2Result" element="tns:nfeStatusServicoNF2Result" />
>   </wsdl:message>
>   <wsdl:message name="nfeStatusServicoNF2nfeCabecMsg">
>     <wsdl:part name="nfeCabecMsg" element="tns:nfeCabecMsg" />
>   </wsdl:message>
>   <wsdl:portType name="NfeStatusServico2Soap">
>     <wsdl:operation name="nfeStatusServicoNF2">
>       <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Serviço destinado à consulta do status do serviço prestado pela Sefaz Virtual do Ambiente Nacional</wsdl:documentation>
>       <wsdl:input message="tns:nfeStatusServicoNF2SoapIn" />
>       <wsdl:output message="tns:nfeStatusServicoNF2SoapOut" />
>     </wsdl:operation>
>   </wsdl:portType>
>   <wsdl:binding name="NfeStatusServico2Soap" type="tns:NfeStatusServico2Soap">
>     <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
>     <wsdl:operation name="nfeStatusServicoNF2">
>       <soap:operation soapAction="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2/nfeStatusServicoNF2" style="document" />
>       <wsdl:input>
>         <soap:body use="literal" />
>         <soap:header message="tns:nfeStatusServicoNF2nfeCabecMsg" part="nfeCabecMsg" use="literal" />
>       </wsdl:input>
>       <wsdl:output>
>         <soap:body use="literal" />
>       </wsdl:output>
>     </wsdl:operation>
>   </wsdl:binding>
>   <wsdl:binding name="NfeStatusServico2Soap12" type="tns:NfeStatusServico2Soap">
>     <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
>     <wsdl:operation name="nfeStatusServicoNF2">
>       <soap12:operation soapAction="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2/nfeStatusServicoNF2" style="document" />
>       <wsdl:input>
>         <soap12:body use="literal" />
>         <soap12:header message="tns:nfeStatusServicoNF2nfeCabecMsg" part="nfeCabecMsg" use="literal" />
>       </wsdl:input>
>       <wsdl:output>
>         <soap12:body use="literal" />
>       </wsdl:output>
>     </wsdl:operation>
>   </wsdl:binding>
>   <wsdl:service name="NfeStatusServico2">
>     <wsdl:port name="NfeStatusServico2Soap" binding="tns:NfeStatusServico2Soap">
>       <soap:address location="https://hom.nfe.fazenda.gov.br/SCAN/NfeStatusServico2/NfeStatusServico2.asmx" />
>     </wsdl:port>
>     <wsdl:port name="NfeStatusServico2Soap12" binding="tns:NfeStatusServico2Soap12">
>       <soap12:address location="https://hom.nfe.fazenda.gov.br/SCAN/NfeStatusServico2/NfeStatusServico2.asmx" />
>     </wsdl:port>
>   </wsdl:service>
> </wsdl:definitions>
> Also, I've done some unit testes to show the problem. 
> P.S.: Remember to set in the "VM Arguments" the following property. -Djava.endorsed.dirs="<JBOSS_HOME>\\lib\\endorsed"
> / **
>  * @author Fernando Rubbo
>  */
> public class TestWSDLWithTwoBindingsForOneInterface
> {
>     private final String PATH_WSDL_FILE = "<PATH>\\NfeStatusServico2.wsdl";
>     private final String PATH_CHANGED_WSDL_FILE = "<PATH>\\NfeStatusServico21.wsdl";
>     private Service service;
>     private Service serviceChanged;
>     @Before
>     public void setUp() throws IOException
>     {
>         URL wsdlLoc = new URL(PATH_WSDL_FILE);
>         QName serviceName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2");
>         service = Service.create(wsdlLoc, serviceName);
>         /*
>          * After changing the line 72 of the WSDL as shown below. We have the order of the wsdlDefinitions.bindings property changed.
>          * Original line
>          *      <wsdl:port name="NfeStatusServico2Soap" binding="tns:NfeStatusServico2Soap">
>          * Modified line
>          *      <wsdl:port name="NfeStatusServico2Soap1" binding="tns:NfeStatusServico2Soap">
>          */
>         wsdlLoc = new URL(PATH_CHANGED_WSDL_FILE);
>         serviceName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2");
>         serviceChanged = Service.create(wsdlLoc, serviceName);
>     }
>     @Test
>     public void testSOAP11OnOriginalWSDL() throws IOException
>     {
>         // asking for using the SOAP 1.1 binding. no problem...
>         QName portName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2Soap");
>         Dispatch<Source> dispatch = service.createDispatch(portName, Source.class, Mode.MESSAGE);
>         String bindingID = dispatch.getBinding().getBindingID();
>         Assert.assertEquals("http://schemas.xmlsoap.org/wsdl/soap/http", bindingID);
>     }
>     @Test
>     public void testSOAP12OnOriginalWSDL() throws IOException
>     {
>         // As you can see, the below code is asking for using the SOAP 1.2 binding. It should return a dispath for
>         // the SOAP 1.2 binding, however it does not behaviour as expected...
>         QName portName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2Soap12");
>         Dispatch<Source> dispatch = service.createDispatch(portName, Source.class, Mode.MESSAGE);
>         String bindingID = dispatch.getBinding().getBindingID();
>         Assert.assertEquals("http://www.w3.org/2003/05/soap/bindings/HTTP/", bindingID);
>     }
>     @Test
>     public void testSOAP11OnChangedWSDL() throws IOException
>     {
>         // in this test we are asking for using the SOAP 1.1 binding but using the changed WSDL. Note that the order of the
>         // the bindings property of WSDLBinding has changed. Therefore, it gets the wrong binding for the SOAP 1.1.
>         QName portName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2Soap1");
>         Dispatch<Source> dispatch = serviceChanged.createDispatch(portName, Source.class, Mode.MESSAGE);
>         String bindingID = dispatch.getBinding().getBindingID();
>         Assert.assertEquals("http://schemas.xmlsoap.org/wsdl/soap/http", bindingID);
>     }
>     @Test
>     public void testSOAP12OnChangedWSDL() throws IOException
>     {
>         // Since the order the bindings property of WSDLBinding has changed we have no problem asking for using the SOAP 1.2 binding.
>         QName portName = new QName("http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2","NfeStatusServico2Soap12");
>         Dispatch<Source> dispatch = serviceChanged.createDispatch(portName, Source.class, Mode.MESSAGE);
>         String bindingID = dispatch.getBinding().getBindingID();
>         Assert.assertEquals("http://www.w3.org/2003/05/soap/bindings/HTTP/", bindingID);
>     }
> }
> Hope this helps to fix the problem.
> Thanks in advance
> ----------------------------------------------------------------------------------------------------------------------------------------------------
> I am implementing an interop test using WSDL organized as follows:
> <?xml version="1.0" encoding="UTF-8"?>
> <wsdl:definitions targetNamespace="http://www.wstf.org/docs/scenarios/sc002"
>                   xmlns:xs="http://www.w3.org/2001/XMLSchema"
>                   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
>                   xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
>                   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
>                   xmlns:tns="http://www.wstf.org/docs/scenarios/sc002">
>   <wsdl:types>
>     . . .
>   </wsdl:types>
>   <wsdl:message name="Begin">
>     <wsdl:part name="Begin" element="tns:Begin"/>
>       . . .
>   </wsdl:message>
>   <wsdl:portType name="sc002Port">
>     <wsdl:operation name="Begin">
>       . . .
>   </wsdl:portType>
>   <wsdl:binding name="sc002SOAP11Binding" type="tns:sc002Port">
>     <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
>     <wsdl:operation name="Begin">
>     . . .
>   </wsdl:binding>
>   <wsdl:binding name="sc002SOAP12Binding" type="tns:sc002Port">
>     <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
>     <wsdl:operation name="Begin">
>     . . .
>   </wsdl:binding>
>   <wsdl:service name="sc002Service">
>     <wsdl:port  name="soap11port" binding="tns:sc002SOAP11Binding">
>       <soap:address location="http://www.wstf.org/sc002/sc002SOAP11"/>
>     </wsdl:port>
>     <wsdl:port name="soap12port" binding="tns:sc002SOAP12Binding">
>       <soap12:address location="http://www.wstf.org/sc002/sc002SOAP12"/>
>     </wsdl:port>
>   </wsdl:service>
> </wsdl:definitions>
> In other words, there is one port, two bindings and one service exporting the two bindings.
> I create a client proxy for the port named "soap11port" by invoking
>   new Sc002Service().getPort(new QName("http://www.wstf.org/docs/scenarios/sc002", "soap11port"), Sc002Port.class)
> The returned port uses a SOAP12 binding even though the WSDL labels it clearly as a 1.1 port.
> The problem arises because of an error in the construction of the ClientEndPointMetaData used as the endpointMetaData attached to the ClientProxy. This is constructed inside the ServiceDelegateImpl constructor by invoking JAXWSClientMetaDataBuilder.buildMetaData(). The error occurs in inherited method MetaDataBuilder.initEndpointBinding() when it tries to identify the binding associated with QName sc002:soap11port. The following 4 lines are where it goes wrong:
>       WSDLDefinitions wsdlDefinitions = wsdlEndpoint.getWsdlService().getWsdlDefinitions();
>       WSDLInterface wsdlInterface = wsdlEndpoint.getInterface();
>       WSDLBinding wsdlBinding = wsdlDefinitions.getBindingByInterfaceName(wsdlInterface.getName());
>       String bindingType = wsdlBinding.getType();
> The first two lines locate the port sc002 associated with the binding identified by sc002:soap11port. The 3rd line then reverse searches from the port to find a binding which binds it. Of course there are two of these and, mirabile dictu, the code even prints a warning about this. It then ignores the correct and returns the soap12 binding.
> Ironically before reaching this point the JAXWSClientMetaDataBuilder does this search correctly in method buildMetaDataInternal at lines 154/5 it executes this code
>          WSDLBinding wsdlBinding = wsdlEndpoint.getWsdlService().getWsdlDefinitions().getBinding(bindingName);
>          String bindingType = wsdlBinding.getType();
> I assume the convoluted code in the inherited method is there for a reason but, then again, that's what overriding was invented for.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       



More information about the jbossws-issues mailing list