You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@axis.apache.org by Mi...@wellsfargo.com on 2004/11/10 18:31:20 UTC

wsdl2java serialization process

Hi,
 
How do I envoke the serialization process for objects created by the
WSDL2Java process.  I would like to write the SOAP request and response
objects out as XML to log4j during the processing of the request.  These are
complex objects generated directly from a wsdl.  It is not clear to me how
to envoke this process within Axis.
 
Thanks,
-mike

Re: wsdl2java serialization process

Posted by Ki...@sybase.com.
The following code posted by Michael Binz could help you.

---------------------- START--------------------------------------
package .util;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.ByteArrayInputStream;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.xml.namespace.QName;
import javax.xml.rpc.encoding.TypeMapping;

import net.guardean.agw.*;
import net.guardean.agw.server.AgTransformer;
import net.guardean.agw.ws.schema.*;

import org.apache.axis.MessageContext;
import org.apache.axis.client.AxisClient;
import org.apache.axis.client.Call;
import org.apache.axis.description.TypeDesc;
import org.apache.axis.encoding.DeserializationContextImpl;
import org.apache.axis.encoding.SerializationContextImpl;
import org.apache.axis.message.RPCElement;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPBodyElement;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.AttributesImpl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.axis.encoding.ser.BaseDeserializerFactory;
import org.apache.axis.encoding.ser.BaseSerializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.EnumDeserializerFactory;
import org.apache.axis.encoding.ser.EnumSerializerFactory;



/**
 * Holds AG support functionality.
 *
 * @version $Revision: #4 $
 * @author Michael Binz
 */
public class AgSupportLib
{
    /**
     * Logger used by this class
     */
    private static final Log _logger =
        LogFactory.getLog( AgSupportLib.class );



                 /**
                  * Generated classes from Axis.  This table is only 
necessary on
Axis 1.1.
     * Note that the classes commented with // enum ... require a special
     * handling performed in registerAxisClassesInContext.  Keep them as
     * as comments here so that they arent forgotten.
     *
     * TODO Remove as soon as Axis 1.2 is used.
                  */
                 private static Class generatedAxisClasses[]={
                                 AddressType.class,
                                 AgencyInformationType.class,
                                 CompanyType.class,
                                 ErrorMessageType.class,
                                 FunctionType.class,
// enum GenderType.class,
                                 LegalEventType.class,
                                 MoneyType.class,
                                 OptionalEntry.class,
                                 PartyListType.class,
                                 PartyMatrixType.class,
                                 PartyType.class,
                                 PersonType.class,
                                 RatingType.class,
                                 RequestType.class,
                                 ResponseType.class,
                                 ScoreType.class
                 };

    private final static QName GenderTypeName = 
        new javax.xml.namespace.QName(
            "http://ws.agw.guardean.net/schema",
            getPlainClassName( GenderType.class ) );




