8 Replies Latest reply on Nov 16, 2006 1:57 PM by ebross

    Problems returning arrays from Webservice Method

    kaza

      Hello,

      I have a simple Webservice with one method

      @WebMethod public ServiceWSArray getServiceInfos( Long serviceProviderId ) throws UnknownServiceProviderException;

      It returns a ServiceArray which in fact is a wrapper that contains ServiceWS elements. I generated my client stubs with wstools and it creates the ServiceWSArray as expected

      /*
      * JBossWS WS-Tools Generated Source
      *
      * Generation Date: Thu Oct 26 15:23:00 CEST 2006
      *
      * This generated source code represents a derivative work of the input to
      * the generator that produced it. Consult the input for the copyright and
      * terms of use that apply to this source code.
      */

      package com.siemens.ivon.soap.client;


      public class ServiceWSArray
      {

      protected com.siemens.ivon.soap.client.ServiceWS[] value;
      public ServiceWSArray(){}

      public ServiceWSArray(com.siemens.ivon.soap.client.ServiceWS[] value){
      this.value=value;
      }
      public com.siemens.ivon.soap.client.ServiceWS[] getValue() { return value ;}

      public void setValue(com.siemens.ivon.soap.client.ServiceWS[] value){ this.value=value; }

      }



      When I call the WS method from within a junit test I see the complete soap message comes in but the tests throws the following error. Can anybody help me and tell me what I'm doing wrong or is this a known bug. I'm using JBoss 4.0.4 GA with EJB3.

      Thanks

      Erik

      [junit] java.rmi.RemoteException: Call invocation failed: Java type 'class com.siemens.ivon.soap.client.ServiceWSArray' is not assignable from: [Lcom.siemens.ivon.soap.client.ServiceWS;; nested exception is:
      [junit] org.jboss.ws.WSException: Java type 'class com.siemens.ivon.soap.client.ServiceWSArray' is not assignable from: [Lcom.siemens.ivon.soap.client.ServiceWS;
      [junit] at org.jboss.ws.jaxrpc.CallImpl.invokeInternal(CallImpl.java:719)
      [junit] at org.jboss.ws.jaxrpc.CallImpl.invoke(CallImpl.java:398)
      [junit] at org.jboss.ws.jaxrpc.CallProxy.invoke(CallProxy.java:164)
      [junit] at $Proxy1.getServiceInfos(Unknown Source)
      [junit] at com.siemens.ivon.facade.soap.TestServiceSOAP.testGetServiceInfos(TestServiceSOAP.java:336)
      [junit] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      [junit] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      [junit] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      [junit] at java.lang.reflect.Method.invoke(Method.java:585)
      [junit] at junit.framework.TestCase.runTest(TestCase.java:164)
      [junit] at junit.framework.TestCase.runBare(TestCase.java:130)
      [junit] at junit.framework.TestResult$1.protect(TestResult.java:110)
      [junit] at junit.framework.TestResult.runProtected(TestResult.java:128)
      [junit] at junit.framework.TestResult.run(TestResult.java:113)
      [junit] at junit.framework.TestCase.run(TestCase.java:120)
      [junit] at junit.framework.TestSuite.runTest(TestSuite.java:228)
      [junit] at junit.framework.TestSuite.run(TestSuite.java:223)
      [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:289)
      [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:656)
      [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:558)
      [junit] Caused by: org.jboss.ws.WSException: Java type 'class com.siemens.ivon.soap.client.ServiceWSArray' is not assignable from: [Lcom.siemens.ivon.soap.client.ServiceWS;
      [junit] at org.jboss.ws.soap.SOAPContentElement.getObjectValue(SOAPContentElement.java:299)
      [junit] at org.jboss.ws.binding.EndpointInvocation.transformPayloadValue(EndpointInvocation.java:233)
      [junit] at org.jboss.ws.binding.EndpointInvocation.getReturnValue(EndpointInvocation.java:182)
      [junit] at org.jboss.ws.jaxrpc.CallImpl.syncOutputParams(CallImpl.java:871)
      [junit] at org.jboss.ws.jaxrpc.CallImpl.invokeInternal(CallImpl.java:706)
      [junit] ... 19 more



        • 1. Re: Problems returning arrays from Webservice Method
          jason.greene

          Can you file create a simple example/test case of this and open a jira issue? We will take a look at it.

          http://jira.jboss.com

          -Jason


          • 2. Re: Problems returning arrays from Webservice Method
            kaza

            Sorry Jason, but I don't know exactly what you mean by "jira issue" but here is my server code and a snippet of a junit test that tries to access this (I simplified things a bit to focus on the problem)

            First of all my ServiceWS class

            public class ServiceWS {
            private Long id;
            private String name;

            public Long getId(){ return this.id;}
            public void setId(Long id) {this.id = id;}
            public String getName(){return this.name;};
            public void setName(String name){this.name=name;}
            }

            Then there is the ServiceWSArray class

            public class ServiceWSArray {
            private ServiceWS[] value;

            public ServiceWSArray() {
            }

            public ServiceWS[] getValue() {
            return this.value;
            }

            public void setValue(ServiceWS[] value) {
            this.value = value;
            }
            }

            And finally there is my webservice endpoint

            @Stateless
            @WebService(serviceName="MyWebService")
            @SOAPBinding(style=Style.RPC,use=Use.LITERAL)
            public class FacadeWS {

            @WebMethod public ServiceWSArray getServiceInfos()
            throws UnknownServiceProviderException {

            if (this.logger.isTraceEnabled())
            this.logger.trace("SOAP:getServiceInfos");

            ServiceWS[] services = new ServiceWS[10];
            for (int i=0;i<10;i++)
            services = new ServiceWS.fromService();

            ServiceWSArray result = new ServiceWSArray();
            result.setValue(services);

            return result;
            }
            }


            On the junit client I create the port to this service and just call this

            this.getPort().getServiceInfos();

            • 3. Re: Problems returning arrays from Webservice Method
              jason.greene

              Jira is our bug reporting system. I created a report for you. It is located here for you to monitor/vote on.

              http://jira.jboss.com/jira/browse/JBWS-1318

              -Jason

              • 4. Re: Problems returning arrays from Webservice Method
                mmarcom

                Hello,
                had same problem with arrays..
                was able to fix it by specifying WebResult and WebParam in my webservice methods..
                As far as i read, the less you annotate your webservice method, the more jbossws will try to 'figure out' what the parameters/result would be..
                No problem with primitive/wrappres return, but if you start to have 'arrays' or custom classes, then i guess jbossws would need a little help in order to generate WSDL etc..

                You'd need to annotate your webservice method with
                @WebResult
                @WebParam

                check jbossws samples, (or google it) i have found a similar example that uses WebParam and WebREsult and that fixed my problem

                HTH
                marco

                try to speci

                • 5. Re: Problems returning arrays from Webservice Method
                  kaza

                  Sorry Marco,

                  I downloaded all the samples and I did not find one that had @WebResult in it. I also annotated my method with WebResult but that did not change my WSDL at all and so my test still fails . Can you send me some sample code where and how you use this annotation. I'm trying to return an array not sending one in a parameter.

                  Thanks

                  Erik

                  • 6. Re: Problems returning arrays from Webservice Method
                    kaza

                    I have changed the code in SOAPContentElement that deals with the array part. The original code says

                    if (obj != null)
                    {
                    Class objType = obj.getClass();
                    boolean isAssignable = JavaUtils.isAssignableFrom(javaType, objType);
                    if (isAssignable == false && javaType.isArray())
                    {
                    try
                    {
                    Method toArrayMethod = objType.getMethod("toArray", new Class[] {});
                    Class returnType = toArrayMethod.getReturnType();
                    if (JavaUtils.isAssignableFrom(javaType, returnType))
                    {
                    Method getValueMethod = objType.getMethod("getValue", new Class[] {});
                    Object value = getValueMethod.invoke(obj, new Object[] {});
                    if (value != null)
                    {
                    // Do not invoke toArray if getValue returns null
                    obj = toArrayMethod.invoke(obj, new Object[] {});
                    }
                    else
                    {
                    // if the fragment did not indicate a null return
                    // by an xsi:nil we return an empty array
                    Class componentType = javaType.getComponentType();
                    obj = Array.newInstance(componentType, 0);
                    }
                    isAssignable = true;
                    }
                    }
                    catch (Exception e)
                    {
                    // ignore
                    }
                    }


                    I think it is better to look to the object that was deserialized to decide wether this is an array. If it turns out to be an array then look for a setter method that takes this array class as argument. If that exists set its value. I think this way of unmarshalling fits better to the way the client artifacts are generated by wstools. This is my version of the code

                    if (obj != null) {
                    Class objType = obj.getClass();
                    boolean isAssignable = JavaUtils.isAssignableFrom(javaType, objType);
                    if (isAssignable == false && objType.isArray()) { // Changed
                    try {
                    log.debug("Try to locate setValue method "+javaType);
                    Method setValueMethod = javaType.getMethod("setValue", new Class[] {objType});
                    log.debug("Try to create new instance for "+javaType);
                    Object newInstance = javaType.newInstance();
                    log.debug("Try to invoke setValueMethod ");
                    setValueMethod.invoke(newInstance, new Object[] {obj});
                    isAssignable = true;
                    obj = newInstance;
                    } catch (Exception e) {
                    e.printStackTrace();
                    }
                    }


                    Erik

                    • 7. Re: Problems returning arrays from Webservice Method
                      thomas.diesler

                      For this fix not to get lost we'll need a jira issue with the patch + test case (modificatipon) attached.

                      cheers

                      • 8. Re: Problems returning arrays from Webservice Method
                        ebross

                        The questions is whether jbossw do collection or array AND the answer is NO Take a look at the following line from jbossAS console output:

                        18:47:51,328 WARN [SchemaTypeCreator] JAX-RPC does not allow collection types skipping: com.xxxx.yyy.zzz..Users.roles


                        where roles is a List<RolesBean>