You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by sc...@apache.org on 2009/06/17 20:57:51 UTC

svn commit: r785755 - in /webservices/axis2/trunk/java/modules: jaxws-integration/test/org/apache/axis2/jaxws/sample/ jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/ jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/ jax...

Author: scheu
Date: Wed Jun 17 18:57:50 2009
New Revision: 785755

URL: http://svn.apache.org/viewvc?rev=785755&view=rev
Log:
JIRA:AXIS2-4393
Contributor:Rich Scheuerle
Added code to the "document literal wrapped minimal method" marshaling algorithm to detect and accomodate
missing elements/parameters.  This change will allow the runtime to handle applications from third party
vendors that do not package JAXB classes.  The change will have no effect on the marshaling or unmarshaling
when JAXB classes are present.

Modified:
    webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/DLWMinTests.java
    webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/GreeterImpl.java
    webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/greeter.wsdl
    webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/sei/Greeter.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/DocLitWrappedMinimalMethodMarshaller.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/XMLPart.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLPartBase.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpine.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpineImpl.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ParameterDescriptionImpl.java

Modified: webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/DLWMinTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/DLWMinTests.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/DLWMinTests.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/DLWMinTests.java Wed Jun 17 18:57:50 2009
@@ -129,6 +129,117 @@
      * Test simple greetMe method 
      * with style doc/lit wrapped without the presence of wrapper classes.
      */
+    public void testSimpleTest() {
+        
+        Greeter proxy = getProxy("simpleTest");
+        
+        String name = "user1";
+        byte[] bytes = new byte[100];
+        String response = proxy.simpleTest(name, bytes);
+        System.out.println(response);
+        assertTrue(response.contains("name=user1"));
+        assertTrue(response.contains("numbytes=100"));
+        
+        // Try the call again
+        response = proxy.simpleTest(name, bytes);
+        System.out.println(response);
+        assertTrue(response.contains("name=user1"));
+        assertTrue(response.contains("numbytes=100"));
+    }
+    
+    
+    /**
+     * Test simple greetMe method 
+     * with style doc/lit wrapped without the presence of wrapper classes.
+     */
+    public void testSimpleTestNoName() {
+        
+        Greeter proxy = getProxy("simpleTest");
+        
+        
+        // Try with a no name
+        String name = null;
+        byte[] bytes = new byte[100];
+        String response = proxy.simpleTest(name, bytes);
+        System.out.println(response);
+        assertTrue(response.contains("name=null"));
+        assertTrue(response.contains("numbytes=100"));
+        
+        // Try the call again
+        response = proxy.simpleTest(name, bytes);
+        System.out.println(response);
+        assertTrue(response.contains("name=null"));
+        assertTrue(response.contains("numbytes=100"));
+    }
+    
+    /**
+     * Test simple greetMe method with dispatch 
+     * with style doc/lit wrapped without the presence of wrapper classes.
+     */
+    public void testSimple_Dispatch() {
+       
+        Dispatch<String> dispatch = getDispatch("simpleTest");
+        
+        String request =
+            "<pre:simpleTest xmlns:pre='http://apache.org/axis2/jaxws/sample/dlwmin'>" +
+            "<pre:name>user1</pre:name>" +
+            "<pre:bytes>AAAAAA</pre:bytes>" +
+            "</pre:simpleTest>";
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Request =" + request);
+        String response = dispatch.invoke(request);
+        System.out.println(response);
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Response =" + response);
+        
+        assertTrue(response.contains("name=user1"));
+        assertTrue(response.contains("numbytes=3"));
+        assertTrue(response.contains("dlwmin:simpleTestResponse"));
+        
+        // Try the call again
+        response = dispatch.invoke(request);
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Response =" + response);
+        System.out.println(response);
+        
+        assertTrue(response.contains("name=user1"));
+        assertTrue(response.contains("numbytes=3"));
+        assertTrue(response.contains("dlwmin:simpleTestResponse"));
+    }
+    
+    /**
+     * Test simple greetMe method with dispatch 
+     * with style doc/lit wrapped without the presence of wrapper classes.
+     */
+    public void testSimpleNoName_Dispatch() {
+       
+        Dispatch<String> dispatch = getDispatch("simpleTest");
+        
+        String request =
+            "<pre:simpleTest xmlns:pre='http://apache.org/axis2/jaxws/sample/dlwmin'>" +
+            "<pre:bytes>AAAAAA</pre:bytes>" +
+            "</pre:simpleTest>";
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Request =" + request);
+        String response = dispatch.invoke(request);
+        System.out.println(response);
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Response =" + response);
+        
+        assertTrue(response.contains("name=null"));
+        assertTrue(response.contains("numbytes=3"));
+        assertTrue(response.contains("dlwmin:simpleTestResponse"));
+        
+        // Try the call again
+        response = dispatch.invoke(request);
+        TestLogger.logger.debug("Doc/Lit Wrapped Minimal Response =" + response);
+        System.out.println(response);
+        
+        assertTrue(response.contains("name=null"));
+        assertTrue(response.contains("numbytes=3"));
+        assertTrue(response.contains("dlwmin:simpleTestResponse"));
+    }
+    
+    
+    /**
+     * Test simple greetMe method 
+     * with style doc/lit wrapped without the presence of wrapper classes.
+     */
     public void testUnqualified() {
         
         Greeter proxy = getProxy("testUnqualified");

Modified: webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/GreeterImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/GreeterImpl.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/GreeterImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/GreeterImpl.java Wed Jun 17 18:57:50 2009
@@ -65,4 +65,7 @@
         return null;
     }
 
