You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by sc...@apache.org on 2007/01/21 07:55:28 UTC

svn commit: r498250 - in /webservices/axis2/trunk/java/modules: jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/ jaxws/src/org/apache/axis2/jaxws/wrapper/ jaxws/src/org/apache/axis2/jaxws/wrapper/impl/ jaxws/test-resources/wsdl/ jaxws/test/org/apa...

Author: scheu
Date: Sat Jan 20 22:55:27 2007
New Revision: 498250

URL: http://svn.apache.org/viewvc?view=rev&rev=498250
Log:
JIRA-1799
Contributor: Rich Scheuerle
Added legacy exception detection, marshalling and demarshalling.  Corrected @WebFault faultBean defaults.  Added/changed some tests.

Added:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/LegacyExceptionUtil.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/PropertyInfo.java
      - copied, changed from r498044, webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java
    webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/jaxws/SubPackageExceptionBean.java
Removed:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java
Modified:
    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/wrapper/impl/JAXBWrapperToolImpl.java
    webservices/axis2/trunk/java/modules/jaxws/test-resources/wsdl/FaultsService.wsdl
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/FaultsServiceTests.java
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/InvalidTickerFault_Exception.java
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/META-INF/FaultsService.wsdl
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionUtils.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/FaultDescriptionImpl.java
    webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/OperationDescriptionImpl.java
    webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/WrapperPackageTests.java

