7 Replies Latest reply on Jun 21, 2006 4:13 PM by Sverker Abrahamsson

    DII client question

    Justin Bertram Newbie

      I am attempting to write a stand-alone JUnit test to invoke and validate a web service I have running in JBoss 4.0.4GA (JDK 5). According to http://labs.jboss.com/portal/jbossws/user-guide/en/html/clients.html all I need to do is use this:

      public void testEchoString() throws Exception
       {
       ServiceFactoryImpl factory = new ServiceFactoryImpl();
       Service service = factory.createService(new QName("ANY_SERVICE_NAME"));
      
       Call call = service.createCall();
       call.setOperationName(new QName(TARGET_NAMESPACE, "echoString"));
       call.addParameter("String_1", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
       call.addParameter("String_2", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
       call.setReturnType(Constants.TYPE_LITERAL_STRING);
      
       call.setTargetEndpointAddress(TARGET_ENDPOINT_ADDRESS);
      
       String hello = "Hello";
       String world = "world!";
       Object retObj = call.invoke(new Object[]{hello, world});
       assertEquals(hello + world, retObj);
       }


      However, the "echoString" service takes simple String objects as input and my service takes a custom object. I have tried modifying the code to use my object but I am getting an exception. Here is my code:
      public void testEchoString() throws Exception {
       ServiceFactoryImpl factory = new ServiceFactoryImpl();
       Service service = factory.createService(new QName("JBossTest2"));
      
       Call call = service.createCall();
       call.setOperationName(new QName("http://us.mycompany.com/jbosstest2/1.0", "prescreen"));
       call.addParameter("JBossTest2Request", new QName("JBossTest2Request"), ParameterMode.IN);
       call.setReturnType(new QName("com.mycompany.us.test.JBossTest2Reply"));
      
       call.setTargetEndpointAddress("http://jbertr1005:8080/jbosstest2/1.0");
      
       String hello = "Hello";
       String world = "world!";
       Object retObj = call.invoke(new Object[] { new JBossTest2Request() });
       assertEquals(hello + world, retObj);
       }
      


      And here is the exception I am receiving:

      java.lang.IllegalArgumentException: Invalid null parameter
       at org.jboss.ws.jaxrpc.CallImpl.setReturnType(CallImpl.java:349)
       at org.jboss.ws.jaxrpc.CallImpl.setReturnType(CallImpl.java:341)
       at com.mycompany.us.test.ws.WSTestCase.testEchoString(WSTestCase.java:51)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at junit.framework.TestCase.runTest(TestCase.java:154)
       at junit.framework.TestCase.runBare(TestCase.java:127)
       at junit.framework.TestResult$1.protect(TestResult.java:106)
       at junit.framework.TestResult.runProtected(TestResult.java:124)
       at junit.framework.TestResult.run(TestResult.java:109)
       at junit.framework.TestCase.run(TestCase.java:118)
       at junit.framework.TestSuite.runTest(TestSuite.java:208)
       at junit.framework.TestSuite.run(TestSuite.java:203)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
      
      


      How do I get a simple DII client to invoke a web service that uses custom objects for input and output?

        • 1. Re: DII client question
          Thomas Diesler Master

          The user guide has been updated on this

          http://labs.jboss.com/portal/jbossws/user-guide/en/html/clients.html

          This type of "do it all yourself" DII is the worst possible choice. Use wsdl + jaxrpc-mapping.xml to configure your client proxy

          • 2. Re: DII client question
            Sverker Abrahamsson Novice

            Thomas,
            if the neither wsdl nor jaxrpc-mapping.xml are availible then there are no other option than to use DII. It sucks but that's the case sometimes..

            However, I still can't find from the users guide how to do when the web service return a complex type.

            My code now looks like this:

             String endpoint = "https://cbg.tele2.com:443/xmlrpc-login";
            
             ServiceFactory factory = ServiceFactory.newInstance();
             Service service = factory.createService(new QName("ANY_SERVICE_NAME"));
             Call call = service.createCall();
             call.setTargetEndpointAddress(endpoint);
             call.setOperationName(new QName("http://testuri.org", "TRANSLATEIP"));
             call.addParameter("login.user", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
             call.addParameter("login.password", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
             call.addParameter("OriginatingCustomerIP", Constants.TYPE_LITERAL_STRING, ParameterMode.IN);
            
             QName qn = new QName( "item" );
             call.setReturnType(qn,Item.class);
             Item ret = (Item) call.invoke( new Object[] { user, password, ip});
            


            This cause a stack trace like this:
            java.lang.IllegalArgumentException: Invalid namespace for type: item
            at org.jboss.ws.jaxrpc.SchemaGenerator.assertXmlType(SchemaGenerator.java:104)
            at org.jboss.ws.jaxrpc.SchemaGenerator.generateXSDSchema(SchemaGenerator.java:55)
            at org.jboss.ws.jaxrpc.CallImpl.generateOrUpdateParameterSchema(CallImpl.java:804)
            at org.jboss.ws.jaxrpc.CallImpl.generateOrUpdateSchemas(CallImpl.java:783)Got MSISDN null

            at org.jboss.ws.jaxrpc.CallImpl.invokeInternal(CallImpl.java:623)
            at org.jboss.ws.jaxrpc.CallImpl.invoke(CallImpl.java:398)

            From the doc of this api:

            An example request:

            <?xml version="1.0" encoding="ISO-8859-1"?>
            <SOAP-ENV:Envelope
            SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:si="http://soapinterop.org/xsd">
            <SOAP-ENV:Body>
            <ns1:TRANSLATEIP xmlns:ns1="http://testuri.org">
            <login.user xsi:type="xsd:string">K123456</login.user>
            <login.password xsi:type="xsd:string">XXXXX</login.password>
            <OriginatingCustomerIP xsi:type="xsd:string">129.23.23.2</OriginatingCustomerIP>
            </ns1:TRANSLATEIP>
            </SOAP-ENV:Body>
            </SOAP-ENV:Envelope>

            An example response looks the following way:

            <?xml version="1.0"?>
            <SOAP-ENV:Envelope
            xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/1999/XMLSchema"
            xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:si="http://soapinterop.org/xsd" xmlns:ns6="http://testuri.org" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <SOAP-ENV:Body>
            <Response>
            <item>
            <OriginatingCustomerId xsi:type="xsd:string">46736123123</OriginatingCustomerId>
            </item>
            </Response>
            </SOAP-ENV:Body>
            </SOAP-ENV:Envelope>


            I was able to implement this with Axis by doing like this:
             QName qn = new QName( XMLConstants.NULL_NS_URI, "item" );
             call.registerTypeMapping(Item.class, qn,
             new org.apache.axis.encoding.ser.BeanSerializerFactory(Item.class, qn),
             new org.apache.axis.encoding.ser.BeanDeserializerFactory(Item.class, qn));
             call.setReturnType(qn);
            

            plus that the Item class contains a type description like this:
             // Type metadata
             private static TypeDesc typeDesc = new TypeDesc(Item.class, true);
            
             static {
             typeDesc.setXmlType(new QName(XMLConstants.NULL_NS_URI, "item"));
             ElementDesc elemField = new ElementDesc();
             elemField.setFieldName("error");
             elemField.setXmlName(new javax.xml.namespace.QName("", "Error"));
             elemField.setXmlType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"));
             elemField.setNillable(true);
            
             typeDesc.addFieldDesc(elemField);
             elemField = new org.apache.axis.description.ElementDesc();
             elemField.setFieldName("originatingCustomerId");
             elemField.setXmlName(new javax.xml.namespace.QName("", "OriginatingCustomerId"));
             elemField.setXmlType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"));
             elemField.setNillable(true);
             typeDesc.addFieldDesc(elemField);
            
             elemField = new org.apache.axis.description.ElementDesc();
             elemField.setFieldName("transactionId");
             elemField.setXmlName(new javax.xml.namespace.QName("", "TransactionId"));
             elemField.setXmlType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"));
             elemField.setNillable(true);
             typeDesc.addFieldDesc(elemField);
            
             elemField = new org.apache.axis.description.ElementDesc();
             elemField.setFieldName("status");
             elemField.setXmlName(new javax.xml.namespace.QName("", "Status"));
             elemField.setXmlType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "int"));
             elemField.setNillable(true);
             typeDesc.addFieldDesc(elemField);
             }
            


            How to accomplish the same with jbossws?

            • 3. Re: DII client question
              Sverker Abrahamsson Novice

              The example soap request didn't show correctly. New try:

              An example request:
              
              <?xml version="1.0" encoding="ISO-8859-1"?>
              <SOAP-ENV:Envelope
              SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:si="http://soapinterop.org/xsd">
              <SOAP-ENV:Body>
              <ns1:TRANSLATEIP xmlns:ns1="http://testuri.org">
               <login.user xsi:type="xsd:string">K123456</login.user>
               <login.password xsi:type="xsd:string">XXXXX</login.password>
               <OriginatingCustomerIP xsi:type="xsd:string">129.23.23.2</OriginatingCustomerIP>
              </ns1:TRANSLATEIP>
              </SOAP-ENV:Body>
              </SOAP-ENV:Envelope>
              
              An example response looks the following way:
              
              <?xml version="1.0"?>
              <SOAP-ENV:Envelope
              xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
              xmlns:xsd="http://www.w3.org/1999/XMLSchema"
              xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:si="http://soapinterop.org/xsd" xmlns:ns6="http://testuri.org" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
              <SOAP-ENV:Body>
               <Response>
               <item>
               <OriginatingCustomerId xsi:type="xsd:string">46736123123</OriginatingCustomerId>
               </item>
               </Response>
              </SOAP-ENV:Body>
              </SOAP-ENV:Envelope>
              


              • 4. Re: DII client question
                Mylène Reiners Newbie

                 

                QName qn = new QName( "item" );


                I don't get why you want to make "item" a QName, it's just a simple tag...
                So, I suggest something like:

                call.addParameter("item", XMLType.XSD_STRING, ParameterMode.IN);
                (ofcourse you have to change the parameters)

                Success,

                Mylène




                • 5. Re: DII client question
                  Sverker Abrahamsson Novice

                  Hi Mylene
                  that was how I interpertated the javadoc for javax.xml.rpc.Call as the purpose is to set the type of the response to a Item object. Isn't what you suggest what I should do if I wanted to have item as a call parameter? I'll try it anyway and see what happens..

                  • 6. Re: DII client question
                    Mylène Reiners Newbie

                    Have a look at http://users.skynet.be/pascalbotte/rcx-ws-doc/dii.htm
                    He gives nice (working) examples, though not JBoss WS specific.

                    Mylène

                    • 7. Re: DII client question
                      Sverker Abrahamsson Novice

                      Unforturnatly that example still needs the wsdl when the service return an object..

                      This example shows how to do it on Weblogic:
                      http://www.manojc.com/?sample25

                      and earlier in the thread is an example on how to do it wil Axis. However, I can't find a way to do it with JBossWS :(