+    public String simpleTest(String name, byte[] bytes) {
+        return "name=" + name + " numbytes=" +bytes.length;
+    }
 }

Modified: webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/greeter.wsdl
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/greeter.wsdl?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/greeter.wsdl (original)
+++ webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/META-INF/greeter.wsdl Wed Jun 17 18:57:50 2009
@@ -75,6 +75,21 @@
                     </sequence>
                 </complexType>
             </element>
+            <element name="simpleTest">
+                <complexType>
+                    <sequence>
+                        <element name="name" minOccurs="0" type="xsd:string"/>
+                        <element name="bytes" type="xsd:base64binary"/>
+                    </sequence>
+                </complexType>
+            </element>
+            <element name="simpleTestResponse">
+                <complexType>
+                    <sequence>
+                        <element name="response" type="xsd:string"/>
+                    </sequence>
+                </complexType>
+            </element>
         </schema>
     </wsdl:types>
     <wsdl:message name="greetMeRequest">
@@ -104,6 +119,12 @@
     <wsdl:message name="processFault3">
         <wsdl:part name="fault3" element="types:processFault3"/>
     </wsdl:message>
+     <wsdl:message name="simpleTestRequest">
+        <wsdl:part name="in" element="tns:simpleTest"/>
+    </wsdl:message>
+    <wsdl:message name="simpleTestResponse">
+        <wsdl:part name="out" element="tns:simpleTestResponse"/>
+    </wsdl:message>
     <wsdl:portType name="Greeter">
         <wsdl:operation name="greetMe">
             <wsdl:input name="greetMeRequest" message="tns:greetMeRequest"/>
@@ -120,6 +141,10 @@
             <wsdl:fault name="processFault2" message="tns:processFault2"/>
             <wsdl:fault name="processFault3" message="tns:processFault3"/>
         </wsdl:operation>
+        <wsdl:operation name="simpleTest">
+            <wsdl:input name="simpleTestRequest" message="tns:simpleTestRequest"/>
+            <wsdl:output name="simpleTestResponse" message="tns:simpleTestResponse"/>
+        </wsdl:operation>
     </wsdl:portType>
     <wsdl:binding name="GreeterSOAPBinding" type="tns:Greeter">
         <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
@@ -159,6 +184,15 @@
                 <soap:fault name="processFault3" use="literal"/>
             </fault>
         </wsdl:operation>
+        <wsdl:operation name="simpleTest">
+            <soap:operation soapAction="simpleTest" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
     </wsdl:binding>
     <wsdl:service name="GreeterService">
         <wsdl:port name="GreeterPort" binding="tns:GreeterSOAPBinding">

Modified: webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/sei/Greeter.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/sei/Greeter.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/sei/Greeter.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws-integration/test/org/apache/axis2/jaxws/sample/dlwmin/sei/Greeter.java Wed Jun 17 18:57:50 2009
@@ -51,4 +51,12 @@
         @WebParam(targetNamespace = "", partName = "in")
         TestBean in
     ) throws TestException, TestException2, TestException3;