Added: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/LegacyExceptionUtil.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/LegacyExceptionUtil.java?view=auto&rev=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/LegacyExceptionUtil.java (added)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/marshaller/impl/alt/LegacyExceptionUtil.java Sat Jan 20 22:55:27 2007
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ * Copyright 2006 International Business Machines Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.axis2.jaxws.marshaller.impl.alt;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.xml.ws.WebServiceException;
+
+import org.apache.axis2.jaxws.ExceptionFactory;
+import org.apache.axis2.jaxws.description.FaultDescription;
+import org.apache.axis2.jaxws.util.ClassUtils;
+import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
+import org.apache.axis2.jaxws.wrapper.PropertyInfo;
+import org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperToolImpl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * The JAX-WS Specification (chapter 3.7) indicates that JAX-WS
+ * supports exceptions that do not match the normal pattern (the normal
+ * pattern is defined in chapter 2.5.  
+ * 
+ * These non-matching exceptions are the result of running WSGen
+ * on a pre-existing webservice.  I am going to use the term, legacy exception,
+ * to describe these non-matching exceptions.
+ * 
+ * The JAX-WS marshaller (server) must marshal a legacy exception thrown from
+ * the web service impl.  The marshalling/mapping algorithm is defined in chapter 3.7.
+ * 
+ * On the client, the JAX-WS engine will need to demarshal exceptions.  However
+ * the specification assumes that the client is always created via wsimport; therefore
+ * the assumption is that all exceptions on the client are compliant (never legacy exceptions).
+ * I have included some code here in case we have to deal with legacy exceptions on the client...this is non-spec.
+ * 
+ *
+ */
+/**
+ * @author scheu
+ *
+ */
+class LegacyExceptionUtil {
+
+    private static Log log = LogFactory.getLog(LegacyExceptionUtil.class);
+    
+    private static Set<String> ignore = new HashSet<String>();
+    static {
+        // Per Chap 3.7 rule 3, ignore these properties on the exception
+        ignore.add("localizedMessage");
+        ignore.add("stackTrace");
+        ignore.add("class");
+        ignore.add("cause");
+    }
+    
+    /**
+     * Static class.  Constructor is intentionally private
+     */
+    private LegacyExceptionUtil() {}
+    
+    /**
+     * A compliant exception has a @WebFault annotation and a getFaultInfo method.
+     * Legacy exceptions do not.
+     * @param cls
+     * @return true if legacy exception
+     * REVIEW perhaps this detection should be in FaultDescription
+     */
+    static boolean isLegacyException(Class cls) {
+        boolean legacyException = false;
+        
+        try {
+            Method getFaultInfo = cls.getMethod("getFaultInfo", null);
+        } catch (Exception e) {
+            // Failure indicates that this is not a legacy exception
+            legacyException = true;
+        }
+        if (legacyException) {
+            if (log.isDebugEnabled()) {
+                log.debug("Detected Legacy Exception = " + cls);
+            }
+        }
+        return legacyException;
+    }
+    
+    /**
+     * Create a FaultBean populated with the data from the Exception t
+     * The algorithm used to populate the FaultBean is described in 
+     * JAX-WS 3.7
+     * @param t
+     * @param fd
+     * @return faultBean
+     */
+    static Object createFaultBean(Throwable t, FaultDescription fd) throws WebServiceException {
+        
+        Object faultBean = null;
+        try {
+            // Get the fault bean name from the fault description.
+            // REVIEW The default name should be:
+            //      Package = <SEI package> or <SEI package>.jaxws
+            //      Name = <exception name> + Bean
+            String faultBeanName = fd.getFaultBean();
+            
+            // TODO Add check that faultBeanName is correct
+            if (log.isDebugEnabled()) {
+                log.debug("Legacy Exception Bean name is = " + faultBeanName);
+            }
+            
+            // Load the FaultBean Class
+            Class faultBeanClass = MethodMarshallerUtils.loadClass(faultBeanName);
+            
+            // We need to assign the legacy exception data to the java bean class.
+            // We will use the JAXBWrapperTool.wrap utility to do this.
+            
+            // Get the map of child objects
+            Map<String, Object> childObjects = getChildObjectsMap(t);
+            
+            List<String> childNames = new ArrayList<String>(childObjects.keySet());
+            
+            if (log.isErrorEnabled()) {
+                log.debug("List of properties on the Legacy Exception is " + childNames);
+            }
+            // Use the wrapper tool to get the child objects.
+            JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
+            faultBean = wrapperTool.wrap(faultBeanClass, childNames, childObjects);
+            if (log.isErrorEnabled()) {
+                log.debug("Completed creation of the fault bean.");
+            }
+            
+        } catch (Exception e) {
+            throw ExceptionFactory.makeWebServiceException(e);
+        }
+        return faultBean;
+    }
+    
+    /**
+     * Create an Exception using the data in the JAXB object.  
+     * The specification is silent on this issue.
+     * @param exceptionClass
+     * @param jaxb
+     * @return
+     */
+    static Exception createFaultException(Class exceptionClass, Object jaxb) {
+        Exception e = null;
+        try {
+            if (log.isErrorEnabled()) {
+                log.debug("Create Legacy Exception for " + exceptionClass.getName());
+            }
+            // Get the properties names from the exception class
+            Map<String, PropertyInfo> piMap = getPropertyInfoMap(exceptionClass);
+            
+            // Now get a list of PropertyInfo objects that map to the jaxb bean properties
+            Iterator<Entry<String, PropertyInfo>> it = piMap.entrySet().iterator();
+            List<PropertyInfo> piList= new ArrayList<PropertyInfo>();
+            while (it.hasNext()) {
+                Entry<String, PropertyInfo> entry = it.next();
+                String propertyName = entry.getKey();
+                // Some propertyNames should be ignored.
+                if (!ignore.contains(propertyName)) {
+                    piList.add(entry.getValue());
+                }
+            }
+            
+            // Find a matching constructor
+            List<String>  childNames = new ArrayList<String>();
+            if (log.isErrorEnabled()) {
+                log.debug("List of childNames on legacy exception is " + childNames);
+            }
+            Constructor constructor = findConstructor(exceptionClass, piList, childNames);
+            
+            if (log.isErrorEnabled()) {
+                log.debug("The constructor used to create the exception is " + constructor);
+            }
+            // Use the wrapper tool to unwrap the jaxb object
+            JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
+            Object[] childObjects = wrapperTool.unWrap(jaxb, childNames);
+            
+            if (log.isErrorEnabled()) {
+                log.debug("Calling newInstance on the constructor " + constructor);
+            }
+            e = (Exception) constructor.newInstance(childObjects);
+        } catch (Exception ex) {
+            throw ExceptionFactory.makeWebServiceException(ex);
+        }
+        return e;
+    }
+    
+    /**
+     * Find a construcor that matches this set of properties
+     * @param cls
+     * @param piList
+     * @param childNames returned in the order that they occur in the constructor
+     * @return Constructor or null
+     */
+    private static Constructor findConstructor(Class cls, List<PropertyInfo> piList, List<String> childNames) {
+        Constructor[] constructors = cls.getConstructors();
+        Constructor constructor = null;
+        if (constructors != null) {
+            for (int i=0; i<constructors.length && constructor == null; i++) {
+                Constructor tryConstructor = constructors[i];
+                if (tryConstructor.getParameterTypes().length  == piList.size()) {
+                    // Try and find the best match using the property types
+                    List<PropertyInfo> list = new ArrayList<PropertyInfo>(piList);
+                    List<PropertyInfo> args = new ArrayList<PropertyInfo>();
+                    
+                    Class[] parms = tryConstructor.getParameterTypes();
+                    boolean valid= true;
+                    
+                    // Assume the message is first in the constructor
+                    for (int j=0; j<list.size(); j++) {
+                        if ("message".equals(list.get(j).getPropertyName())) {
+                            args.add(list.remove(j));
+                        }
+                    }
+                    if (args.size() != 1 ||
+                        !parms[0].isAssignableFrom(args.get(0).getPropertyType())) {
+                        valid = false;
+                    }
+                    
+                    // Now process the rest of the args
+                    for (int j=1; j<parms.length && valid; j++) {
+                        // Find a compatible argument
+                        Class parm = parms[j];
+                        boolean found = false;
+                        for (int k=0; k<list.size() && !found; k++) {
+                            Class arg = list.get(k).getPropertyType();
+                            if (parm.isAssignableFrom(arg)) {
+                                found = true;
+                                args.add(list.remove(k));
+                            }
+                        }
+                        // If no compatible argument then this constructor is not valid
+                        if (!found) {
+                            valid = false;   
+                        }
+                    }
+                    // A constructor is found
+                    if (valid) {
+                        constructor = tryConstructor;
+                        for (int index = 0; index<args.size(); index++) {
+                            childNames.add(args.get(index).getPropertyName());
+                        }
+                    }
+                }
+            }
+        }
+        
+        return constructor;
+    }
+    
+    
+    /**
+     * Get the child objects map that is required by the wrapper tool.
+     * @param t Exception
+     * @return Map with key is bean property names and values are objects from the Exception
+     * @throws IntrospectionException
+     */
+    private static Map<String, Object> getChildObjectsMap(Throwable t) 
+        throws IntrospectionException, InvocationTargetException, IllegalAccessException {
+        
+        Map<String, PropertyInfo> piMap = getPropertyInfoMap(t.getClass());
+        
+        Map<String, Object> coMap = new HashMap<String, Object>();
+        
+        Iterator<Entry<String, PropertyInfo>> it = piMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Entry<String, PropertyInfo> entry = it.next();
+            String propertyName = entry.getKey();
+            // Some propertyNames should be ignored.
+            if (!ignore.contains(propertyName)) {
+                Object value = entry.getValue().get(t);
+                coMap.put(propertyName, value);
+            }
+        }
+        return coMap;
+    }
+    
+    /**
+     * Get a Map<String, PropertyInfo> for the specified exception
+     * @param t
+     * @return Map<String, PropertyInfo>
+     */
+    private static Map<String, PropertyInfo> getPropertyInfoMap(Class cls) throws IntrospectionException {
+        // TODO Performance Alert
+        // Get a PropertyInfo Map.  Perhaps this should be cached on the FaultDesc for performance
+        PropertyDescriptor[] pds = Introspector.getBeanInfo(cls).getPropertyDescriptors();
+        
+        Map<String, PropertyInfo> piMap = new HashMap<String, PropertyInfo>();
+        if (pds != null) {
+            for (int i=0; i< pds.length; i++) {
+                PropertyInfo pi = new PropertyInfo(pds[i]);
+                piMap.put(pds[i].getName(), pi);
+            }
+        }
+        return piMap;
+    }
+    
+    
+}

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?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- 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 Sat Jan 20 22:55:27 2007
@@ -452,9 +452,12 @@
         // Get the FaultDescriptor matching this Exception.
         // If FaultDescriptor is found, this is a JAX-B Service Exception.
         // If not found, this is a System Exception
