You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wsif-user@ws.apache.org by Ahab Abouzour <ea...@yahoo.com> on 2005/03/10 18:51:57 UTC

complex types (from raw XML) and WSIF

Hello all,

I'm using wsif v2.0 (with its own lib distribution,
e.g. axis-1_0.jar, although axis 1.1 is now
available). I'm trying to invoke a web service that
takes a complex type as an input and returns a complex
type as an output.

My wsif application receives the (complex type) input
parameter as raw XML (serialized form already). What I
did is create a wrapper class that can represent any
complex type and I map the complex types to my wrapper
class. My wrapper class has public static methods
called getSerializer/getDeserializer (which is
dependents on axis specifically, I'm not sure if I
like that!) that gets called by wsif (or the provider
underneath it). These serializer/deserializer classes
are my problem! I did read some threads in the mailing
list with similar idea but they didn't get into the
details of the serializer and the deserializer classes
which I'm having problems with.

The problem I'm having with the serializer, for
example, is that my wrapper class wraps raw XML
representation of the complex type class. When my
serializer gets called, all I want to do is return the
raw xml that represents my complex type. I don't seem
to find a way to so!! The serialize method prototype
is like this:
public void serialize(QName name,
                    Attributes attributes,
                    Object value,
                    SerializationContext context)
I'm supposed to "fill" the SerializationContext with
raw XML "somehow"?! I couldn't find anything in the
SerializationContext API how to do this? Is this
possible? Also when I print the name (QName
parameter), I get "multiRef"! Which doesn't make too
much sense because I should see my complex type
wrapper class name there since it's the one that is
mapped for the input complex parameter! Also, if you
make the serializer create an element (just for
testing), the generated SOAP element (when you look at
the generated SOAP request using a TCP/IP monitor)
will have the generated XML element (from my 
serializer) located parallel to the input parameter,
when it should be INSIDE the input parameter element
as value of its fields! I don't know if this is a bug
in wsif?
Similarly with the deserializer, which extends
DeserializerImpl, which ever method you override
(onStartElement, or onStartChild), you get passed a
DeserializationContext that I'm not sure how I can
retrieve the raw xml directly out of. I had a little
bit of success in that one, where I retrieved the SOAP
envelope, then the body, then I got the child element
of the body and wrote it toString. This gave me raw
xml. But you have to be careful here, this might not
work if there is more than one returned value (e.g. a
return complex type and more than one out parameter).

So the question is it possible to convert from/to XML
<--> serialization/deserializationContext? if yes, can
you please provide an example or how to do it?
I've copied the code below, the result of the run and
the saop request that was generated.

I hope these issue are dealt with in post wsif 2.0
releases. When is the next gen WSIF "SDI" is scheduled
to release?

Thanks.

