views:

2639

answers:

5

I am currently developing a Java app which handles a SOAP webservice.

The problem lies after I parse the WSDL [the Parser object from Apache Axis does it for me], and I create the call.

When I try to invoke it, I have to pass a Object[] to assign the parameters [taken from the Action of the WSDL]. A normal action is easy, but when I have custom datatypes, I can't get it to fill it out for me. I try to pass Object[]{ new Object { }}, but it assigns the first field instead. I can't pass it already processed, because it changes the '< >' to '--lt --gt', and the server doesn't recognize it'.

This is a fragment of the WSDL.

  <s:element name="FERecuperaQTYRequest">
    <s:complexType>
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="argAuth" type="tns:FEAuthRequest" />
      </s:sequence>
    </s:complexType>
  </s:element>
  <s:complexType name="FEAuthRequest">
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="1" name="Token" type="s:string" />
      <s:element minOccurs="0" maxOccurs="1" name="Sign" type="s:string" />
      <s:element minOccurs="1" maxOccurs="1" name="cuit" type="s:long" />
    </s:sequence>
  </s:complexType>

And this is the troublesome Java Fragment

        QTY = (String) call.invoke (
                new Object[]{
                     new Object[]{
                            tokenConexion.getToken (),
                            tokenConexion.getSign (),
                            tokenConexion.getCUIT ()
                                 }
                            });
+1  A: 

Have you looked into using something like Spring's proxy functionality? You tell it a bit about the webservice in a spring config file, and all your client code has to deal with is an interface that you create - it doesn't even have to know that there is a web service on the other side!

Example Spring config:

<bean id="myService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
 <property name="serviceFactoryClass" value="org.apache.axis.client.ServiceFactory"/>
 <property name="wsdlDocumentUrl" value="classpath://META-INF/myService.wsdl"/>
 <property name="namespaceUri" value="http://com/myService"/&gt;
 <property name="endpointAddress" value="http://server/MyService"/&gt;
 <property name="serviceName" value="MyService"/>
 <property name="portName" value="MyService"/>
 <property name="serviceInterface" value="com.IMyService"/>
 <property name="lookupServiceOnStartup" value="false"/>
</bean>
<bean id="myClient" class="com.MyServiceClient">
    <property name="myService" ref="myService"/>
</bean>

Java:

public interface IMyService {
    Foo getFoo();
}

public class MyServiceClient {
    private IMyService myService;
    public void setMyService(IMyService myService) {
     this.myService = myService;
    }

    public void DoStuff() {
     Foo foo = myService.getFoo();
     ...
    }
}

For custom objects, you may need to subclass JaxRpcPortProxyFactoryBean:

public class MyServiceFactoryBean extends JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
 TypeMappingRegistry registry = service.getTypeMappingRegistry();
 TypeMapping mapping = registry.createTypeMapping();
            QName qName = new QName("http://com/myService", "Foo");
 mapping.register(Foo.class, qName,
   new BeanSerializerFactory(Foo.class, qName),
   new BeanDeserializerFactory(Foo.class, qName));
    }
}

What I love about this is that code that shouldn't care about the implementation of the service doesn't. Testing becomes a breeze, and the cohesion of your classes is much better.

Chris Marasti-Georg
I would like not to add another framework to my simple application. Someone must have figured it out how to use axis invoke.
Manuel Ferreria
A: 

We tried to use complex objects and Axis. Don't! We had a bunch of problems with Dotnet being able to create a correct object from the WSDL. We ended up just using primitives, strings, and arrays. If someone has a good method of using complex object I would love to hear it.

Javamann
A: 

So far I think the solution might lie on serialization, yet I keep encountering the 'NoSerializerFound' even when I implement the io.Serializable.

Does anyone know if I can I override a method to tell it how to serialize it?

UPDATE: I might have to implement instead a few objects from org.apache.axis.encoding.ser. Anyone?

Manuel Ferreria
as defined in Java API for the Serializable interface you can override the way it is serialized by implementing private functions writeObject(java.io.ObjectOutputStream) and readObject(java.io.ObjectInputStream)
Vinze
A: 

i defined an Student bean with properties name,rno,m1,m2. i defined an StudentInt which takes Student as parameter do some computation and return Student object. i defined one StudentImpl class in which i have implemented StudentInt \

now how do a axis webservice for it plz provide information or atleiast link with this requirement.

anish
A: 

Just adding to this...

We have an issue with nested beans. Bean1 has an ArrayList of Bean2, which has an ArrayList of Bean3 On running our service I get an error telling me that we have an 'invalid element' listOfBean3 which is a param under Bean2.

Basically it would seem Axis can not see params in the child Beans only the parent Bean, is there a way around this?

KIPS