-        FaultDescription fd = operationDesc.resolveFaultByExceptionName(t.getClass().getName());
+        FaultDescription fd = operationDesc.resolveFaultByExceptionName(t.getClass().getCanonicalName());
 
         if (t instanceof SOAPFaultException) {
+            if (log.isErrorEnabled()) {
+                log.debug("Marshal SOAPFaultException");
+            }
             // Category C: SOAPFaultException 
             // Construct the xmlFault from the SOAPFaultException's Fault
             SOAPFaultException sfe = (SOAPFaultException) t;
@@ -468,13 +471,30 @@
             }
             
         } else if (fd != null) {
+            if (log.isErrorEnabled()) {
+                log.debug("Marshal as a Service Exception");
+            }
             // The exception is a Service Exception.  It may be (A) JAX-WS compliant exception or (B) JAX-WS legacy exception
             
-            // TODO Need to add detection and code to differentiate between (A) and (B)
+            // The faultBeanObject is a JAXB object that represents the data of the exception.  It is marshalled in the detail
+            // section of the soap fault.  The faultBeanObject is obtained direction from the exception (A) or via 
+            // the legacy exception rules (B).
+            Object faultBeanObject = null;
+       
+            if (LegacyExceptionUtil.isLegacyException(t.getClass())) {
+                // Legacy Exception case
+                faultBeanObject = LegacyExceptionUtil.createFaultBean(t, fd);
+            } else {
+                // Normal case
+                // Get the fault bean object.  
+                Method getFaultInfo = t.getClass().getMethod("getFaultInfo", null);
+                faultBeanObject = getFaultInfo.invoke(t, null);
+            }
             
-            // Get the fault bean object.  Make sure it can be rendered as an element
-            Method getFaultInfo = t.getClass().getMethod("getFaultInfo", null);
-            Object faultBeanObject = getFaultInfo.invoke(t, null);
+            if (log.isErrorEnabled()) {
+                log.debug("The faultBean type is" + faultBeanObject.getClass().getName());
+            }
+            // Make sure the faultBeanObject can be marshalled as an element
             if (!XMLRootElementUtil.isElementEnabled(faultBeanObject.getClass())) {
                 faultBeanObject = XMLRootElementUtil.getElementEnabledObject(fd.getTargetNamespace(), fd.getName(), 
                         faultBeanObject.getClass(), faultBeanObject);
@@ -492,9 +512,15 @@
             Block[] detailBlocks = new Block[1];
             detailBlocks[0] = factory.createFrom(faultBeanObject,context,null);
             
+            if (log.isErrorEnabled()) {
+                log.debug("Create the xmlFault for the Service Exception");
+            }
             // Now make a XMLFault containing the detailblock
             xmlfault = new XMLFault(null, new XMLFaultReason(t.getMessage()), detailBlocks);
         } else if (t instanceof WebServiceException) {
+            if (log.isErrorEnabled()) {
+                log.debug("Marshal as a WebServiceException");
+            }
             // Category D: WebServiceException
             // The reason is constructed with the getMessage of the exception.  
             // There is no detail
@@ -502,6 +528,9 @@
             xmlfault = new XMLFault(null,       // Use the default XMLFaultCode
                     new XMLFaultReason(wse.getMessage()));  // Assumes text is the language supported by the current Locale
         } else {
+            if (log.isErrorEnabled()) {
+                log.debug("Marshal as a unchecked System Exception");
+            }
             // Category E: Other System Exception
             // The reason is constructed with the toString of the exception.  
             // This places the class name of the exception in the reason
@@ -556,7 +585,10 @@
             // This is a system exception if the method does not throw a checked exception or if 
             // the detail block is missing or contains multiple items.
             exception = createSystemException(xmlfault, message);
-        } else {            
+        } else {        
+            if (log.isErrorEnabled()) {
+                log.debug("Ready to demarshal service exception.  The detail entry name is " + elementName);
+            }
             // Get the JAXB object from the block
             JAXBBlockContext blockContext = new JAXBBlockContext(packages);        
             
@@ -602,23 +634,34 @@
                 faultBeanQName = XMLRootElementUtil.getXmlRootElementQName(faultBeanObject);
             }
             
+            if (log.isErrorEnabled()) {
+                log.debug("Searching for the matching FaultDescription");
+            }
             // Using the faultBeanQName, find the matching faultDescription 
             FaultDescription faultDesc = null;
             for(int i=0; i<operationDesc.getFaultDescriptions().length && faultDesc == null; i++) {
                 FaultDescription fd = operationDesc.getFaultDescriptions()[i];
                 QName tryQName = new QName(fd.getTargetNamespace(), fd.getName());
-                                
+                if (log.isErrorEnabled()) {
+                    log.debug("  FaultDescription qname is (" + tryQName + ") and demarshalled bean qname is (" + faultBeanQName + ")");
+                }
                 if (faultBeanQName == null || faultBeanQName.equals(tryQName)) {
                     faultDesc = fd;
                     
                 }
             }
             if (faultDesc == null) {
+                if (log.isErrorEnabled()) {
+                    log.debug("A FaultDescription was not found");
+                }
                 throw ExceptionFactory.makeWebServiceException(Messages.getMessage("MethodMarshallerErr1", faultBeanObject.getClass().toString()));
             }
             
             // Construct the JAX-WS generated exception that holds the faultBeanObject
             Class exceptionClass = loadClass(faultDesc.getExceptionClassName());
+            if (log.isErrorEnabled()) {
+                log.debug("Found FaultDescription.  The exception name is " + exceptionClass.getName());
+            }
             Class faultBeanFormalClass = loadClass(faultDesc.getFaultBean());  // Note that faultBean may not be a bean, it could be a primitive     
             exception =createServiceException(xmlfault.getReason().getText(), exceptionClass, faultBeanObject, faultBeanFormalClass);
         }
