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

    Problems returning arrays from Webservice Method

    Erik Kazandjian Newbie

      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 Master

          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
            Erik Kazandjian Newbie

            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 Master

              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
                Marco Novice

                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
                  Erik Kazandjian Newbie

                  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
                    Erik Kazandjian Newbie

                    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 Master

                      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
                        Benjamin Seyinbour Expert

                        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>