type mismatch on SOAP Web Service method invocation
When I run the generated client for a web service, I get the following error, which I can get rid of by using a primitive type (e.g. String) as the parameter to doSomething instead of wstest.test2.APIClass3, i.e. the SOAP server seems happy handling wstest.test2.APIClass1 as a return type, but not a similar class as a parameter type:
[SOAPException: faultCode=SOAP-ENV:Server; msg=type mismatch [java.lang.IllegalArgumentException]]
wstest.test2.APIClass1 wstest.test2.EmbeddedStatelessTest2Stub.doSomething(wstest.test2.APIClass3)
EmbeddedStatelessTest2Stub.java:89
void wstest.test2.EmbeddedStatelessTest2Stub.main(java.lang.String[])
EmbeddedStatelessTest2Stub.java:48
I am using JDeveloper9i 9.0.3 Preview and the standalone OC4J 9.0.3 that came with it. I followed the Oracle9i JDeveloper 9.0.3 Web Services Quickstart Install (http://otn.oracle.com/tech/webservices/htdocs/quickstart/quickstart903.html) to get OC4J running standalone. I had to register the stateless EJB provider, and the WEB services wizard didn't manage to include APIClass2 (an instance of which is contained in APIClass1) in the .dd so I added it manually which works fine with APIClass1 as the method return type.
Sorry for the length of this posting, but I wasn't sure which bits would be relevant.
WSDL
====
<?xml version = '1.0' encoding = 'windows-1252'?>
<!--Generated by the Oracle9i JDeveloper Web Services WSDL Generator-->
<!--Date Created: Wed Sep 11 15:54:08 BST 2002-->
<definitions
name="StatelessTest2"
targetNamespace="http://wstest/test2/StatelessTest2.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://wstest/test2/StatelessTest2.wsdl"
xmlns:ns1="http://wstest.test2/IStatelessTest2.xsd">
<types>
<schema
targetNamespace="http://wstest.test2/IStatelessTest2.xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<complexType name="wstest_test2_APIClass3" jdev:packageName="wstest.test2" xmlns:jdev="http://xmlns.oracle.com/jdeveloper/webservices">
<all>
<element name="Name" type="string"/>
<element name="Value" type="double"/>
</all>
</complexType>
<complexType name="wstest_test2_APIClass1" jdev:packageName="wstest.test2" xmlns:jdev="http://xmlns.oracle.com/jdeveloper/webservices">
<all>
<element name="Name" type="string"/>
<element name="Value" type="double"/>
<element name="APIClass2" type="ns1:wstest_test2_APIClass2"/>
</all>
</complexType>
<complexType name="wstest_test2_APIClass2" jdev:packageName="wstest.test2" xmlns:jdev="http://xmlns.oracle.com/jdeveloper/webservices">
<all>
<element name="IntegerValue" type="int"/>
<element name="DoubleValue" type="double"/>
<element name="Name" type="string"/>
</all>
</complexType>
</schema>
</types>
<message name="doSomething0Request">
<part name="p0" type="ns1:wstest_test2_APIClass3"/>
</message>
<message name="doSomething0Response">
<part name="return" type="ns1:wstest_test2_APIClass1"/>
</message>
<portType name="StatelessTest2PortType">
<operation name="doSomething">
<input name="doSomething0Request" message="tns:doSomething0Request"/>
<output name="doSomething0Response" message="tns:doSomething0Response"/>
</operation>
</portType>
<binding name="StatelessTest2Binding" type="tns:StatelessTest2PortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="doSomething">
<soap:operation soapAction="" style="rpc"/>
<input name="doSomething0Request">
<soap:body use="encoded" namespace="wstest.test2.StatelessTest2" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="doSomething0Response">
<soap:body use="encoded" namespace="wstest.test2.StatelessTest2" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="StatelessTest2">
<port name="StatelessTest2Port" binding="tns:StatelessTest2Binding">
<soap:address location="http://localhost:8888/soap/servlet/soaprouter"/>
</port>
</service>
</definitions>
Deployment Decriptor
====================
<?xml version = '1.0' encoding = 'windows-1252'?>
<!--Generated by the Oracle9i JDeveloper Web Services Deployment Descriptor Generator-->
<!--This Deployment Descriptor file is for use with the Oracle9iAS Release 2 / Apache 2.2 SOAP Server SOAP Server-->
<!--Date Created: Wed Sep 11 15:54:09 BST 2002-->
<isd:service
id="wstest.test2.StatelessTest2"
type="rpc"
xmlns:isd="http://xmlns.oracle.com/soap/2001/04/deploy/service">
<isd:provider
id="stateless-ejb-provider"
methods="doSomething"
scope="Request">
<isd:option key="JNDILocation" value="StatelessTest2"/>
<isd:option key="DeploymentName" value="StatelessTest2"/>
</isd:provider>
<isd:faultListener
class="org.apache.soap.server.DOMFaultListener"/>
<isd:mappings>
<isd:map
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="http://wstest.test2/IStatelessTest2.xsd"
qname="x:wstest_test2_APIClass1"
javaType="wstest.test2.APIClass1"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
<isd:map
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="http://wstest.test2/IStatelessTest2.xsd"
qname="x:wstest_test2_APIClass2"
javaType="wstest.test2.APIClass2"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
<isd:map
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="http://wstest.test2/IStatelessTest2.xsd"
qname="x:wstest_test2_APIClass3"
javaType="wstest.test2.APIClass3"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
</isd:mappings>
</isd:service>
StatelesTest2.java
==================
package wstest.test2;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface StatelessTest2 extends EJBObject {
/*
* @webmethod
*/
APIClass1 doSomething(APIClass3 p0) throws RemoteException;
}
StatelessTest2Bean.java
=======================
package wstest.test2.impl;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import wstest.test2.APIClass1;
import wstest.test2.APIClass2;
import wstest.test2.APIClass3;
public class StatelessTest2Bean implements SessionBean {
public void ejbCreate() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
}
public void setSessionContext(SessionContext ctx) {
}
public APIClass1 doSomething(APIClass3 p0) {
APIClass1 ac1 = new APIClass1();
ac1.setName(p0.getName() + "1");
ac1.setValue(p0.getValue());
APIClass2 ac2 = ac1.getAPIClass2();
ac2.setName(p0.getName() + "2");
ac2.setIntegerValue(new Integer(ac1.getValue().intValue()));
ac2.setDoubleValue(new Double(ac1.getValue().doubleValue() * 2.0));
return ac1;
}
}
EmbeddedStatelessTest2Stub.java
===============================
I change the http port from 8988 to 8888 to get this working. Also, the generated referenced a new class APIClass31, also generated, but as it didn't make any difference to the problem I replaced it with APIClass3, which has essentially the same characteristics.
package wstest.test2;
import oracle.soap.transport.http.OracleSOAPHTTPConnection;
import org.apache.soap.encoding.soapenc.BeanSerializer;
import org.apache.soap.encoding.SOAPMappingRegistry;
import org.apache.soap.util.xml.QName;
import java.net.URL;
import org.apache.soap.Constants;
import org.apache.soap.Fault;
import org.apache.soap.SOAPException;
import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
import wstest.test2.*;
import java.util.Vector;
import java.util.Properties;
import wstest.test2.APIClass1;
import wstest.test2.APIClass2;
import wstest.test2.APIClass3;
/**
* Generated by the Oracle9i JDeveloper Web Services Stub/Skeleton Generator.
* Date Created: Wed Sep 11 15:41:19 BST 2002
* WSDL URL: file:/C:/Projects/WSTest/Test2/src/wstest/test2/StatelessTest2.wsdl
*/
public class EmbeddedStatelessTest2Stub
{
public EmbeddedStatelessTest2Stub()
{
m_httpConnection = new OracleSOAPHTTPConnection();
m_smr = new SOAPMappingRegistry();
BeanSerializer beanSer = new BeanSerializer();
m_smr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("http://wstest.test2/IStatelessTest2.xsd", "wstest_test2_APIClass1"), wstest.test2.APIClass1.class, beanSer, beanSer);
m_smr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("http://wstest.test2/IStatelessTest2.xsd", "wstest_test2_APIClass2"), wstest.test2.APIClass2.class, beanSer, beanSer);
m_smr.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("http://wstest.test2/IStatelessTest2.xsd", "wstest_test2_APIClass3"), wstest.test2.APIClass3.class, beanSer, beanSer);
}
public static void main(String[] args)
{
try
{
EmbeddedStatelessTest2Stub stub = new EmbeddedStatelessTest2Stub();
// Add your own code here.
APIClass3 ac3 = new APIClass3();
ac3.setName("fred");
ac3.setValue(new Double(17.36));
printAPIClass3("Input", ac3);
APIClass1 retAc1 = stub.doSomething(ac3);
printAPIClass1("Return", retAc1);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public String endpoint = "http://172.25.1.176:8888/soap/servlet/soaprouter";
private OracleSOAPHTTPConnection m_httpConnection = null;
private SOAPMappingRegistry m_smr = null;
public APIClass1 doSomething(APIClass3 p0) throws Exception
{
APIClass1 returnVal = null;
URL endpointURL = new URL(endpoint);
Call call = new Call();
call.setSOAPTransport(m_httpConnection);
call.setTargetObjectURI("wstest.test2.StatelessTest2");
call.setMethodName("doSomething");
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
Vector params = new Vector();
params.addElement(new Parameter("p0", wstest.test2.APIClass3.class, p0, null));
call.setParams(params);
call.setSOAPMappingRegistry(m_smr);
Response response = call.invoke(endpointURL, "");
if (!response.generatedFault())
{
Parameter result = response.getReturnValue();
returnVal = (APIClass1)result.getValue();
}
else
{
Fault fault = response.getFault();
throw new SOAPException(fault.getFaultCode(), fault.getFaultString());
}
return returnVal;
}
private static void printAPIClass3(String prefix, APIClass3 ac3)
{
System.out.println(prefix + ": [" + ac3.getName() + ", " + ac3.getValue() + "]");
}
private static void printAPIClass1(String prefix, APIClass1 ac1)
{
APIClass2 ac2 = ac1.getAPIClass2();
System.out.println(prefix + ": [" + ac1.getName() + ", " + ac1.getValue() + " ["
+ ac2.getName() + ", " + ac2.getIntegerValue() + ", " + ac2.getDoubleValue()
+ "]]");
}
public void setMaintainSession(boolean maintainSession)
{
m_httpConnection.setMaintainSession(maintainSession);
}
public boolean getMaintainSession()
{
return m_httpConnection.getMaintainSession();
}
public void setTransportProperties(Properties props)
{
m_httpConnection.setProperties(props);
}
public Properties getTransportProperties()
{
return m_httpConnection.getProperties();
}
}
APIClass1.java
==============
package wstest.test2;
import java.io.Serializable;
public class APIClass1 implements Serializable {
private String name;
private Double value;
private APIClass2 apiClass2;
public APIClass1() {
name = new String("");
value = new Double(0.0);
apiClass2 = new APIClass2();
}
public String getName() {
return name;
}
public void setName(String newName) {
name = new String(newName);
}
public Double getValue() {
return value;
}
public void setValue(Double newValue) {
value = new Double(newValue.doubleValue());
}
public APIClass2 getAPIClass2() {
return apiClass2;
}
public void setAPIClass2(APIClass2 newAPIClass2) {
apiClass2 = new APIClass2();
apiClass2.setName(newAPIClass2.getName());
apiClass2.setDoubleValue(newAPIClass2.getDoubleValue());
apiClass2.setIntegerValue(newAPIClass2.getIntegerValue());
}
}
APIClass2.java
==============
package wstest.test2;
import java.io.Serializable;
public class APIClass2 implements Serializable {
private String name;
private Integer iVal;
private Double dVal;
public APIClass2() {
iVal = new Integer(0);
dVal = new Double(0.0);
name = new String("");
}
public Integer getIntegerValue() {
return iVal;
}
public void setIntegerValue(Integer newIVal) {
iVal = new Integer(newIVal.intValue());
}
public Double getDoubleValue() {
return dVal;
}
public void setDoubleValue(Double newDoubleValue) {
dVal = new Double(newDoubleValue.doubleValue());
}
public String getName() {
return name;
}
public void setName(String newName) {
name = new String(newName);
}
}
APIClass3.java
==============
package wstest.test2;
import java.io.Serializable;
public class APIClass3 implements Serializable {
private String name;
private Double value;
public APIClass3() {
}
public String getName() {
return name;
}
public void setName(String newName) {
name = new String(newName);
}
public Double getValue() {
return value;
}
public void setValue(Double newValue) {
value = new Double(newValue.doubleValue());
}
}
APIClass31.java
===============
package wstest.test2;
/**
* Generated by the Oracle9i JDeveloper Web Services Stub/Skeleton Generator.
* Date Created: Wed Sep 11 10:44:56 BST 2002
*
* <pre>
* <complexType name="wstest_test2_APIClass3" jdev:packageName="wstest.test2" xmlns:jdev="http://xmlns.oracle.com/jdeveloper/webservices">
* <all>
* <element name="Name" type="string"/>
* <element name="Value" type="double"/>
* </all>
* </complexType>
* </pre>
*/
public class APIClass31 {
private String m_Name;
private Double m_Value;
public APIClass31() {
}
public APIClass31(String Name, Double Value) {
m_Name = Name;
m_Value = Value;
}
public void setName(String Name) {
m_Name = Name;
}
public String getName() {
return m_Name;
}
public void setValue(Double Value) {
m_Value = Value;
}
public Double getValue() {
return m_Value;
}
}