axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Eric.D.Fried...@WellsFargo.COM
Subject RE: Improvements to Axis (among others, performance issues with
Date Fri, 03 Jan 2003 23:15:10 GMT
Hi Jean-Fran├žois,

Bug 15724 was fixed today -- check the latest CVS (or the January 4th
"interim" source tarball, which does not yet exist).

Regards,
Eric

-----Original Message-----
From: Jean-Fran├žois Cloutier [mailto:jf_cloutier@hotmail.com]
Sent: Friday, January 03, 2003 2:56 PM
To: axis-dev@xml.apache.org
Subject: Improvements to Axis (among others, performance issues with 


These modifications are based on the v1 release done on October 7, 2002 
(since this is the only "official" release).

---------------------------------------------------------------------
IMPROVEMENT #1 : probably the most important one (already reported in Bug 
15724)
---------------------------------------------------------------------

I made this modification after I found out wsdl2java to be extremely slow 
with large WSDL files. In my case, the WSDL file had about 150 schema types.

On a Pentium III 700Mhz and 512Mhz, it was taking 15 minutes to generate the

Java stubs. After my code change, it was taking... 10 seconds.

My investigation revealed that 98% of the time was spent figuring out what 
are the derived types of a schema type. When you have a somewhat large 
object model, this computation was done multiple for a given type. The trick

is obviously to cache this computation for each type.

Class: org.apache.axis.wsdl.symbolTable.Utils

    /**
     * This method returns a set of all types that are derived
     * from this type via an extension of a complexType
     */
    public static HashSet getDerivedTypes(TypeEntry type, SymbolTable 
symbolTable) {
    	HashSet types = (HashSet) symbolTable.derivedSets.get(type);

    	if (types != null)
    	    return types;

        types = new HashSet();
        symbolTable.derivedSets.put(type, types);

        if (type != null && type.getNode() != null) {
            getDerivedTypes(type, types, symbolTable);
        } else if (Constants.isSchemaXSD(type.getQName().getNamespaceURI()) 
&&
                   (type.getQName().getLocalPart().equals("anyType")||
                    type.getQName().getLocalPart().equals("any"))) {
            // All types are derived from anyType
            types.addAll(symbolTable.getTypes());
        }
        return types;
    } // getNestedTypes

    private static void getDerivedTypes(
            TypeEntry type, HashSet types, SymbolTable symbolTable) {

        // If all types are in the set, return
        if (types.size() == symbolTable.getTypes().size()) {
            return;
        }

        // Search the dictionary for derived types of type
        Vector allTypes = symbolTable.getTypes();
        Iterator it = allTypes.iterator();
        while(it.hasNext()) {
            TypeEntry derivedType = (TypeEntry) it.next();
            if (derivedType instanceof DefinedType &&
                derivedType.getNode() != null &&
                !types.contains(derivedType) &&
                SchemaUtils.getComplexElementExtensionBase(
                   derivedType.getNode(),
                   symbolTable) == type) {
                types.add(derivedType);
                HashSet derivedTypes = getDerivedTypes(derivedType, 
symbolTable);
                types.addAll(derivedTypes);
            }
        }
    } // getDerivedTypes


Class: org.apache.axis.wsdl.symbolTable.SymbolTable

    public HashMap derivedSets = new HashMap();


---------------------------------------------------------------------
IMPROVEMENT #2 : BeanDeserializerFactory should respect the class
		set in deserClass such that Bean deserializer can be
		subclassed.
		Likewise for BeanSerializerFactory with serClass.
---------------------------------------------------------------------

Class: org.apache.axis.encoding.ser.BeanDeserializerFactory

	static final Class[] ctorArgTypes =
		{
			Class.class,
			QName.class,
			TypeDesc.class,
			java.util.Map.class
		};

	protected Deserializer getGeneralPurpose(String mechanismType)
	{
		if ((javaType == null) || (xmlType == null))
			return super.getGeneralPurpose(mechanismType);

		if (deserClass == EnumDeserializer.class)
			return super.getGeneralPurpose(mechanismType);

		try
		{
			Constructor ctor =
deserClass.getConstructor(ctorArgTypes);
			Object[] args = new Object[] { javaType, xmlType,
typeDesc, propertyMap 
};

			return (Deserializer) ctor.newInstance(args);
		}
		catch (Exception e)
		{
			return new BeanDeserializer(javaType, xmlType,
typeDesc, propertyMap);
		}
	}

Class: org.apache.axis.encoding.ser.BeanSerializerFactory

	static final Class[] ctorArgTypes =
		{
			Class.class,
			QName.class,
			TypeDesc.class,
			BeanPropertyDescriptor[].class
		};

	protected Serializer getGeneralPurpose(String mechanismType)
	{
		if ((javaType == null) || (xmlType == null))
			return super.getGeneralPurpose(mechanismType);

		if (serClass == EnumSerializer.class)
			return super.getGeneralPurpose(mechanismType);

		try
		{
			Constructor ctor =
serClass.getConstructor(ctorArgTypes);
			Object[] args = new Object[] { javaType, xmlType,
typeDesc, 
propertyDescriptor };

			return (Serializer) ctor.newInstance(args);
		}
		catch (Exception e)
		{
			return new BeanSerializer(javaType, xmlType,
typeDesc, 
propertyDescriptor);
		}
	}


---------------------------------------------------------------------
IMPROVEMENT #3 : allow a subclass of Bean serializer to hook his own
		 BeanPropertyTarget
---------------------------------------------------------------------

Title says it all.

Class: org.apache.axis.encoding.ser.BeanDeserializer

    /**
     * Deserializer interface called on each child element encountered in
     * the XML stream.
     * @param namespace is the namespace of the child element
     * @param localName is the local name of the child element
     * @param prefix is the prefix used on the name of the child element
     * @param attributes are the attributes of the child element
     * @param context is the deserialization context.
     * @return is a Deserializer to use to deserialize a child (must be
     * a derived class of SOAPHandler) or null if no deserialization should
     * be performed.
     */
    public SOAPHandler onStartChild(String namespace,
                                    String localName,
                                    String prefix,
                                    Attributes attributes,
                                    DeserializationContext context)
        throws SAXException
    {
        BeanPropertyDescriptor propDesc = null;
        FieldDesc fieldDesc = null;

        String encodingStyle = 
context.getMessageContext().getEncodingStyle();
        boolean isEncoded = Constants.isSOAP_ENC(encodingStyle);

        QName elemQName = new QName(namespace, localName);
        // The collectionIndex needs to be reset for Beans with multiple 
arrays
        if ((prevQName == null) || (!prevQName.equals(elemQName))) {
            collectionIndex = -1;
        }
        prevQName = elemQName;

        if (typeDesc != null) {
            // Lookup the name appropriately (assuming an unqualified
            // name for SOAP encoding, using the namespace otherwise)
            String fieldName = typeDesc.getFieldNameForElement(elemQName,
                                                               isEncoded);
            propDesc = (BeanPropertyDescriptor)propertyMap.get(fieldName);
            fieldDesc = typeDesc.getFieldByName(fieldName);
        }

        if (propDesc == null) {
            // look for a field by this name.
            propDesc = (BeanPropertyDescriptor) propertyMap.get(localName);
        }

        // try and see if this is an xsd:any namespace="##any" element 
before
        // reporting a problem
        if (propDesc == null) {
            // try to put unknown elements into a SOAPElement property, if
            // appropriate
            propDesc = getAnyPropertyDesc();
            if (propDesc != null) {
                try {
                    MessageElement [] curElements = 
(MessageElement[])propDesc.get(value);
                    int length = 0;
                    if (curElements != null) {
                        length = curElements.length;
                    }
                    MessageElement [] newElements = new 
MessageElement[length + 1];
                    if (curElements != null) {
                        System.arraycopy(curElements, 0,
                                         newElements, 0, length);
                    }
                    MessageElement thisEl = context.getCurElement();

                    newElements[length] = thisEl;
                    propDesc.set(value, newElements);

                    return new SOAPHandler();
                } catch (Exception e) {
                    throw new SAXException(e);
                }
            }
        }


        if (propDesc == null) {
            // No such field
            throw new SAXException(
                    Messages.getMessage("badElem00", javaType.getName(),
                                         localName));
        }

        // Get the child's xsi:type if available
        QName childXMLType = context.getTypeFromXSITypeAttr(namespace,
                                                            localName,
                                                            attributes);

        String href = attributes.getValue("href");

        // If no xsi:type or href, check the meta-data for the field
        if (childXMLType == null && fieldDesc != null && href == null) {
            childXMLType = fieldDesc.getXmlType();
        }

        // Get Deserializer for child, default to using DeserializerImpl
        Deserializer dSer = getDeserializer(childXMLType, 
propDesc.getType(),
                                            href,
                                            context);
        // It is an error if the dSer is not found, the base
        // deserializer impl is returned so that it can generate the correct

message.
        if (dSer == null) {
            dSer = new DeserializerImpl();
            return (SOAPHandler)dSer;
        }

        // Register value target
        if (propDesc.isWriteable()) {
            // If this is an indexed property, and the deserializer we found
            // was NOT the ArrayDeserializer, this is a non-SOAP array:
            // <bean>
            //   <field>value1</field>
            //   <field>value2</field>
            // ...
            // In this case, we want to use the collectionIndex and make 
sure
            // the deserialized value for the child element goes into the
            // right place in the collection.
            if (propDesc.isIndexed() && !(dSer instanceof 
ArrayDeserializer)) {
                    collectionIndex++;
                    dSer.registerValueTarget(createValueTarget(value,
                                                    propDesc, 
collectionIndex));
            } else {
                // If we're here, the element maps to a single field value,
                // whether that be a "basic" type or an array, so use the
                // normal (non-indexed) BeanPropertyTarget form.
                collectionIndex = -1;
                dSer.registerValueTarget(createValueTarget(value, propDesc, 
-1));
            }
        }
        return (SOAPHandler)dSer;
    }

    protected Target createValueTarget(Object value, BeanPropertyDescriptor 
propDesc, int collectionIndex)
    {
	return new BeanPropertyTarget(value, propDesc, collectionIndex);
    }


_________________________________________________________________
MSN Messenger : discutez en direct avec vos amis ! 
http://www.msn.fr/msger/default.asp

Mime
View raw message