                 /**
                  * Register a set of generated classes from Axis in a 
Message
Context
                  *
                  *@param pContext MessageContext where all the classes 
will be
registered
                  *@param pClassArray generated classes by Axis that will 
be register
in the 
     *       context given as parameter
                  */
                 private static void 
registerAxisClassesInContext(MessageContext
pContext, Class pClassArray[]){
                                 Class currentClass = null;
                                 //TODO Is there a way to check 
dynamically the classes
generated by Axis 
                                 //under the schema package??
        //TODO Operation is not longer necessary on Axis 1.2.  No need to
invest
        // the time to make that finally cool on Axis 1.1 -- would be
expensive.
                                 if (pContext == null)
                                                 return;
 
                                 if (pClassArray == null){
                                                 _logger.warn("No 
generated classes from Axis in
system!.");
                                                 return;
                                 }

                                 TypeMapping typeMapping = 
pContext.getTypeMapping();

                                 for(int i=0; i < pClassArray.length; 
i++){
                                     try{
                                         currentClass = pClassArray[i];
                                         // get TypeDesc from class
                                         Method gtd = 
currentClass.getMethod( "getTypeDesc",
null );
                                         TypeDesc td = 
(TypeDesc)gtd.invoke( null, null );
                                         // register serializer and 
deserializer for this
class 
                                         typeMapping.register( 
                        currentClass,
                                                 td.getXmlType(), 
 
BaseSerializerFactory.createFactory(BeanSerializerFactory.class,currentClass
,td.getXmlType()),
 
BaseDeserializerFactory.createFactory(BeanDeserializerFactory.class,currentC
lass,td.getXmlType())
            );
                                                 }catch(Exception e){
 _logger.error("No Axis generated class ("+
currentClass.getName()+")",e);
                         throw new IllegalArgumentException(
                                 "No Axis generated class: " + 
currentClass.getName()
); 
                                                 }
                                 }

                                 // Special handling for enumeration 
simple types.
        // genderType
        {
            typeMapping.register( 
                GenderType.class,
                GenderTypeName, 
                EnumSerializerFactory.createFactory(
                        EnumSerializerFactory.class,
                        GenderType.class,
                        GenderTypeName ),
                EnumDeserializerFactory.createFactory(
                        EnumDeserializerFactory.class,
                        GenderType.class,
                        GenderTypeName ) );
        }
                 }



    /**
     * <p>Transforms an instance of a type generated by Axis
     * <code>WSDL2Java</code> into an XML representation, using only Axis
APIs.
     * <p>Note that this implementation only works on Axis data types 
since
     * only these are registered against the Axis runtime,</p>
     *
     * @param pO The object to be transformed.
     * @param pQname The qualified name of the passed object.  Note that
     *        passing the wrong value here does not result in an error, 
but
in
     *        the generation of a wrong XML structure.  This can be 
accessed

     *        for a given type <i>Type</i> by the code 
     *        <code><i>Type</i>.getTypeDesc().getXmlType()</code>.
     * @return An XML-stringified representation of the input object.
     * @deprecated Use the single parameter version of this operation.
QName
     *             autodetection is save and simple.
     */
    private static String transformWsInstanceToXml( Object pO, QName 
pQname
)
    {
        // Since we are not in a message call context, we have to create a
        // message context ourselves.
        MessageContext mc = new MessageContext( new AxisClient() );
        registerAxisClassesInContext( mc, generatedAxisClasses );
        // This means that the XSI type attributes are not generated.
        mc.setProperty( Call.SEND_TYPE_ATTR, "false" );

        // This writer will ultimately receive the generated XML...
        StringWriter result = new StringWriter();
        // ...and is connected to the serialisation context.
        SerializationContextImpl sci = new SerializationContextImpl(
            result,
            mc );
        // Pretty print the result for convenience.
        sci.setPretty(  true );

        // MultiRef'ing means that when object graphs are serialized, the
        // identity of objects is kept, i.e. first the first level objects
are
        // serialized with hrefs to the nested objects.  After that the
nested
        // objects are serialised and so on.
        // This is not what we want.  We want instead an in-place 
expansion
of
        // nested objects without the hassle of object decomposition, we
have
        // only plain vanilla data structures in the end.
        sci.setDoMultiRefs( false );

        try
        {
            // ...and perform the serialization.
            sci.serialize(
                    pQname,
                    new AttributesImpl(),
                    pO );
        }
        catch ( IOException e )
        {
            // This exception is triggered by the java.io.Writer in the
            // SerialisationContext.  Since we use a StringWriter, we can
            // guarantee that no IOExceptions will be thrown and safely
            // ignore these.
            _logger.warn( "java.io.StringWriter threw IOException.", e );
        }

        return result.toString();
    }



    /**
     * Transforms the passed type into its XML representation.  The passed
     * object must represent a type generated by the Axis WSDL compiler.
     *
     * @param pO The object to be transformed.
     * @return The passed object's XML representation in string format.
     * @throws IllegalArgumentException If the passed object is not an
instance
     *         of an Axis-generated type.
     */
    public static String axisToXml( Object pO )
    {
        Class oClass = pO.getClass();

        try
        {
            // Get the type description via the static method.
            Method gtd = oClass.getMethod( "getTypeDesc", null );
            TypeDesc td = (TypeDesc)gtd.invoke( null, null );
            // From the type description get the QName.
            return transformWsInstanceToXml( pO, td.getXmlType() );
        }
        catch ( Exception e )
        {
            // Check whether this is one of the non-complex types in the
            // package.  In this case we synthesize a QName. Holy cow,
looking
            // forward to Axis 1.2
            return transformWsInstanceToXml(
                    pO,
                    new javax.xml.namespace.QName( 
                            "http://ws.agw.guardean.net/schema", 
                            getPlainClassName( pO.getClass() ) ) ); 
        }
    }



    /**
     * Transforms the passed type into its XML representation.  The passed
     * object must represent a type generated by the Axis WSDL compiler.
     *
     * @param pO The object to be transformed.
     * @return The passed object's XML representation in string format.
     * @deprecated Use axisToXml() instead.
     * @throws IllegalArgumentException If the passed object is not an
instance
     *         of an Axis-generated type.
     */
    public static String transformWsInstanceToXml( Object pO )
    {
        return axisToXml( pO );
    }



    /**
     * Convert an XML structure created from an Axis-generated class back
into
     * an object representation.
                  * 
     * @param xml The XML structure.  Generated by
     *        <code>axisToXml( Object )</code>.
     * @param pQname The qualified name of the target type.
     * @return An instance of the Axis generated class.
     * @see AgSupportLib#axisToXml(Object)
     */
    public static Object xmlToAxis( String xml, QName pQname )
    {
        // TODO would be cool to dynamically detect the target qname. This
        // could be done by looking at the first element's name in the
inbound
        // XML data.

        try
        {
                                 // Wrap the InputStream up into a SOAP 
Body and Envelope
since the parser
                                     // expects a SOAP Envelope
                                 SOAPEnvelope env1 = new SOAPEnvelope();
                                 env1.addBodyElement(
                    new SOAPBodyElement(
                            new ByteArrayInputStream(xml.getBytes())));
 
            // Since we are not in a message call context, we have to 
create
a
            // message context ourselves.
            MessageContext mc = new MessageContext( new AxisClient() );
            // TODO: This following line manually registers the generated
type
            // mappings.  This has to be removed as soon as Axis 1.2 is
used.
 
registerAxisClassesInContext(mc,generatedAxisClasses);
 
            InputSource is = 
                new InputSource( new StringReader( env1.toString() ) );

            // ...and is connected to the serialisation context.
            DeserializationContextImpl sci = new 
DeserializationContextImpl(
                    is, mc, org.apache.axis.Message.REQUEST );
            sci.parse();

            SOAPEnvelope env2 = sci.getEnvelope();
            RPCElement rpcElem = (RPCElement) env2.getFirstBody();
 
            // On Axis 1.2 use the getValueAsType( qname, class ) in the
next
            // line and not the single arg version.
            //return rpcElem.getValueAsType(qname, clazz);
            return rpcElem.getValueAsType( pQname ); // Axis 1.1 code.
        }
        catch ( Exception e )
        {
            _logger.debug( "deserialisation problem.", e );
            throw new IllegalArgumentException(
              e.getMessage() );
        }
    }



    /**
     * 
     * @param pclass
     * @return
     */
    public static String getPlainClassName( Class pclass )
    {
        String fullyQualified = pclass.getName();
        int lastDot = fullyQualified.lastIndexOf( '.' );
        if ( lastDot == -1 )
            return fullyQualified;
 
        return fullyQualified.substring( lastDot+1 );
    }



    /**
     * Test code.
     *
     * @param argv
     */
    public static void main( String[] argv )
    {
        LegalEventType o = new LegalEventType();

        o.setDate( new Date() );
        o.setDescription( "This is a test for legal event serialisation." 
);
        o.setHasExpired( Boolean.TRUE );
 
                                 System.out.println( "Serialized Object. 
Description: " +
o.getDescription() );
                                 System.out.println( "Serialized Object. 
hasExpired: " +
o.getHasExpired() );
                                 System.out.println( "Serialized Object: 
Date: " +
o.getDate() );
 
        String intermediateString = transformWsInstanceToXml( o );

        Object deserialised = xmlToAxis(
            intermediateString,
            LegalEventType.getTypeDesc().getXmlType() );

                                 LegalEventType t = (LegalEventType) 
deserialised;

                                 System.out.println( "Deserialized Object. 
Description: " +
o.getDescription() );
                                 System.out.println( "Deserialized Object. 
hasExpired: " +
o.getHasExpired() );
                                 System.out.println( "Deserialized Object: 
Date: " +
o.getDate() );
        //System.err.println( "" + deserialised );
 
        GenderType gender = GenderType.FEMALE;
        intermediateString = transformWsInstanceToXml( gender );
        System.err.println( intermediateString );
        deserialised = xmlToAxis( intermediateString, GenderTypeName );
        System.err.println( deserialised.toString() );
        Gender g = AgTransformer.transform( (GenderType)deserialised );
        System.err.println( "Gender is: " + g );
    }
}
-----------------------------------------------------------------------------

Regards,
- kiru





Laurent CORNELIS <la...@ingleasebelgium.be> 
10/18/2004 06:37 AM
Please respond to
axis-user@ws.apache.org


To
"Axis-User (E-mail)" <ax...@ws.apache.org>
cc

Subject
BeanSerializer / BeanDeserializer






Hi,
 
Can someone tell me how to use BeanSerializer / Deserializer out of the 
context of a message ? (ie to encode an object to XML and to parse XML for 
an object).
 
For the serialization I do :
 
-------------------------------------------------------------------
 
MyObject obj = new MyObject();
 
