3 Replies Latest reply on Apr 17, 2007 4:32 AM by dlofthouse

    JSR-109Client, Mapping problem and trying to connect to a .N

    d_pavel

      Hi All,

      I developed a JAX-RPC web service client in order to connect to a .NET webservice. I am using jdk1.5.0_09, JBoss AS 4.0.5.GA and jbossws-1.2.0.GA. I set properly the java.endorsed.dirs.
      Here is the config file:

      <?xml version="1.0" encoding="UTF-8"?>
      
      <!-- top~down or wsdl~to~java JAX-RPC config file -->
      <configuration xmlns="http://www.jboss.org/jbossws-tools"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.jboss.org/jbossws-tools http://www.jboss.org/jbossws-tools/schema/jbossws-tool_1_0.xsd">
      
       <wsdl-java file="META-INF/Vax.wsdl">
       <mapping file="jaxrpc-mapping.xml" />
       </wsdl-java>
      
      </configuration>
      

      Using wstools I was able to generate the related artifacts (the jaxrpc-mapping.xml file and all the related stubs and the required Service Endpoint Interface (SEI).

      The target namespace it will be similar with: "https://www.acompany.com/VaxHttp/Vax"

      The important code in my client looks like this:
       String feedback = "";
       try
       {
       URL url = null;
       //wsdl location
       try
       {
       url = new URL(urlstr);
       }
       catch (MalformedURLException e)
       {
       e.printStackTrace();
       }
      
       QName qName = new QName("https://www.acompany.com/VaxHttp/Vax.asmx?wsdl", "Vax");
      
       System.out.println("############ local part = "+qName.getLocalPart());
       System.out.println("############ namespace URI = "+qName.getNamespaceURI());
      
       //set jboss ServiceFactory
       System.setProperty( "javax.xml.rpc.ServiceFactory",
       "org.jboss.ws.core.jaxrpc.client.ServiceFactoryImpl" );
      
       //have to have only one instance of the ServiceFactory
       ServiceFactoryImpl serviceFactory = (ServiceFactoryImpl)ServiceFactory.newInstance();
       File mapping = new File("WebRoot/WEB-INF/jaxrpc-mapping.xml");
       URL mappingURL = null;
       try
       {
       mappingURL = mapping.toURL();
       }
       catch (MalformedURLException e)
       {
       e.printStackTrace();
       }
      
       ServiceImpl service = (ServiceImpl)serviceFactory.createService(url, qName, mappingURL);
      
       //get stub or dynamic proxy that supports the specified service endpoint interface
       VaxSoap port = (VaxSoap) service.getPort(VaxSoap.class);
      
       //create PutOrder object
       PutOrder po = new PutOrder(...);
      
       //using SOAP 1.1 and calling the related method on the service endpoint interface
       PutOrderResponse status = port.putOrder(po);
      
       feedback = status.getPutOrderResult();
       //check the PurchaseOrder status
       System.out.println("output order response:" + feedback);
      
       }
       catch(ServiceException se)
       {
       System.out.println("Service Exception from executePutPurchaseOrder() = "+se.getMessage());
       }
      
       return feedback;
      


      Now when I try to run the client passing the valid parameters, I get the following mapping exception from the Client:

      Could not update IN parameter to be INOUT, as indicated in the mapping: parameters

      In the generated jaxrpc-mapping.xml (after the wsdl available) all the ~SoapIn wsdl-message from within the related wsdl-message-mapping have this

      <parameter-mode>INOUT</parameter-mode>

      parameter mode defined.
      I want to metion that is no denial of traffic and the network is good.
      Now this param can be IN, OUT, or INOUT. I should not have to modify this generated xml file! However if I modify it and put "IN" instead of "INOUT" I am able to go further (but this in fact is not correct because the called method has to return a PutOrderResponse object so we need the INOUT isn't it ?). Anyway using a modified jaxrpc-mapping.xml as I said before I am able to make the invokation to the remote web service but it barfs here:

      org.jboss.remoting.CannotConnectException: Can not connect http client invoker.

      This exception is generated when the remoting layer cannot connect to
      the remote server . It means that the client cannot send the request to
      the server. Well it's normal I think when the remote side is on .NET and the JBoss TransporterClient(InvokerLocator locator, String targetSubsystem) it's trying to use a org.jboss.remoting.InvokerLocator which will work as it is only between JBOSS application servers (correct me if I'm wrong please). The JBossWS fails to create properly the org.jboss.remoting.Client remoteClient instance.
      How can one explicitly set the transport protocol to be "http" (and not "socket" as for the JBoss AS) ?
      I mean the InvokerLocator has to take that into consideration when trying to connect to .NET webservices right ?
      There is some documentation or useful links related to how to connect to .NET webservices ? I will have also my own JBoss webservices which will have to be accessible from any endpoint (well .NET is the one I'm afraid off and it's causing me grief).

      Did I missed something ? I mean the client description is pretty straight forward in the user guide...

      Aside: when the "JBoss Remoting" comes in to play ? For what is recommended especially ?If one doesn't use transports and data marshallers or push and pull callbacks, then doesn't need "JBoss Remoting" either right?

      I hope to get an answer to this post because this is not trivial to debug and fix. Please help.
      I would really appreciate an/any answer as soon as possible.

      Thank you in advance.

        • 1. Re: JSR-109Client, Mapping problem and trying to connect to
          d_pavel

          OK this is what I discovered:
          The "Could not update IN parameter to be INOUT..." error comes from processOutputDocElement method inside JAXRPCMetaDataBuilder class. The processOutputDocElement is called from


          buildParameterMetaDataDoc(OperationMetaData opMetaData, WSDLInterfaceOperation wsdlOperation, ServiceEndpointMethodMapping seiMethodMapping,TypeMappingImpl typeMapping)

          Now the description of this class is mentioning: "A meta data builder that is based on webservices.xml." So I supposed that this error occurs due to issues related to my webservices.xml.
          Here is my webservices.xml :
          <webservices version='1.1' xmlns='http://java.sun.com/xml/ns/j2ee' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd'>
           <webservice-description>
           <webservice-description-name>Vax</webservice-description-name>
           <wsdl-file>WebRoot/WEB-INF/wsdl/Vax.wsdl</wsdl-file>
           <jaxrpc-mapping-file>WebRoot/WEB-INF/jaxrpc-mapping.xml</jaxrpc-mapping-file>
           <port-component>
           <port-component-name>VaxSoapPort</port-component-name>
           <!-- wsdl-port xmlns:portNS='https://www.acompany.com/VaxHttpTest/Vax.asmx'>portNS:VaxSoapPort</wsdl-port -->
           <wsdl-port xmlns:portNS='https://www.acompany.com/VaxHttpTest/VaxSoap'>portNS:VaxSoapPort</wsdl-port>
          
           <service-endpoint-interface>ca.agenthttp.vax.VaxSoap</service-endpoint-interface>
           <service-impl-bean>
           <servlet-link>VaxSoap</servlet-link>
           </service-impl-bean>
           </port-component>
           </webservice-description>
          </webservices>
          


          Now from the docs we know:

          The port-component-name element specifies a port component's name. This name is assigned by the module producer to name the service implementation bean in the module's deployment descriptor. The name must be unique among the port component names defined in the same module.
          Used in: port-component
          Example:
          <port-component-name>EmployeeService
          </port-component-name>

          So according to this the wsdl-port tag line should be like this:

          <wsdl-port xmlns:portNS='https://www.acompany.com/VaxHttpTest/VaxSoap'>portNS:VaxSoapPort</wsdl-port>


          I tried also to provide the target namespace like in the commented line:

          <!-- wsdl-port xmlns:portNS='https://www.acompany.com/VaxHttpTest/Vax.asmx'>portNS:VaxSoapPort</wsdl-port -->

          (even if I know the correct use is like in the previous uncommented line) but with same error results:

          Could not update IN parameter to be INOUT, as indicated in the mapping: parameters


          Is it possible that this occurs because the wsdl location URL points to

          https://www.acompany.com/VaxHttp/Vax?wsdl

          but the real SEI is in fact "VaxSoap" class ???
          Let me explain: "Vax" referenced in URL is just a simple javax.xml.rpc.Service and looks like this:
          /*
          * JBoss, the OpenSource EJB server
          * Distributable under LGPL license. See terms of license at gnu.org.
          */
          
          //Auto Generated by jbossws - Please do not edit!!!
          
          package ca.agenthttp.vax;
          
          
          import javax.xml.rpc.*;
          
          
          public interface Vax extends javax.xml.rpc.Service
          {
          
           public ca.agenthttp.vax.VaxSoap getVaxSoap() throws ServiceException;
          
          }
          

          Now the ca.agenthttp.vax.VaxSoap is my real SEI which contains references to all the published methods which are web servable.

          Please confirm to me if this webservices.xml is properly configured or if I have to reconfigure some other .xml files.

          Last but not least this is my jboss-client.xml file:
          <?xml version="1.0" encoding="UTF-8"?>
          
          <jboss-client>
           <jndi-name>jbossws-client</jndi-name>
           <service-ref>
           <service-ref-name>Vax</service-ref-name>
           <wsdl-override>
          https://www.acompany.com/VaxHttpTest/Vax.asmx?wsdl
           </wsdl-override>
           </service-ref>
          </jboss-client>
          


          The service defined in Wax.wsdl looks like this:
           <wsdl:service name="Vax">
           <wsdl:port name="VaxSoap" binding="tns:VaxSoap">
           <soap:address location="https://www.acompany.com/VaxHttpTest/Vax.asmx" />
           </wsdl:port>
           </wsdl:service>
          


          Any suggestions ?

          • 2. Re: JSR-109Client, Mapping problem and trying to connect to
            d_pavel

            Once again the root cause of the problems are the JBossWS tools used to generate the required artifacts.
            For comparison I used XFire (=open source Java SOAP framework).
            I got a total of X artifacts generated using JBossWS wbservices stack and related tools.
            In comparison I got a total of (X+10) artifacts generated using XFire (from these other 10 artifacts 7 are array type classes and the reminder of 3 are just simple object type classes...).

            So in conclusion I used both and here is my opinion:
            Not only that (different nr of artifacts), but there are discrepancies between the structure of the generated artifacts using JBossWS versus XFire even if the core of them should be in sync because I run against same WSDL. Please correct me if I'm wrong related with my last assumption.
            Even the methods in the generated Service Endpoint Interface had different method signatures (well 2 of them but still !!!).

            Now everything is working for me without issues (sorry no offence) but I was wondering about the different result from the tools in the 2 cases mentioned above....

            • 3. Re: JSR-109Client, Mapping problem and trying to connect to
              dlofthouse

              There is no requirement for two code generators to generate identicle code as the JAX-RPC mapping file is used to describe how the schema was mapped to Java.

              If you have a reproducable scenario where invalid code is being generated please raise a bug in Jira with the required files to reproduce it.