Reputation: 1232
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 ()
}
});
Upvotes: 1
Views: 7761
Reputation: 2912
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.
Upvotes: 0
Reputation: 34650
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"/>
<property name="endpointAddress" value="http://server/MyService"/>
<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.
Upvotes: 1