+    
+    @WebMethod
+    public String simpleTest(
+            @WebParam(targetNamespace = "http://apache.org/axis2/jaxws/sample/dlwmin", name = "name")
+            String name, 
+            @WebParam(targetNamespace = "http://apache.org/axis2/jaxws/sample/dlwmin", name = "bytes")
+            byte[] bytes);
+    
 }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java Wed Jun 17 18:57:50 2009
@@ -452,6 +452,9 @@
 
         if (DEBUG_ENABLED) {
             log.debug("Invoking unmarshalByType.");
+            log.debug("  type = " + type);
+            log.debug("  isList = " + isList);
+            log.debug("  ctype = "+ ctype);
         }
 
         return AccessController.doPrivileged(new PrivilegedAction() {
@@ -470,12 +473,14 @@
                             // but there is not much we can do about it so seralize it as
                             // usual
                             if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CONTEXT_PATH) {
+                                if (DEBUG_ENABLED) {
+                                    log.debug("Unmarshal Array via BY_CONTEXT_PATH approach");
+                                }
                                 jaxb = u.unmarshal(reader, type);
                             }
                             // list on client array on server, Can happen only in start from java
                             // case.
                             else if ((ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY)) {
-
                                 // The type could be any Object or primitive
                             	
                             	//process primitives first
@@ -486,6 +491,9 @@
                             		cType = cType.getComponentType();
                             	}
                             	if(cType.isPrimitive()){
+                            	    if (DEBUG_ENABLED) {
+                                        log.debug("Unmarshal Array of primitive via BY_CLASS_ARRAY approach");
+                                    }
                             		jaxb = u.unmarshal(reader, type);
                             	}
                             	// process non primitive                       	
@@ -494,11 +502,16 @@
                                 // proper type Object Array.
                             	
                             	else{
+                            	    if (DEBUG_ENABLED) {
+                                        log.debug("Unmarshal Array of non-primitive via BY_CLASS_ARRAY approach");
+                                    }
                             		jaxb = unmarshalArray(reader, u, type);
                             	}
                                 
                             } else {
-                                
+                                if (DEBUG_ENABLED) {
+                                    log.debug("Unmarshal Array");
+                                }
                                 jaxb = u.unmarshal(reader, type);
                                 
                             }
@@ -523,7 +536,7 @@
                             // object
                             // ... }
                             if (DEBUG_ENABLED) {
-                                log.debug("unmarshalByType. Unmarshalling " + type.getName()
+                                log.debug("Unmarshalling " + type.getName()
                                         + " as Enum");
                             }
 
@@ -539,6 +552,9 @@
                         }
                         //Normal case: We are not unmarshalling a xsd:list or Array
                         else {
+                            if (DEBUG_ENABLED) {
+                                log.debug("Unmarshalling normal case (not array, not xsd:list, not enum)");
+                            }
                             jaxb = u.unmarshal(reader, type);
                         }
 
@@ -547,10 +563,32 @@
                         // list or array (see NOTE above)
                         // First unmarshal as a String
                         //Second convert the String into a list or array
-                        
+                        if (DEBUG_ENABLED) {
+                            log.debug("Unmarshalling xsd:list");
+                        }
                         jaxb = unmarshalAsListOrArray(reader, u, type);
                         
                     }