@@ -691,15 +734,21 @@
      * @throws NoSuchMethodException
      */
     private static Exception createServiceException(String message, Class exceptionclass, Object bean, Class beanFormalType) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
-        // All webservice exception classes are required to have a constructor that takes a (String, bean) argument
-        // TODO necessary to be more careful here with instantiating, casting, etc?
+        
         if (log.isDebugEnabled()) {
             log.debug("Constructing JAX-WS Exception:" + exceptionclass);
         }
-        Constructor constructor = exceptionclass.getConstructor(new Class[] { String.class, beanFormalType });
-        Object exception = constructor.newInstance(new Object[] { message, bean });
+        Exception exception = null;
+        if (LegacyExceptionUtil.isLegacyException(exceptionclass)) {
+            // Legacy Exception
+            exception = LegacyExceptionUtil.createFaultException(exceptionclass, bean);
+        } else {
+            // Normal case, use the contstructor to create the exception
+            Constructor constructor = exceptionclass.getConstructor(new Class[] { String.class, beanFormalType });
+            exception = (Exception) constructor.newInstance(new Object[] { message, bean });
+        }
 
-        return (Exception) exception;
+        return exception;
 
     }
     

Copied: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/PropertyInfo.java (from r498044, webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java)
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/PropertyInfo.java?view=diff&rev=498250&p1=webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java&r1=498044&p2=webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/PropertyInfo.java&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/PropertyInfo.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/PropertyInfo.java Sat Jan 20 22:55:27 2007
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.axis2.jaxws.wrapper.impl;
+package org.apache.axis2.jaxws.wrapper;
 
 import java.beans.IndexedPropertyDescriptor;
 import java.beans.PropertyDescriptor;
@@ -26,6 +26,7 @@
 import org.apache.axis2.jaxws.ExceptionFactory;
 import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.axis2.jaxws.util.ConvertUtils;
