2 Replies Latest reply on Dec 1, 2009 10:02 AM by gwzoller

    Newbie: Empty ArrayList Passed on WS Call

    gwzoller

      Hello,

      I'm having some difficulty getting a list of things passed successfully as a web service parameter. A no-param, or simple (non-list) param works fine. My web service is an EJB stateless session bean...code below.

      The Interface:

      @Remote
      @WebService
      @SOAPBinding(style = SOAPBinding.Style.RPC)
      public interface OrderTakerRemote {
       @WebMethod
       public String msg(ArrayList<String> say);
      }


      The Implementation:
      @WebService(endpointInterface="com.kepler.ecom.services.OrderTakerRemote")
      @Stateless
      public class OrderTaker implements OrderTakerRemote {
      
       // Default constructor.
       public OrderTaker() {
       }
      
       public String msg(ArrayList<String> say) {
       StringBuffer sb = new StringBuffer();
       System.out.println(say.size()); // verify non-emtpy list
       if( say != null ) {
       sb.append("Hey you says ");
       for(String one : say ) {
       sb.append("\""+one+"\" ");
       }
       }
       return sb.toString();
       }
      }


      The Client:
       private void wsPlaceOrder() {
       String endpointURI ="http://127.0.0.1:8080/keplerEAR-kepler/OrderTaker?wsdl";
       try
       {
       ArrayList<String> stuff = new ArrayList<String>();
       stuff.add("One");
       stuff.add("Two");
       stuff.add("Three");
       this.wsOrderResult = (String) getPort(endpointURI).msg(stuff);
       } catch (MalformedURLException e) {
       e.printStackTrace();
       throw new RuntimeException(e);
       }
       }


      The ArrayList is clearly created and populated in the client. The call is made...no errors on the console..and I do get a result string back, but its just the little header "Hey you says"...not the rest of it. The console output from the implementation showing the received list size prints 0.

      Any ideas why my list isn't going over the wire?

      Thanks!
      Greg

        • 1. Re: Newbie: Empty ArrayList Passed on WS Call
          gwzoller

          Ok... I have 1/2 an answer. By playing with the annotations (brute force really) I can now get my list going over the wire, but... I lost my WSDL.

          New Interface:

          @WebService
          public interface OrderTakerRemote {
           public String msg(ArrayList<String> say);
          }
          


          New Impl:
          @Remote(OrderTakerRemote.class)
          @WebService(endpointInterface="com.kepler.ecom.services.OrderTakerRemote")
          @SOAPBinding(style = SOAPBinding.Style.RPC)
          @Stateless
          public class OrderTaker implements OrderTakerRemote {
          
           // Default constructor.
           public OrderTaker() {
           }
          
           @WebMethod
           public String msg(ArrayList<String> say) {
           // same as before
           }
          }


          I'd rather annotate the interface, not the implementation but to get it working it's a minor quibble.

          My larger problem is the WSDL. If I specify a simple @WebService (no endpoint parameter) in the impl then my WSDL looks something like this:
          <definitions name="OrderTakerService" targetNamespace="http://ecom.kepler..com/">
          -
          <types>
          -
          <xs:schema targetNamespace="http://ecom.kepler.com/" version="1.0">
          <xs:element name="msg" type="tns:msg"/>
          <xs:element name="msgResponse" type="tns:msgResponse"/>
          -
          <xs:complexType name="msg">
          -
          <xs:sequence>
          <xs:element maxOccurs="unbounded" minOccurs="0" name="arg0" type="xs:string"/>
          </xs:sequence>
          </xs:complexType>
          -
          <xs:complexType name="msgResponse">
          -
          <xs:sequence>
          <xs:element minOccurs="0" name="return" type="xs:string"/>
          </xs:sequence>
          </xs:complexType>
          </xs:schema>
          </types>
          -
          <message name="OrderTaker_msg">
          <part element="tns:msg" name="msg"/>
          </message>
          -
          <message name="OrderTaker_msgResponse">
          <part element="tns:msgResponse" name="msgResponse"/>
          </message>
          -
          <portType name="OrderTaker">
          -
          <operation name="msg" parameterOrder="msg">
          <input message="tns:OrderTaker_msg"/>
          <output message="tns:OrderTaker_msgResponse"/>
          </operation>
          </portType>
          -
          <binding name="OrderTakerBinding" type="tns:OrderTaker">
          <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
          -
          <operation name="msg">
          <soap:operation soapAction=""/>
          -
          <input>
          <soap:body use="literal"/>
          </input>
          -
          <output>
          <soap:body use="literal"/>
          </output>
          </operation>
          -
          <operation name="placeOrder_1_0">
          <soap:operation soapAction=""/>
          -
          <input>
          <soap:body use="literal"/>
          </input>
          -
          <output>
          <soap:body use="literal"/>
          </output>
          </operation>
          </binding>
          -
          <service name="OrderTakerService">
          -
          <port binding="tns:OrderTakerBinding" name="OrderTakerPort">
          <soap:address location="http://127.0.0.1:8080/keplerEAR-kepler/OrderTaker"/>
          </port>
          </service>
          </definitions>


          As shown in this code (with the endpoint parameter) my WSDL looks like this:
          <definitions name="OrderTakerService" targetNamespace="http://ecom.kepler.com/">
          <import location="http://127.0.0.1:8080/keplerEAR-kepler/OrderTaker?wsdl&resource=OrderTakerRemote_PortType8465038229007643058.wsdl" namespace="http://services.ecom.kepler.aviall.com/"/>
          -
          <service name="OrderTakerService">
          -
          <port binding="ns1:OrderTakerRemoteBinding" name="OrderTakerPort">
          <soap:address location="http://127.0.0.1:8080/keplerEAR-kepler/OrderTaker"/>
          </port>
          </service>
          </definitions>


          Somehow my Java client was fine with the abbreviated WSDL but I'm worried a non-Java client may need all the detail in the longer version. The annotation combo that gives me the longer (more complete?) WSDL doesn't let me pass my list. The short WSDL passes my list.

          Any ideas what's going on? What happened to all the stuff that defined the method calls and the parameter types?

          Any ideas appreciated! Confused newbie.
          Greg

          • 2. Re: Newbie: Empty ArrayList Passed on WS Call
            gwzoller

            Here's the rest of the story. I finally stumbled on the right recipe, and here 'tis. I was over-complicating things. Removing almost all the annotations fixed both the list-passing and the WSDL.

            Interface:

            import java.util.ArrayList;
            import javax.ejb.Remote; // for the EJB
            import javax.jws.WebService; // for the web service
            import com.kepler.ecom.domain.OrderLine;
            
            @Remote
            @WebService
            public interface OrderTakerRemote {
             public String msg(ArrayList<String> say);
            }


            Implementation:
            import javax.ejb.Stateless;
            import javax.jws.WebService;
            import com.aviall.kepler.ecom.domain.OrderLine;
            import com.aviall.kepler.ecom.services.OrderTakerRemote;
            import java.util.ArrayList;
            
            @WebService
            @Stateless
            public class OrderTaker implements OrderTakerRemote {
             public OrderTaker() {
             }
            
             public String msg(ArrayList<String> say) {
             // Use the list here
             }
            }