   FileWriter fout = new FileWriter("c:\\test.xml");
 
   AxisClient client = new AxisClient();
   MessageContext msgContext = new MessageContext(client);
   SerializationContextImpl context = new SerializationContextImpl(
     fout, msgContext);
   context.setPretty(true);
   context.setDoMultiRefs(false);
   context.setSendDecl(true);
 
   BeanSerializer s = (BeanSerializer) MyObject
     .getSerializer(Constants.AXIS_SAX, MyObject.class,
       MyObject.getTypeDesc().getXmlType());
   s.serialize(MyObject.getTypeDesc().getXmlType(),
     null, obj, context);
 
   fout.flush();
   fout.close();
-------------------------------------------------------------------
 
And it is working.
 
Now I don't know how to deserialize ... I tried this but it don't work :
 
-------------------------------------------------------------------
   BeanDeserializer d = 
(BeanDeserializer)MyObject.getDeserializer(Constants.AXIS_SAX,MyObject.class,MyObject.getTypeDesc().getXmlType());
   InputSource source = new InputSource("c:\\test.xml");
 
   SAXParser p = XMLUtils.getSAXParser();
 
   XMLReader reader = p.getXMLReader();
 
   reader.setContentHandler(d);
   reader.setDTDHandler(d);
   reader.setEntityResolver(d);
   reader.setErrorHandler(d);
 
   reader.parse(source);
 
  MyObject obj = (MyObject)d.getValue();
-------------------------------------------------------------------





Michael.S.Ward@wellsfargo.com 
11/10/2004 09:31 AM
Please respond to
axis-user@ws.apache.org


To
axis-user@ws.apache.org
cc

Subject
wsdl2java serialization process






Hi,
 
How do I envoke the serialization process for objects created by the 
WSDL2Java process.  I would like to write the SOAP request and response 
objects out as XML to log4j during the processing of the request.  These 
are complex objects generated directly from a wsdl.  It is not clear to me 
how to envoke this process within Axis.
 
Thanks,
-mike