public class IAComplexType  implements
java.io.Serializable {

    public IAComplexType() {
	System.out.println("IAComplexType() constructor
called");
    }

    public synchronized boolean
equals(java.lang.Object obj) {
	System.out.println("equals() called");
	return true;
    }

    public synchronized int hashCode() {
	System.out.println("hashCode() called");
	return 1;
    }

    // Type metadata
    private static
org.apache.axis.description.TypeDesc typeDesc =
        new
org.apache.axis.description.TypeDesc(IAComplexType.class);

    public String getValue(){
	return rawSoap;
    }

    public void setValue(String rawsoap){
	rawSoap = rawsoap;
    }

    public String getPartName(){
	return partName;
    }

    public void setPartName(String name){
	partName = name;
    }

    /**
     * Return type metadata object
     */
    public static org.apache.axis.description.TypeDesc
getTypeDesc() {
	System.out.println("getTypeDesc() called");
        return typeDesc;
    }

    /**
     * Get Custom Serializer
     */
    public static org.apache.axis.encoding.Serializer
getSerializer(
           java.lang.String mechType, 
           java.lang.Class _javaType,  
           javax.xml.namespace.QName _xmlType) {

	System.out.println("getSerializer() called. mechType:
"+mechType+", _javaType: "+_javaType.getName()+",
QName: "+_xmlType.toString());
        return new IAComplexTypeSerializer();
    }

    /**
     * Get Custom Deserializer
     */
    public static
org.apache.axis.encoding.Deserializer getDeserializer(
           java.lang.String mechType, 
           java.lang.Class _javaType,  
           javax.xml.namespace.QName _xmlType) {

	System.out.println("getDeserializer() called.
mechType: "+mechType+", _javaType:
"+_javaType.getName()+", QName:
"+_xmlType.toString());
        return new IAComplexTypeDeserializer();
    }

    String rawSoap = "";
    String partName = "";
}


import
org.apache.axis.encoding.DeserializationContext;
import org.xml.sax.Attributes;
import org.apache.axis.encoding.DeserializerImpl;
import org.apache.axis.message.SOAPEnvelope;
import java.util.Vector;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import java.util.Iterator;
import org.apache.axis.message.SOAPBodyElement;

public class IAComplexTypeDeserializer extends
DeserializerImpl {

    public IAComplexTypeDeserializer()
    {
	System.out.println("IAComplexTypeDeserializer
constructor called");
	value = new IAComplexType();
    }

    public void onStartElement(String namespace,
    				String localName,
                              	String qName,
				Attributes attributes,
			      	DeserializationContext context)
    {
	try
	{
	    SOAPEnvelope envelope = context.getEnvelope();
	    SOAPBody body = envelope.getBody();
	    Iterator it = body.getChildElements();
	    SOAPBodyElement bodyElement = new
SOAPBodyElement();//empty
	    //TODO:
	    //1- find out if the element is really complex
type or not?
	    //2- handle more than one complex element
	    while ( it.hasNext() ){
		bodyElement = (SOAPBodyElement)it.next();
	    }
	    ((IAComplexType)value).setValue(
bodyElement.toString() );

	}catch(Exception s){
	    s.printStackTrace();
	}
    }
}

import org.apache.axis.encoding.Serializer;
import org.apache.axis.Constants;
import org.apache.axis.encoding.SerializationContext;
import org.apache.axis.wsdl.fromJava.Types;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import javax.xml.namespace.QName;
import java.io.IOException;
import org.apache.axis.Message;
import org.apache.axis.message.SOAPEnvelope;
import java.io.ByteArrayInputStream;
import org.apache.axis.message.SOAPBodyElement;
import javax.xml.soap.SOAPBody;
import java.util.Iterator;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPException;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class IAComplexTypeSerializer implements
Serializer {

    public IAComplexTypeSerializer()
    {
	System.out.println("IAComplexTypeSerializer
constructor called");
    }

    public String getMechanismType() { return
Constants.AXIS_SAX; }

    public void printTagInfo(SOAPBodyElement elm){
	Name childName = elm.getElementName();
	String localName = childName.getLocalName();
	System.out.println("Tag localname is: "+localName);
    }

    public void serialize(QName name,
    			Attributes attributes,
                        Object value,
			SerializationContext context)
	throws IOException
    {
	System.out.println("serialize called");
	System.out.println("Qname LocalPart:
"+name.getLocalPart()+" namespace:
"+name.getNamespaceURI()+" ");
	System.out.println("attributes: "+attributes);
	System.out.println("Object: "+value);
	IAComplexType myObj = (IAComplexType)value;

	//NOTE: don't know how to give context the raw xml
(from myObj.getValue())!
	//      this is just a sample filler!
	context.startElement(name,attributes);
	context.serialize(new QName("", "varString"), null,
new String("Hello"));
	context.serialize(new QName("", "varInt"), null, new
Integer(10));
	context.serialize(new QName("", "varFloat"), null,
new Float(1.23));
	context.endElement();
    }

    public Element writeSchema(Class javaType, Types
types)
    	throws Exception
    {
	return null;
    }

    public boolean
writeSchema(org.apache.axis.wsdl.fromJava.Types types)
    	throws Exception
    {
	return false;
    }
}


import javax.xml.namespace.QName;
import org.apache.wsif.WSIFMessage;
import org.apache.wsif.WSIFOperation;
import org.apache.wsif.WSIFPort;
import org.apache.wsif.WSIFService;
import org.apache.wsif.WSIFServiceFactory;
import
org.apache.wsif.providers.soap.apacheaxis.WSIFPort_ApacheAxis;
import org.apache.wsif.util.WSIFPluggableProviders;
import
org.apache.wsif.providers.soap.apacheaxis.WSIFDynamicProvider_ApacheAxis;

public class RunDynamic2{

    private static final String SOAP_BINDING_NS =
"http://schemas.xmlsoap.org/wsdl/soap/";

    public static void main(String[] args) {

    String wsdlLocation =
"http://localhost/axis/base?wsdl";

    System.out.println("Invocation dynamic run2");

    try{

	WSIFPluggableProviders.overrideDefaultProvider(
SOAP_BINDING_NS,
	        new WSIFDynamicProvider_ApacheAxis());
        
        // create a service factory
        WSIFServiceFactory factory =
WSIFServiceFactory.newInstance();
        WSIFService service =
            factory.getService(
                wsdlLocation,
                null,
                null,
		"http://soapinterop.org/",
		"InteropTestPortType");

        // map types
        service.mapType(
            new QName("http://soapinterop.org",
"SOAPStruct"),
            Class.forName("IAComplexType") );

        // get the port
        WSIFPort port = service.getPort();

        // create the operation
        WSIFOperation operation =
port.createOperation("echoStruct");

        // create the input, output and fault messages
associated with this operation
        WSIFMessage input =
operation.createInputMessage();
        WSIFMessage output =
operation.createOutputMessage();
        WSIFMessage fault =
operation.createFaultMessage();

        // populate the input message
	IAComplexType inputStruct = new IAComplexType();
	inputStruct.setValue("<SOAPStruct
xsi:type=\"ns2:SOAPStruct\"
xmlns:ns2=\"http://soapinterop.org/xsd\"><varString
xsi:type=\"xsd:string\">This is string in
SOAPStruct</varString> <varInt
xsi:type=\"xsd:int\">5000</varInt> <varFloat
xsi:type=\"xsd:float\">12345.7</varFloat>
</SOAPStruct>");

        input.setObjectPart("inputStruct",
inputStruct);
	System.setProperty("http.proxyHost","localhost");
	System.setProperty("http.proxyPort",""+8080);

        // do the invocation
        if
(operation.executeRequestResponseOperation(input,
output, fault)) {
            // invocation succeeded, extract
information from output 
            // message
	    IAComplexType order =
(IAComplexType)output.getObjectPart("GetLatLongResult");
            System.out.println("SOAP Response:
\n"+order.getValue());


        } else {
            System.out.println("Invocation failed");
            // extract fault message info
        }
    }catch(Exception e){
	e.printStackTrace();
	e.getMessage();
    }

    }//main
}


The output of the run is here:

C:\>java RunDynamic2
Invocation dynamic run2
- WSIF0007I: Using WSIFProvider
'org.apache.wsif.providers.soap.apacheaxis.WSIFD
ynamicProvider_ApacheAxis' for namespaceURI
'http://schemas.xmlsoap.org/wsdl/soa
p/'
IAComplexType() constructor called
getTypeDesc() called
getTypeDesc() called
getSerializer() called. mechType: Axis SAX Mechanism,
_javaType: IAComplexType,
QName: {http://soapinterop.org}SOAPStruct
IAComplexTypeSerializer constructor called
serialize called
Qname LocalPart: multiRef namespace:
attributes: org.xml.sax.helpers.AttributesImpl@9934d4
hashCode() called
Object: IAComplexType@1
Invocation failed


The generated SOAP request is this:
Please note that I think the <multiRef> element (which
shouldn't be called that in the first place) should be
inside the <inputStruct> element.

POST http://localhost/axis/base HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime,
multipart/related, text/*
User-Agent: Axis/1.0
Host: localhost
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: "base#echoStruct"
Content-Length: 826

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
  <ns1:echoStruct
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://soapinterop.org/">
   <ns1:inputStruct href="#id0"/>
  </ns1:echoStruct>
  <multiRef id="id0" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:SOAPStruct"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://soapinterop.org">
   <varString xsi:type="xsd:string">Hello</varString>
   <varInt xsi:type="xsd:int">10</varInt>
   <varFloat xsi:type="xsd:float">1.23</varFloat>
  </multiRef>
 </soapenv:Body>
</soapenv:Envelope>









		
__________________________________ 
Do you Yahoo!? 
Make Yahoo! your home page 
http://www.yahoo.com/r/hs