+                    if (log.isDebugEnabled()) {
+                        Class cls;
+                        if (jaxb == null) {
+                            if (DEBUG_ENABLED) {
+                                log.debug("End unmarshalByType returning null object");
+                            }
+
+                        } else if (jaxb instanceof JAXBElement) {
+                            JAXBElement jbe = (JAXBElement) jaxb;
+                            if (DEBUG_ENABLED) {
+                                log.debug("End unmarshalByType returning JAXBElement");
+                                log.debug("  Class = " + jbe.getDeclaredType());
+                                log.debug("  QName = " + jbe.getName());
+                            }
+                        } else {
+                            if (DEBUG_ENABLED) {
+                                log.debug("End unmarshalByType returning " + jaxb.getClass());
+                            }
+                        }
+                    }
                     return jaxb;
                 } catch (OMException e) {
                     throw e;

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/DocLitWrappedMinimalMethodMarshaller.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/DocLitWrappedMinimalMethodMarshaller.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/DocLitWrappedMinimalMethodMarshaller.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/DocLitWrappedMinimalMethodMarshaller.java Wed Jun 17 18:57:50 2009
@@ -84,26 +84,6 @@
                     MethodMarshallerUtils.getMarshalDesc(endpointDesc);
             TreeSet<String> packages = marshalDesc.getPackages();
 
-            // TODO This needs more work.  We need to check inside holders of input params.  We also
-            // may want to exclude header params from this check
-            //Validate input parameters for operation and make sure no input parameters are null.
-            //As per JAXWS Specification section 3.6.2.3 if a null value is passes as an argument 
-            //to a method then an implementation MUST throw WebServiceException.
-            if (pds.length > 0) {
-                if (signatureArguments == null) {
-                	throw ExceptionFactory.makeWebServiceException(
-                			Messages.getMessage("NullParamErr1",operationDesc.getJavaMethodName()));
-                }
-                if (signatureArguments != null) {
-                    for (Object argument : signatureArguments) {
-                        if (argument == null) {
-                        	throw ExceptionFactory.makeWebServiceException(
-                        			Messages.getMessage("NullParamErr1",operationDesc.getJavaMethodName()));
-                        }
-                    }
-                }
-            }
-
             // Create the message 
             MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
             Message m = mf.create(protocol);
@@ -193,7 +173,7 @@
             }
 
             // Unmarshal the ParamValues from the Message