+import org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -36,6 +37,8 @@
  */
 public class PropertyInfo {
 	PropertyDescriptor descriptor;
+    Class propertyType = null;
+    String propertyName = null;
 	private static Log log = LogFactory.getLog(PropertyInfo.class);
 	/**
 	 * @param propertyName
@@ -46,6 +49,27 @@
 		this.descriptor = descriptor;
 	}
 	
+    /**
+     * @return property type
+     */
+    public Class getPropertyType() {
+        // Get once and remember so that we can avoid syncronization penalties
+        if (propertyType == null) {
+            propertyType = descriptor.getPropertyType();
+        }
+        return propertyType;
+    }
+    
+    /**
+     * @return property name
+     */
+    public String getPropertyName() {
+        // Get once and remember so that we can avoid syncronization penalties
+        if (propertyName == null) {
+            propertyName = descriptor.getName();
+        }
+        return propertyName;
+    }
 	
 	/**
      * Get the object 

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/wrapper/impl/JAXBWrapperToolImpl.java Sat Jan 20 22:55:27 2007
@@ -31,6 +31,7 @@
 import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.axis2.jaxws.util.XMLRootElementUtil;
 import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
+import org.apache.axis2.jaxws.wrapper.PropertyInfo;
 
 public class JAXBWrapperToolImpl implements JAXBWrapperTool {
 
@@ -134,6 +135,9 @@
         // It is possible the that the number of fields is greater than the number of child elements due
         // to customizations.
 		if(field.length < childNames.size()){
+            // TODO we may want to allow the case where the childNames contains the "message" and
+            // the jaxb object does not.  Scenaio: jaxbClass is a faultBean for an exception, but
+            // does not map "message" because "message" is passed in the faultstring.
 			throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr4", jaxbClass.getName()));
 		}
         

Modified: webservices/axis2/trunk/java/modules/jaxws/test-resources/wsdl/FaultsService.wsdl
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test-resources/wsdl/FaultsService.wsdl?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test-resources/wsdl/FaultsService.wsdl (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test-resources/wsdl/FaultsService.wsdl Sat Jan 20 22:55:27 2007
@@ -11,13 +11,15 @@
     <xsd:schema targetNamespace="http://org/test/polymorphicfaults">
         
       <xsd:element name="SimpleFault" type="xsd:int"/>
-      <xsd:element name="InvalidTickerFault" type="ts:InvalidTickerFaultBean"/>
-      <xsd:complexType name="InvalidTickerFaultBean">
+      <xsd:element name="InvalidTickerFault" type="ts:InvalidTickerFault_ExceptionBean"/>
+      <xsd:complexType name="InvalidTickerFault_ExceptionBean">
         <xsd:sequence>
            <xsd:element name="legacyData1" type="xsd:string" />
            <xsd:element name="legacyData2" type="xsd:int" />
+           <xsd:element name="message" type="xsd:string" />
         </xsd:sequence>
       </xsd:complexType>
+
 
       <xsd:element name="BaseFault" type="ts:BaseFault"/>
       <xsd:complexType name="BaseFault">

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/FaultsServiceTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/FaultsServiceTests.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/FaultsServiceTests.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/FaultsServiceTests.java Sat Jan 20 22:55:27 2007
@@ -171,7 +171,7 @@
      * Test throwing legacy fault
      * Disabled while I fix this test
      */
-    public void _testFaultsService5(){
+    public void testFaultsService5(){
         Exception exception = null;
         try{
             FaultsServicePortType proxy = getProxy();

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/InvalidTickerFault_Exception.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/InvalidTickerFault_Exception.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/InvalidTickerFault_Exception.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/InvalidTickerFault_Exception.java Sat Jan 20 22:55:27 2007
@@ -4,13 +4,16 @@
 import javax.xml.ws.WebFault;
 
 /**
- * This is an example of a legacy exception (InvalidTickerFault) which may be the result of a JAX-RPC emission.
+ * This is an example of a legacy exception  which may be the result of a JAX-RPC emission.
  * The fault does not have the valid constructors and lacks a getFaultInfo method.
  * However (in this case) the fault has a @WebFault that identifies the faultbean
  */
 @WebFault(name = "InvalidTickerFault", 
         targetNamespace = "http://org/test/polymorphicfaults",
-        faultBean="org.test.polymorphicfaults.InvalidTickerFaultBean")
+        faultBean="org.test.polymorphicfaults.InvalidTickerFaultExceptionBean")
+        
+        // faultBean is intentionally not specified. It should default to 
+        // faultBean="org.test.polymorphicfaults.InvalidTickerFault_ExceptionBean"
 public class InvalidTickerFault_Exception
     extends Exception
 {

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/META-INF/FaultsService.wsdl
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/META-INF/FaultsService.wsdl?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/META-INF/FaultsService.wsdl (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/sample/faultsservice/META-INF/FaultsService.wsdl Sat Jan 20 22:55:27 2007
@@ -11,11 +11,12 @@
     <xsd:schema targetNamespace="http://org/test/polymorphicfaults">
         
       <xsd:element name="SimpleFault" type="xsd:int"/>
-      <xsd:element name="InvalidTickerFault" type="ts:InvalidTickerFaultBean"/>
-      <xsd:complexType name="InvalidTickerFaultBean">
+      <xsd:element name="InvalidTickerFault" type="ts:InvalidTickerFault_ExceptionBean"/>
+      <xsd:complexType name="InvalidTickerFault_ExceptionBean">
         <xsd:sequence>
            <xsd:element name="legacyData1" type="xsd:string" />
            <xsd:element name="legacyData2" type="xsd:int" />
+           <xsd:element name="message" type="xsd:string" />
         </xsd:sequence>
       </xsd:complexType>
 

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionUtils.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionUtils.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/DescriptionUtils.java Sat Jan 20 22:55:27 2007
@@ -264,4 +264,59 @@
     	}
     	return true;
     }
+
+    /**
+     * Determine the actual packager name for the generated artifacts by trying to load the class from one of two
+     * packages.  This is necessary because the RI implementations of WSGen and WSImport generate the artifacts 
+     * in different packages:
+     * - WSImport generates the artifacts in the same package as the SEI
+     * - WSGen generates the artifacts in a "jaxws" sub package under the SEI package.
+     * Note that from reading the JAX-WS spec, it seems that WSGen is doing that correctly; See
+     * the conformance requirement in JAX-WS 2.0 Spec Section 3.6.2.1 Document Wrapped on page 36:
+     *     Conformance (Default wrapper bean package): In the absence of customizations, the wrapper beans package
+     *     MUST be a generated jaxws subpackage of the SEI package.
+     *                         ^^^^^^^^^^^^^^^^
+     * @param requestWrapperClassName
+     * @return
+     */
+    static final String JAXWS_SUBPACKAGE = "jaxws";
+    static String determineActualAritfactPackage(String wrapperClassName) {
+        String returnWrapperClassName = null;
+    
+        // Try to load the class that was passed in
+        try {
+            loadClass(wrapperClassName);
+            returnWrapperClassName = wrapperClassName;
+        }
+        catch (ClassNotFoundException e) {
+            // Couldn't load the class; we'll try another one below.
+        }
+    
+        // If the original class couldn't be loaded, try adding ".jaxws." to the package
+        if (returnWrapperClassName == null) {
+            String originalPackage = getJavaPackageName(wrapperClassName);
+            if (originalPackage != null) {
+                String alternatePackage = originalPackage + "." + DescriptionUtils.JAXWS_SUBPACKAGE;
+                String className = getSimpleJavaClassName(wrapperClassName);
+                String alternateWrapperClass = alternatePackage + "." + className;
+                try {
+                    loadClass(alternateWrapperClass);
+                    returnWrapperClassName = alternateWrapperClass;
+                }
+                catch (ClassNotFoundException e) {
+                    // Couldn't load the class
+                }
+            }
+        }
+        
+        if (returnWrapperClassName == null){
+            // Couldn't load either class, so stick with the original wrapper class name
+            // REVIEW: Is this correct behavior?  Note that some of the annotation unit tests don't have the actual
+            //         classes available, and so will fail if this is changed.
+            returnWrapperClassName = wrapperClassName;
+        }
+        return returnWrapperClassName;
+    }
+
+    
 }

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/FaultDescriptionImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/FaultDescriptionImpl.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/FaultDescriptionImpl.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/FaultDescriptionImpl.java Sat Jan 20 22:55:27 2007
@@ -19,8 +19,10 @@
 package org.apache.axis2.jaxws.description.impl;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 import java.util.StringTokenizer;
 
+import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.ws.WebFault;
 
 import org.apache.axis2.jaxws.description.FaultDescription;
@@ -28,6 +30,7 @@
 import org.apache.axis2.jaxws.description.FaultDescriptionWSDL;
 import org.apache.axis2.jaxws.description.OperationDescription;
 import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
+import org.apache.axis2.jaxws.description.builder.MethodDescriptionComposite;
 
 /**
  * @see ../FaultDescription
@@ -83,51 +86,55 @@
         return annotation;
     }
 
+    
     public String getFaultBean() {
         if (faultBean.length() > 0) {
+            // Return the faultBean if it was already calculated
             return faultBean;
-        }
-        else if (annotation.faultBean().length() > 0) {
-            faultBean = annotation.faultBean();
-        }
-        else {
-            /*
-             * we need to figure out a default.  The JAXWS spec
-             * has no defaults defined, except what can be interpreted
-             * from 2.5, 2.8, 2.8.1, and 7.2
-             *
-             * specifically, section 2.5 says "using the mapping
-             * described in section 2.4."
-             * 
-             * I have a better way:
-             * The exception class defined by the JAXWS spec has two constructors where the second parameter
-             * of each is the faultBean.  Let's see if we can figure what the faultBean is from that:
-             */
-
-        	if (!isDBC()) {
-        		try {
-        			Constructor[] cons = exceptionClass.getConstructors();
-        			Class[] parms = cons[0].getParameterTypes();
-        			faultBean = parms[1].getCanonicalName();
-        		} catch (Exception e) {
-        			/* 
-        			 * if faultBean is still not set, then something is wrong with the exception
-        			 * class that the code generators generated, or someone instantiated a FaultDescription
-        			 * object for a generic exception.
-        			 *
-        			 * TODO log it?  I don't think we need to worry about throwing an exception here, as we're just
-        			 * doing a best-effort to determine the faultBean name.  If the try{} fails, something is really
-        			 * messed up in the generated code anyway, and I suspect nothing would work right.
-        			 */
-        		}
-        		
-        		// If all else fails, this might get us what we want:
-        		if ((faultBean == null) || (faultBean.length() == 0))
-        			faultBean = getOperationDescription().getRequestWrapperClassName().toString() + FAULT;
-        	} else {
-        		//REVIEW: Need to verify that this is the name we need...hmm, seems to easy
-        		faultBean = composite.getClassName();
-        	}
+        } else {
+            // Load up the WebFault annotation and get the faultBean.
+            // @WebFault may not be present
+            WebFault annotation = getAnnoWebFault();
+            
+            if (annotation != null &&
+                annotation.faultBean().length() > 0) {
+                faultBean = annotation.faultBean();
+            } else {
+                // We don't have a faultBean. Try looking at the getFaultInfo method.
+                if (!isDBC()) {
+                    try {
+                        Method method = exceptionClass.getMethod("getFaultInfo", null);
+                        faultBean = method.getReturnType().getCanonicalName();
+                    } catch (Exception e) {
+                        // This must be a legacy exception
+                    }
+                }  else {
+                    MethodDescriptionComposite mdc = 
+                        composite.getMethodDescriptionComposite("getFaultInfo", 1);
+                    if (mdc != null) {
+                        faultBean = mdc.getReturnType();
+                    }
+                }
+                
+                // Still not found, this must be a non-compliant exception.
+                // Use the JAX-WS chap 3.7 algorithm
+                if (faultBean.length() <= 0) {
+                    String simpleName = getSimpleName(getExceptionClassName()) + "Bean";
+                    String packageName = null;
+                    if (!isDBC()) {
+                        Class clazz = getOperationDescription().getSEIMethod().getDeclaringClass();
+                        packageName = clazz.getPackage().getName();
+                    } else {
+                        // Similar algorithm as the OperationDesc RequestWrapper and ResponseWrapper
+                        String declaringClazz = ((OperationDescriptionImpl )getOperationDescription()).getMethodDescriptionComposite().getDeclaringClass();
+                        packageName = declaringClazz.substring(0, declaringClazz.lastIndexOf("."));
+                    }
+                    faultBean = packageName + "." + simpleName;
+                    
+                    // The following call adjusts the package name if necessary
+                    faultBean = DescriptionUtils.determineActualAritfactPackage(faultBean);
+                }
+            }
         }
         return faultBean;
     }
