Announcement Announcement Module
Collapse
No announcement yet.
Web Service return String[] Problem Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Web Service return String[] Problem

    I'm using Spring's JaxRpcPortProxyFactoryBean for consuming a web service. The web service has a function that returns an array of Strings and I get the following ClassCastException when I call this function through the service proxy generated by JaxRpcPortProxyFactoryBean.
    The signature of the function is:
    Code:
    String[] getPrioritiesList();
    The error:
    Code:
    java.lang.String
    java.lang.ClassCastException: java.lang.String
            at $Proxy0.getPrioritiesList(Unknown Source)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at org.springframework.remoting.rmi.RmiClientInterceptorUtils.doInvoke(RmiClientInterceptorUtils.java:103)
            at org.springframework.remoting.rmi.RmiClientInterceptorUtils.invoke(RmiClientInterceptorUtils.java:71)
            at org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.invoke(JaxRpcPortClientInterceptor.java:442)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
            at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
            at $Proxy1.getPrioritiesList(Unknown Source)
            at helpdeskws.HelpDeskServiceImplTest.testGetPrioritiesList(HelpDeskServiceImplTest.java:154)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    Note that when I call this function through the NetBeans web service invoker, it works fine. So the problem is not in the Web Service.

  • #2
    Do I need to register a serializer and deserializer for the String[] class in Spring JaxRpcServicePostProcessor?
    Has anyone been able to access web services that return arrays with Spring's JaxRpcPortProxyFactoryBean?
    Any ideas?

    Comment


    • #3
      I did some more experimentation with this. I found that if I change the web service type to rpc/encoded everything works, but I really need the web service to be wrapped/literal.

      Also, the error I'm getting now is:

      Code:
      java.util.ArrayList
      java.lang.ClassCastException: java.util.ArrayList
              at $Proxy0.getPrioritiesList(Unknown Source)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at org.springframework.remoting.rmi.RmiClientInterceptorUtils.doInvoke(RmiClientInterceptorUtils.java:103)
              at org.springframework.remoting.rmi.RmiClientInterceptorUtils.invoke(RmiClientInterceptorUtils.java:71)
              at org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.invoke(JaxRpcPortClientInterceptor.java:442)
              at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
              at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
              at $Proxy1.getPrioritiesList(Unknown Source)
              at helpdeskws.HelpDeskServiceImplTest.testGetPrioritiesList(HelpDeskServiceImplTest.java:206)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

      Comment


      • #4
        The problem seems to be that your proxy declares the affected method with return value String[], while the underlying RMI stub seems to declare the method with return value String.

        Double-check your service interface - "serviceInterface" on JaxRpcPortProxyFactoryBean; the interface that your proxy exposes - and your port interface - "portInterface" on JaxRpcPortProxyFactoryBean; the interface returned by the underlying Web Service provider. They need to be in sync in every respect other than the exception thrown.

        Alternatively, consider not specifying the port interface in the first place. JaxRpcPortProxyFactoryBean will then use the JAX-RPC Dynamic Invocation API straight from your service proxy. This might expose different behavior, depending on your Web Service provider.

        Juergen

        Comment


        • #5
          Juergen,

          I've checked the serviceInterface and the portInterface and they are in sync. I've also tried not specifying portInterface to no avail.

          Note that the error that I'm now getting is ArrayList casting exception:

          Code:
          java.util.ArrayList
          java.lang.ClassCastException: java.util.ArrayList
          Since this is not working, I'm considering an alternative to using the JaxRpcPortProxyFactoryBean. I'm thinking of using the web service client stubs that Axis generates using the wsdl2java tool. However, the problem here is that I want to get a bean that will implement the serviceInterface, but the stub that Axis generates implemetns the remoteInterface.
          Let say you have the following:
          Code:
          interface Service
          {
           void f();
          }
          interface RemoteService extends Remote
          {
           void f() throws RemoteException;
          }
          class RemoteServiceImpl implements RemoteService
          {
           void f() throws RemoteExcpetion { throw new RemoteException(); }
          }
          I need a bean factory that will take RemoteServiceImpl and return an implementation of the Service interface. Is this possible?

          Comment


          • #6
            I've just re-analyzed your stacktrace: It's actually the proxy for the low-level RMI stub that causes the ClassCastException. I assume you're running on JDK 1.5, where RMI uses dynamic proxies for its stubs itself. I haven't considered that at first.

            To verify this, you could try to use the JAX-RPC API directly: create a JAX-RPC Service, retrieve the corresponding JAX-RPC port and pass the RMI interface in. I would expect that you get the same ClassCastException there. This is a problem within the JAX-RPC provider, not within Spring's JaxRpcPortProxyFactoryBean.

            It seems that your Web Service call actually returns an ArrayList, while your port interface declares a String[] as return value. This looks like your JAX-RPC provider does not support automatic conversion of such arguments. Try to declare the return value of your service and port interfaces as java.util.List and see whether it works then.

            If you generate the stubs with some WSDL2java tool, I would expect the generated port interface to declare List or ArrayList as return value there. The JAX-RPC provider seems to deserialize an ArrayList, according to your WSDL definition, so I would expect it to generate a corresponding port interface through its tools.

            Juergen

            Comment


            • #7
              I want to emphasize that this ClassCastException only occurs when I make the web service wrapped/literal as opposed to rpc/encoded. With the rpc/encoded style everything works fine with JaxRpcPortProxyFactoryBean and the String[] is returned correctly.

              Also, with wrapped/literal style turned on, the wsdl2java tool generates stubs that declare a String[] as a return value (not ArrayList) and using the stubs it works with no problems. Only when I try to use this web service in wrapped/literal style through JaxRpcPortProxyFactoryBean that I get the error.

              Perhaps, it's a problem with the JAX-RPC implementation for which I'm using Axis, but then why do the stubs that Axis generates which use the same JAX-RPC implementation work fine?

              Comment


              • #8
                Well, it might an issue with the JAX-RPC provider's dynamic proxy support: the "javax.xml.rpc.Service" API, in particular the "getPort" method exposed there which allows to retrieve a dynamic proxy for a target port. This is a standard facility defined by JAX-RPC, as alternative to static proxy generation.

                You could try to create a dynamic port proxy through standard JAX-RPC. I would expect that this would result in the ClassCastException as well - simply because Spring's JaxRpcPortProxyFactoryBean is using the very same JAX-RPC API underneath. And your stacktrace clearly indicates that the ClassCastException happens in the dynamic JAX-RPC proxy created by Axis, not in JaxRpcPortProxyFactoryBean itself.

                Juergen

                Comment


                • #9
                  You are right. I've tried creating a dynamic port proxy through JAX-RPC and indeed I get the exactly same ClassCastException. So the problem is in Axis not in JaxRpcPortProxyFactoryBean.
                  Does anyone know a workaround for this?

                  Comment


                  • #10
                    I've just encountered this problem myself, using Axis 1.3 on the client.

                    I've created an issue at the Axis JIRA:
                    https://issues.apache.org/jira/browse/AXIS-2393

                    Comment

                    Working...
                    X