-            List<PDElement> pvList = MethodMarshallerUtils.getPDElements(pds,
+            List<PDElement> pvList = MethodMarshallerUtils.getPDElementsWithMissingElements(pds,
                                                                          message,
                                                                          packages,
                                                                          true, // input
@@ -203,19 +183,11 @@
             // Build the signature arguments
             Object[] sigArguments = MethodMarshallerUtils.createRequestSignatureArgs(pds, pvList);
 
-            // TODO This needs more work.  We need to check inside holders of input params.  We also
-            // may want to exclude header params from this check
-            //Validate input parameters for operation and make sure no input parameters are null.
-            //As per JAXWS Specification section 3.6.2.3 if a null value is passes as an argument 
-            //to a method then an implementation MUST throw WebServiceException.
-            if (sigArguments != null) {
-                for (Object argument : sigArguments) {
-                    if (argument == null) {
-                        throw ExceptionFactory.makeWebServiceException(
-                    			Messages.getMessage("NullParamErr2",operationDesc.getJavaMethodName()));
-                    }
-                }
-            }
+            // Note:  The code used to check to ensure that parameters were not null.
+            // The code sited 3.6.2.3 of the JAX-WS specification, but that portion of the specification
+            // is for rpc/literal marshaling.  This code is for document/literal marshaling.
+            // Nulls are allowed.
+            
             return sigArguments;
         } catch (Exception e) {
             throw ExceptionFactory.makeWebServiceException(e);
@@ -442,7 +414,6 @@
                                                                          hasReturnInBody,
                                                                          javaTypes); // unmarshal by type
 
-            // TODO Should we check for null output body values?  Should we check for null output header values ?
 
             // Populate the response Holders
             MethodMarshallerUtils.updateResponseSignatureArgs(pds, pvList, signatureArgs);

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/MethodMarshallerUtils.java Wed Jun 17 18:57:50 2009
@@ -247,6 +247,7 @@
      * return value is expected in the body.
      * @param unmarshalByJavaType in most scenarios this is null.  
      * Only use this in the scenarios that require unmarshalling by java type
+     * @see getPDElementsWithMissingElements
      * @return ParamValues
      */
     static List<PDElement> getPDElements(ParameterDescription[] params,
@@ -372,8 +373,248 @@
     }
 
     /**
+     * Return the list of PDElements that is unmarshalled from the wire.
+     * NOTE: This method is slower as the normal getPDElements method because it 
+     * must cache the message in order to do QName matches.
+     * This method is only necessary to support the cases where the incoming message
+     * may have missing data items.  
+     * Currently this is limited to the document/literal minimal case.
+     * 
+     * @param params ParameterDescription for this operation
+     * @param message Message
+     * @param packages set of packages needed to unmarshal objects for this operation
+     * @param isInput indicates if input or output  params (input on server, output on client)
+     * @param hasReturnInBody if isInput=false, then this parameter indicates whether a 
+     * return value is expected in the body.
+     * @param unmarshalByJavaType in most scenarios this is null.  
+     * Only use this in the scenarios that require unmarshalling by java type
+     * @see getPDElements
+     * @return ParamValues
+     */
+    static List<PDElement> getPDElementsWithMissingElements(ParameterDescription[] params,
+                                         Message message,
+                                         TreeSet<String> packages,
+                                         boolean isInput,
+                                         boolean hasReturnInBody, 
+                                         Class[] unmarshalByJavaType) throws XMLStreamException {
+
+        if (log.isDebugEnabled()) {
+            log.debug("start getPDElementsWithMissingElements");
+        }
+        List<PDElement> pdeList = new ArrayList<PDElement>();
+        
+        // Create an array of indices indicating where each parameter is located in the body
+        // A -1 indicates that the parameter is not in the body
+        int[] bodyIndex = new int[params.length];
+        for (int i=0; i<bodyIndex.length; i++) {
+            bodyIndex[i] = -1;  
+        }
+
+        // Calculate the array indices based on the parameter location 
+        int bi = (!isInput && hasReturnInBody) ? 1 : 0;  // If there is a return in the body, the output parameters start at index 1
+        for (int i = 0; i < params.length; i++) {
+            ParameterDescription pd = params[i];
+
+            if (pd.getMode() == Mode.IN && isInput ||
+                    pd.getMode() == Mode.INOUT ||
+                    pd.getMode() == Mode.OUT && !isInput) {
+                if (!pd.isHeader() && !isSWAAttachment(pd)) {
+                    bodyIndex[i] = bi;
+                    bi++;
+                }
+            }
+        }
+        int totalBodyBlocks = bi;        
+        
+        // Now recalculate the bodyIndex array if the number of expected body parameters 
+        // does not match the incoming message.
+        if (message.getNumBodyBlocks() != totalBodyBlocks) {
+            calculateBodyIndex(bodyIndex, params, message.getBodyBlockQNames());
+        }
+        
+        // TODO What if return is an swa attachment, then this should start
+        // at 1 not 0.
+        int swaIndex = 0;
+        
+        for (int i = 0; i < params.length; i++) {
+            ParameterDescription pd = params[i];
+            
+            if (log.isDebugEnabled()) {
+                log.debug("  processing Parameter " + pd);
+            }
+            
+
+            if (pd.getMode() == Mode.IN && isInput ||
+                    pd.getMode() == Mode.INOUT ||
+                    pd.getMode() == Mode.OUT && !isInput) {
+
+                // Don't consider async handlers, they are are not represented on the wire,
+                // thus they don't have a PDElement
+                // TODO
+                //if (isAsyncHandler(param)) {
+                //    continue;
+                //}
+
+                Block block = null;
+                JAXBBlockContext context = new JAXBBlockContext(packages);
+
+                AttachmentDescription attachmentDesc = pd.getAttachmentDescription();
+                if (attachmentDesc == null) {
+                    
+                    // Normal Processing: Not an Attachment
+                    // Trigger unmarshal by java type if necessary
+                    if (unmarshalByJavaType != null && unmarshalByJavaType[i] != null) {
+                        context.setProcessType(unmarshalByJavaType[i]);
+                        context.setIsxmlList(pd.isListType());
+                    }
+                    
+                    // Unmarshal the object into a JAXB object or JAXBElement
+                    Element element = null;
+                    if (pd.isHeader()) {
+                        
+                        if (log.isDebugEnabled()) {
+                            log.debug("  get block from the headers");
+                        }
+                        // Get the Block from the header
+                        // NOTE The parameter name is always used to get the header 
+                        // element
+                        String localName = pd.getParameterName();
+                        block = message.getHeaderBlock(pd.getTargetNamespace(),
+                                                       localName,
+                                                       context,
+                                                       factory);
+                        element = new Element(block.getBusinessObject(true), 
+                                block.getQName());
+                    } else if (bodyIndex[i] >= 0) {
+                        if (totalBodyBlocks > 1) {
+                            if (log.isDebugEnabled()) {
+                                log.debug("  get block from the " + bodyIndex[i] +
+                                        " element in the body block");
+                            }
+                            // You must use this method if there are more than one body block
+                            // This method may cause OM expansion
+                            block = message.getBodyBlock(bodyIndex[i], context, factory);
+                        } else {
+                            if (log.isDebugEnabled()) {
+                                log.debug("  this is the only block in the body block");
+                            }
+                            // Use this method if you know there is only one body block.
+                            // This method prevents OM expansion.
+                            block = message.getBodyBlock(context, factory);
+                        }
+                        element = new Element(block.getBusinessObject(true), 
+                                block.getQName());
+                    } else {
+                        // Missing parameter
+                        if (log.isDebugEnabled()) {
+                            log.debug("  there is no block for this parameter.");
+                        }
+                        QName qName = new QName(pd.getTargetNamespace(), pd.getPartName());
+                        element = new Element(null, qName);
+                    }
+                    
+                    
+                    PDElement pde =
+                        new PDElement(pd, element, unmarshalByJavaType == null ? null
+                                : unmarshalByJavaType[i]);
+                    pdeList.add(pde);
+                } else {
+                    // Attachment Processing
+                    if (attachmentDesc.getAttachmentType() == AttachmentType.SWA) {
+                        String partName = pd.getPartName();
+                        String cid = null;
+                        if (log.isDebugEnabled()) {
+                            log.debug("Getting the attachment dataHandler for partName=" + partName);
+                        }
+                        if (partName != null && partName.length() > 0) {
+                            // Compliant WS-I behavior
+                            cid = message.getAttachmentID(partName);
+                        }
+                        if (cid == null) {
+                            if (log.isDebugEnabled()) {
+                                log.debug("Attachment dataHandler was not found.  Fallback to use attachment " + swaIndex);
+                            }
+                            // Toleration mode for non-compliant attachment names
+                            cid = message.getAttachmentID(swaIndex);
+                        }
+                        DataHandler dh = message.getDataHandler(cid);
+                        Attachment attachment = new Attachment(dh, cid);
+                        PDElement pde = new PDElement(pd, null, null, attachment);
+                        pdeList.add(pde);
+                        swaIndex++;
+                    } else {
+                        throw ExceptionFactory.makeWebServiceException(Messages.getMessage("pdElementErr"));
+                    }
+                }
+            }
+        }
+
+        if (log.isDebugEnabled()) {
+            log.debug("end getPDElementsWithMissingElements");
+        }
+        return pdeList;
+    }
+    
+    /**
+     * @param bodyIndex
+     * @param params
+     * @param qNames
+     */
+    private static void calculateBodyIndex(int[] bodyIndex, 
+            ParameterDescription[] params, 
+            List<QName> qNames) {
+        if (log.isDebugEnabled()) {
+            log.debug("Start calculateBodyIndex");
+            for (int i=0; i<qNames.size(); i++) {
+                log.debug("   QName " + i + " = " + qNames.get(i));
+            }
+        }
+        for (int pi=0; pi<params.length; pi++) {
+            if (pi >= 0) {
+                ParameterDescription pd = params[pi];
+                if (log.isDebugEnabled()) {
+                    log.debug("  ParameterDescription =" + pd.toString());
+                    log.debug("  original bodyIndex = " + bodyIndex[pi]);
+                }
+                bodyIndex[pi] = -1;  // Reset index
+                // Found a parameter that is expected in the body
+                // Calculate its index by looking for an exact qname match
+                for (int qi=0; qi<qNames.size(); qi++) {
+                    QName qName = qNames.get(qi);
+                    if (qName.getLocalPart().equals(pd.getPartName())) {
+                        if (qName.getNamespaceURI().equals(pd.getTargetNamespace())) {
+                            if(log.isDebugEnabled()) {
+                                log.debug("    found exact match with " + qName);
+                            }
+                            bodyIndex[pi] = qi;
+                        }
+                    }
+                }
+                // Fallback to searching for just the part name
+                if (bodyIndex[pi] < 0) {
+                    for (int qi=0; qi<qNames.size(); qi++) {
+                        QName qName = qNames.get(qi);
+                        if (qName.getLocalPart().equals(pd.getPartName())) {
+                            if(log.isDebugEnabled()) {
+                                log.debug("    found fallback match with " + qName);
+                            }
+                            bodyIndex[pi] = qi;
+                        }
+                    }
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug("  final bodyIndex = " + bodyIndex[pi]);
+                }
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("End calculateBodyIndex");
+        }
+    }
+    
+    /**
      * Creates the request signature arguments (server) from a list
-     * of element eabled object (PDEements)
+     * of element enabled object (PDEements)
      * @param pds ParameterDescriptions for this Operation
      * @param pvList Element enabled object
      * @return Signature Args

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/XMLPart.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/XMLPart.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/XMLPart.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/XMLPart.java Wed Jun 17 18:57:50 2009
@@ -197,6 +197,15 @@
      * @throws WebServiceException
      */
     public int getNumBodyBlocks() throws WebServiceException;
+    
+    /**
+     * getBodyBlockQNames 
+     * Calling this method will cache the OM.  Avoid it in performant situations.
+     *
+     * @return List of QNames
+     * @throws WebServiceException
+     */
+    public List<QName> getBodyBlockQNames() throws WebServiceException;
 
     /**
      * getBodyBlock Get the body block at the specificed index. The BlockFactory and object context are

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/MessageImpl.java Wed Jun 17 18:57:50 2009
@@ -508,6 +508,10 @@
         return xmlPart.getNumBodyBlocks();
     }
     
+    public List<QName> getBodyBlockQNames() throws WebServiceException {
+        return xmlPart.getBodyBlockQNames();
+    }
+    
     public int getNumHeaderBlocks() throws WebServiceException {
         return xmlPart.getNumHeaderBlocks();
     }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLPartBase.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLPartBase.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLPartBase.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLPartBase.java Wed Jun 17 18:57:50 2009
@@ -608,6 +608,17 @@
     public int getNumBodyBlocks() throws WebServiceException {
         return getContentAsXMLSpine().getNumBodyBlocks();
     }
+    
+    /**
+     * getBodyBlockQNames 
+     * Calling this method will cache the OM.  Avoid it in performant situations.
+     *
+     * @return List of QNames
+     * @throws WebServiceException
+     */
+    public List<QName> getBodyBlockQNames() throws WebServiceException {
+        return getContentAsXMLSpine().getBodyBlockQNames();
+    }
 
     /* (non-Javadoc)
       * @see org.apache.axis2.jaxws.message.XMLPart#getNumHeaderBlocks()

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpine.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpine.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpine.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpine.java Wed Jun 17 18:57:50 2009
@@ -48,7 +48,7 @@
     /**
      * Get the protocol for this Message (soap11, soap12, etc.)
      *
-     * @return Protocl
+     * @return Protocol
      */
     public Protocol getProtocol();
 
@@ -132,6 +132,15 @@
      * @throws WebServiceException
      */
     public int getNumBodyBlocks() throws WebServiceException;
+    
+    /**
+     * getBodyBlockQNames 
+     * Calling this method will cache the OM.  Avoid it in performant situations.
+     *
+     * @return List of QNames
+     * @throws WebServiceException
+     */
+    public List<QName> getBodyBlockQNames() throws WebServiceException;
 
     /**
      * getBodyBlock Get the body block at the specificed index. The BlockFactory and object 

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpineImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpineImpl.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpineImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/impl/XMLSpineImpl.java Wed Jun 17 18:57:50 2009
@@ -269,6 +269,26 @@
     public int getNumBodyBlocks() throws WebServiceException {
         return _getNumChildElements(_getBodyBlockParent());
     }
+    
+    /**
+     * getBodyBlockQNames 
+     * Calling this method will cache the OM.  Avoid it in performant situations.
+     *
+     * @return List of QNames
+     * @throws WebServiceException
+     */
+    public List<QName> getBodyBlockQNames() throws WebServiceException {
+        int numBlocks = getNumBodyBlocks();
+        List<QName> qNames = new ArrayList<QName>();
+        
+        for (int i =0; i< numBlocks; i++ ) {
+            OMElement omElement = _getChildOMElement(_getBodyBlockParent(), i);
+            if (omElement != null) {
+                qNames.add(omElement.getQName());
+            } 
+        }
+        return qNames;
+    }
 
 
     /* (non-Javadoc)

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ParameterDescriptionImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ParameterDescriptionImpl.java?rev=785755&r1=785754&r2=785755&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ParameterDescriptionImpl.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/ParameterDescriptionImpl.java Wed Jun 17 18:57:50 2009
@@ -350,6 +350,11 @@
             string.append("Name: " + getParameterName());
             //
             string.append(newline);
+            string.append("Namespace: " + getTargetNamespace());
+            string.append(newline);
+            string.append("PartName: " + getPartName());
+            //
+            string.append(newline);
             string.append("Is header: " + (isHeader() == true));
             string.append(sameline);
             string.append("Is holder: " + (isHolderType() == true));