@@ -135,13 +142,24 @@
     public String getName() {
         if (name.length() > 0) {
             return name;
-        }
-        else if (annotation.name().length() > 0) {
-            name = annotation.name();
-        }
-        else {
-            // need to figure out a default.  Let's use the logic in getFaultBean()
-            name = getSimpleName(getFaultBean());
+        } else {
+            // Load the annotation. The annotation may not be present in WSGen cases
+            WebFault annotation = this.getAnnoWebFault();
+            if (annotation != null && 
+                annotation.name().length() > 0) {
+                name = annotation.name();
+            } else {
+                // The default is the name on the @XmlRootElement of the FaultBean since this
+                // is what is flowed over the wire.
+                try {
+                    Class clazz = DescriptionUtils.loadClass(getFaultBean());
+                    XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class);
+                    name = root.name();
+                } catch (Exception e) {
+                    // All else fails use the faultBean name
+                    name = getSimpleName(getFaultBean());
+                }
+            }
         }
         return name;
     }
@@ -149,15 +167,24 @@
     public String getTargetNamespace() {
         if (targetNamespace.length() > 0) {
             return targetNamespace;
-        }
-        else if (annotation.targetNamespace().length() > 0) {
-            targetNamespace = annotation.targetNamespace();
-        }
-        else {
-            // need to figure out a default.  Let's use the logic in getFaultBean() 
-        	//and make a namespace out of the package
-            
-            targetNamespace = makeNamespace(getFaultBean());
+        } else {
+            // Load the annotation. The annotation may not be present in WSGen cases
+            WebFault annotation = this.getAnnoWebFault();
+            if (annotation != null && 
+                annotation.targetNamespace().length() > 0) {
+                targetNamespace = annotation.targetNamespace();
+            } else {
+                // The default is the namespace on the @XmlRootElement of the FaultBean since this
+                // is what is flowed over the wire.
+                try {
+                    Class clazz = DescriptionUtils.loadClass(getFaultBean());
+                    XmlRootElement root = (XmlRootElement) clazz.getAnnotation(XmlRootElement.class);
+                    targetNamespace = root.namespace();
+                } catch (Exception e) {
+                    // All else fails use the faultBean to calculate a namespace
+                    targetNamespace = makeNamespace(getFaultBean());
+                }
+            }
         }
         return targetNamespace;
     }

Modified: webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/OperationDescriptionImpl.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/OperationDescriptionImpl.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/OperationDescriptionImpl.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/src/org/apache/axis2/jaxws/description/impl/OperationDescriptionImpl.java Sat Jan 20 22:55:27 2007
@@ -617,7 +617,7 @@
                     String className = DescriptionUtils.javaMethodtoClassName(seiMethod.getName());
                     requestWrapperClassName = packageName + "." + className;
                 }
-                requestWrapperClassName = determineActualAritfactPackage(requestWrapperClassName);
+                requestWrapperClassName = DescriptionUtils.determineActualAritfactPackage(requestWrapperClassName);
             }
         }
         return requestWrapperClassName;
@@ -724,7 +724,7 @@
                 	String packageName = declaringClazz.substring(0, declaringClazz.lastIndexOf("."));
                     responseWrapperClassName = packageName + "." + DescriptionUtils.javaMethodtoClassName(methodComposite.getMethodName()) + "Response";
                 }
-                responseWrapperClassName = determineActualAritfactPackage(responseWrapperClassName);
+                responseWrapperClassName = DescriptionUtils.determineActualAritfactPackage(responseWrapperClassName);
             }
         }
         return responseWrapperClassName;
@@ -1096,59 +1096,6 @@
             return true;
         else
             return false;
-    }
-
-    /**
-     * Determine the actual packager name for the generated artifacts by trying to load the class from one of two
-     * packages.  This is necessary because the RI implementations of WSGen and WSImport generate the artifacts 
-     * in different packages:
-     * - WSImport generates the artifacts in the same package as the SEI
-     * - WSGen generates the artifacts in a "jaxws" sub package under the SEI package.
-     * Note that from reading the JAX-WS spec, it seems that WSGen is doing that correctly; See
-     * the conformance requirement in JAX-WS 2.0 Spec Section 3.6.2.1 Document Wrapped on page 36:
-     *     Conformance (Default wrapper bean package): In the absence of customizations, the wrapper beans package
-     *     MUST be a generated jaxws subpackage of the SEI package.
-     *                         ^^^^^^^^^^^^^^^^
-     * @param requestWrapperClassName
-     * @return
-     */
-    private static final String JAXWS_SUBPACKAGE = "jaxws";
-    private static String determineActualAritfactPackage(String wrapperClassName) {
-        String returnWrapperClassName = null;
-
-        // Try to load the class that was passed in
-        try {
-            DescriptionUtils.loadClass(wrapperClassName);
-            returnWrapperClassName = wrapperClassName;
-        }
-        catch (ClassNotFoundException e) {
-            // Couldn't load the class; we'll try another one below.
-        }
-
-        // If the original class couldn't be loaded, try adding ".jaxws." to the package
-        if (returnWrapperClassName == null) {
-            String originalPackage = DescriptionUtils.getJavaPackageName(wrapperClassName);
-            if (originalPackage != null) {
-                String alternatePackage = originalPackage + "." + JAXWS_SUBPACKAGE;
-                String className = DescriptionUtils.getSimpleJavaClassName(wrapperClassName);
-                String alternateWrapperClass = alternatePackage + "." + className;
-                try {
-                    DescriptionUtils.loadClass(alternateWrapperClass);
-                    returnWrapperClassName = alternateWrapperClass;
-                }
-                catch (ClassNotFoundException e) {
-                    // Couldn't load the class
-                }
-            }
-        }
-        
-        if (returnWrapperClassName == null){
-            // Couldn't load either class, so stick with the original wrapper class name
-            // REVIEW: Is this correct behavior?  Note that some of the annotation unit tests don't have the actual
-            //         classes available, and so will fail if this is changed.
-            returnWrapperClassName = wrapperClassName;
-        }
-        return returnWrapperClassName;
     }
 
     /* (non-Javadoc)

Modified: webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/WrapperPackageTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/WrapperPackageTests.java?view=diff&rev=498250&r1=498249&r2=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/WrapperPackageTests.java (original)
+++ webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/WrapperPackageTests.java Sat Jan 20 22:55:27 2007
@@ -21,6 +21,7 @@
 import javax.jws.WebService;
 import javax.xml.ws.RequestWrapper;
 import javax.xml.ws.ResponseWrapper;
+import javax.xml.ws.WebFault;
 
 import junit.framework.TestCase;
 
@@ -39,7 +40,12 @@
         assertEquals("org.apache.axis2.jaxws.description.Method1", requestWrapperClass);
         String responseWrapperClass = opDesc.getResponseWrapperClassName();
         assertEquals("org.apache.axis2.jaxws.description.Method1Response", responseWrapperClass);
-        
+        FaultDescription fDesc = opDesc.getFaultDescriptions()[0];
+        String faultExceptionClass = fDesc.getExceptionClassName();
+        assertEquals("org.apache.axis2.jaxws.description.Method1Exception", faultExceptionClass);
+        String faultBeanClass = fDesc.getFaultBean();
+        assertEquals("org.apache.axis2.jaxws.description.ExceptionBean", faultBeanClass);
+
     }
     
     public void testSEISubPackageWrapper() {
@@ -49,7 +55,12 @@
         assertEquals("org.apache.axis2.jaxws.description.jaxws.SubPackageMethod1", requestWrapperClass);
         String responseWrapperClass = opDesc.getResponseWrapperClassName();
         assertEquals("org.apache.axis2.jaxws.description.jaxws.SubPackageMethod1Response", responseWrapperClass);
-        
+        FaultDescription fDesc = opDesc.getFaultDescriptions()[0];
+        String faultExceptionClass = fDesc.getExceptionClassName();
+        assertEquals("org.apache.axis2.jaxws.description.SubPackageException", faultExceptionClass);
+        String faultBeanClass = fDesc.getFaultBean();
+        assertEquals("org.apache.axis2.jaxws.description.jaxws.SubPackageExceptionBean", faultBeanClass);
+
     }
     
     /*
@@ -78,7 +89,7 @@
 class SEIPackageWrapper {
     @RequestWrapper()
     @ResponseWrapper()
-    public String method1(String string) {
+    public String method1(String string) throws Method1Exception {
         return string;
     }
 }
@@ -91,11 +102,25 @@
     
 }
 
+@WebFault()
+class Method1Exception extends Exception {
+    public ExceptionBean getFaultInfo() { return null; }
+}
+
+class ExceptionBean {
+    
+}
+
+@WebFault
+class SubPackageException extends Exception {
+    // No getFaultInfo method
+}
+
 @WebService()
 class SEISubPackageWrapper {
     @RequestWrapper()
     @ResponseWrapper()
-    public String subPackageMethod1(String string) {
+    public String subPackageMethod1(String string) throws SubPackageException {
         return string;
     }
 }

Added: webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/jaxws/SubPackageExceptionBean.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/jaxws/SubPackageExceptionBean.java?view=auto&rev=498250
==============================================================================
--- webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/jaxws/SubPackageExceptionBean.java (added)
+++ webservices/axis2/trunk/java/modules/metadata/test/org/apache/axis2/jaxws/description/jaxws/SubPackageExceptionBean.java Sat Jan 20 22:55:27 2007
@@ -0,0 +1,9 @@
+package org.apache.axis2.jaxws.description.jaxws;
+
+/**
+ * Used by WrappedPackageTests
+ *
+ */
+public class SubPackageExceptionBean {
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org