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 2006/11/18 17:58:26 UTC

svn commit: r476565 - in /webservices/axis2/trunk/java/modules/jaxws: src/org/apache/axis2/jaxws/message/databinding/ src/org/apache/axis2/jaxws/server/ src/org/apache/axis2/jaxws/util/ test/org/apache/axis2/jaxws/proxy/

Author: scheu
Date: Sat Nov 18 08:58:26 2006
New Revision: 476565

URL: http://svn.apache.org/viewvc?view=rev&rev=476565
Log:
AXIS2-1730
Contributor: Rich Scheuerle (WSDL author by Lizet Ernand)
More RPC tests, fixes to getClassesFromPackage logic to include array classes, fix to JAXWSMessageReceiver to throw an AxisFault when problems occur.

Modified:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/ClassUtils.java
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/proxy/RPCProxyTests.java

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java?view=diff&rev=476565&r1=476564&r2=476565
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java Sat Nov 18 08:58:26 2006
@@ -16,8 +16,14 @@
  */
 package org.apache.axis2.jaxws.message.databinding;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +36,7 @@
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
+import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl;
 import org.apache.axis2.jaxws.util.ClassUtils;
 import org.apache.commons.logging.Log;
@@ -60,6 +67,7 @@
 	
     private static boolean ENABLE_ADV_POOLING = false;
     
+
     /**
 	 * Get a generic JAXBContext (that can be used for primitives)
 	 * @throws JAXBException
@@ -96,14 +104,50 @@
 		if (context == null) {
             synchronized(map) {
                 try{
-                    Iterator<Package> it = contextPackages.iterator();
-                    List<Class> fullList = new ArrayList<Class>();
-                    while (it.hasNext()) {
-                        Package pkg = it.next();
-                		fullList.addAll(ClassUtils.getAllClassesFromPackage(pkg));
-                	}
-                	Class[] classArray = fullList.toArray(new Class[0]);
-                    context = JAXBContext.newInstance(classArray);
+                    // There are two ways to construct the context.
+                    // 1) USE A CONTEXTPATH, which is a string containing
+                    //    all of the packages separated by colons.
+                    // 2) USE A CLASS[], which is an array of all of the classes
+                    //    involved in the marshal/unmarshal.
+                    //   
+                    // There are pros/cons with both approaches.
+                    // USE A CONTEXTPATH: 
+                    //    Pros: preferred way of doing this.  
+                    //          performant
+                    //          most dynamic
+                    //    Cons: Each package in context path must have an ObjectFactory
+                    //          Problems with RPC types
+                    //
+                    // USE CLASS[]:
+                    //    Pros: Doesn't require ObjectFactory in each package
+                    //    Cons: Hard to set up, must account for JAX-WS classes, etc.
+                    //          Does not work if arrays of classes are needed
+                    //          slower
+                    //
+                    //  The following code attempts to build a context path.  It then
+                    //  choose one of the two constructions above (prefer USE A CONTEXT_PATH)
+                    //
+                    
+                    // REVIEW: DISABLE UNTIL ARRAY PROBLEMS WITH RPC ARE DIAGNOSED
+                    //context = createJAXBContextUsingContextPath(contextPackages);
+                    
+                    if (context == null) {
+                        // Unsuccessful, USE CLASS[]
+                        if (log.isDebugEnabled()) {
+                            log.debug("Attempting to create JAXBContext with Class[]");
+                        }
+                        Iterator<Package> it = contextPackages.iterator();
+                        List<Class> fullList = new ArrayList<Class>();
+                        while (it.hasNext()) {
+                            Package pkg = it.next();
+                    		fullList.addAll(JAXBUtils.getAllClassesFromPackage(pkg));
+                    	}
+                    	Class[] classArray = fullList.toArray(new Class[0]);
+                        context = JAXBContext.newInstance(classArray);
+                        if (log.isDebugEnabled()) {
+                            log.debug("Successfully created JAXBContext with Class[] = " + context.toString());
+                        }
+                    }
                     map.put(contextPackages, context);	
                 }catch(ClassNotFoundException e){
                 	throw new JAXBException(e);
@@ -247,4 +291,198 @@
         }
         imap.put(context, introspector);
 	}
+    
+    /**
+     * Create a JAXBContext using the contextpath approach
+     * @param packages
+     * @return JAXBContext or null if unsuccessful
+     */
+    private static JAXBContext createJAXBContextUsingContextPath(Set<Package> packages) {
+        JAXBContext context = null;
+        String contextpath = "";
+        
+        // TODO
+        // Do we want to use the current class loader, or get it from a loaded class ?
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        
+        // Iterate through the classes and build the contextpath
+        Iterator<Package> it = packages.iterator();
+        while(it.hasNext()) {
+            Package p = it.next();
+            if (p.getName().startsWith("java.") ||
+                p.getName().startsWith("javax.")) {
+               ; // Assume that these packages don't have an object factory
+            } else {
+                // REVIEW 
+                // There are two paths here.
+                // A) We could blindly add this package to the contextpath
+                //    The JAXBContext construction will fail if the ObjectFactory is 
+                //    not found
+                // B) We can look for an ObjectFactory in the package and only
+                //    add the package if the ObjectFactory is found
+                // I am choosing (A) because choosing (B) may delay an exception 
+                // until we are marshalling/unmarshalling an object.  
+                if (contextpath.length() != 0) {
+                    contextpath +=":";
+                }
+                contextpath += p.getName();
+            }
+        }
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Attempting to create JAXBContext with contextPath=" + contextpath);
+            }
+            context = JAXBContext.newInstance(contextpath, cl);
+            if (log.isDebugEnabled()) {
+                log.debug("  Successfully created JAXBContext:" + context);
+            }
+        } catch (Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("  Unsuccessful: We will now use an alterative JAXBConstruct construction");
+                log.debug("  Reason " + e.toString());
+            }
+        }
+        return context;
+    }
+
+    /**
+     * This method will return all the Class names needed to construct a JAXBContext
+     * @param pkg Package
+     * @return
+     * @throws ClassNotFoundException
+     */
+    private static List<Class> getAllClassesFromPackage(Package pkg) throws ClassNotFoundException {
+        if (pkg == null) {
+            return new ArrayList<Class>();
+        }   
+        // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
+        String pckgname = pkg.getName();
+        ArrayList<File> directories = new ArrayList<File>();
+        try {
+            ClassLoader cld = Thread.currentThread().getContextClassLoader();
+            if (cld == null) {
+                if(log.isDebugEnabled()){
+                    log.debug("Unable to get class loader");
+                }
+                throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr1"));
+            }
+            String path = pckgname.replace('.', '/');
+            // Ask for all resources for the path
+            Enumeration<URL> resources = cld.getResources(path);
+            while (resources.hasMoreElements()) {
+                directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
+            }
+        } catch (UnsupportedEncodingException e) {
+            if(log.isDebugEnabled()){
+                log.debug(pckgname + " does not appear to be a valid package (Unsupported encoding)");
+            }
+            throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr2", pckgname));
+        } catch (IOException e) {
+            if(log.isDebugEnabled()){
+                log.debug("IOException was thrown when trying to get all resources for "+ pckgname);
+            }
+            throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr3", pckgname));
+        }
+        
+        ArrayList<Class> classes = new ArrayList<Class>();
+        // For every directory identified capture all the .class files
+        for (File directory : directories) {
+            if (log.isDebugEnabled()) {
+                log.debug("Adding classes from: " + directory.getName());
+            }
+            if (directory.exists()) {
+                // Get the list of the files contained in the package
+                String[] files = directory.list();
+                for (String file : files) {
+                    // we are only interested in .class files
+                    if (file.endsWith(".class")) {
+                        // removes the .class extension
+                        // TODO Java2 Sec
+                        String className = pckgname + '.' + file.substring(0, file.length() - 6);
+                        try {
+                            Class clazz = Class.forName(className, 
+                                    false, 
+                                    Thread.currentThread().getContextClassLoader());
+                            // Don't add any interfaces or JAXWS specific classes.  
+                            // Only classes that represent data and can be marshalled 
+                            // by JAXB should be added.
+                            if(!clazz.isInterface() 
+                                    && ClassUtils.getDefaultPublicConstructor(clazz) != null
+                                    && !ClassUtils.isJAXWSClass(clazz)){
+                                if (log.isDebugEnabled()) {
+                                    log.debug("Adding class: " + file);
+                                }
+                                classes.add(clazz);
+                                
+                                // REVIEW:
+                                // Support of RPC list (and possibly other scenarios) requires that the array classes should also be present.
+                                // This is a hack until we can determine how to get this information.
+                                
+                                // The arrayName and loadable name are different.  Get the loadable
+                                // name, load the array class, and add it to our list
+                                className += "[]";
+                                String loadableName = ClassUtils.getLoadableClassName(className);
+                                
+                                Class aClazz = Class.forName(loadableName, false, Thread.currentThread().getContextClassLoader());
+                            }
+                        } catch (Exception e) {
+                            if (log.isDebugEnabled()) {
+                                log.debug("Tried to load class " + className + " while constructing a JAXBContext.  This class will be skipped.  Processing Continues." );
+                                log.debug("  The reason that class could not be loaded:" + e.toString());
+                            }
+                            e.printStackTrace();
+                        }
+                        
+                    }
+                }
+                
+                // REVIEW Load and add the common array classes
+                // Support of RPC list (and possibly other scenarios) requires that the array classes should also be present.
+                // This is a hack until we can determine how to get this information.
+                addCommonArrayClasses(classes);
+            }
+        }
+        return classes;
+    }
+    
+    private static  String[] commonArrayClasses = new String[] { 
+        // primitives
+        "boolean[]",
+        "byte[]",
+        "char[][]",
+        "double[]",
+        "float[]",
+        "int[]",
+        "long[]",
+        "short[]",
+        "java.lang.String[]",
+        // Others
+        "java.lang.Object[]",
+        "java.awt.Image[]",
+        "java.math.BigDecimal[]",
+        "java.math.BigInteger[]",
+        "java.util.Calendar[]",
+        "javax.xml.namespace.QName[]" };
+    
+    private static void addCommonArrayClasses(List<Class> list) {
+        // Add common primitives arrays (necessary for RPC list type support)
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+       
+        for (int i=0; i<commonArrayClasses.length; i++) {
+            String className = commonArrayClasses[i];
+            try {
+                // Load and add the class
+                Class cls = Class.forName(ClassUtils.getLoadableClassName(className), false, cl);
+                list.add(cls);
+            } catch (Exception e) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Tried to load class " + className + " while constructing a JAXBContext.  This class will be skipped.  Processing Continues." );
+                    log.debug("  The reason that class could not be loaded:" + e.toString());
+                }
+                e.printStackTrace();
+            }
+        }
+    }
+    
 }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java?view=diff&rev=476565&r1=476564&r2=476565
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java Sat Nov 18 08:58:26 2006
@@ -17,6 +17,8 @@
 
 package org.apache.axis2.jaxws.server;
 
+import javax.xml.ws.WebServiceException;
+
 import org.apache.axiom.soap.SOAPEnvelope;
 import org.apache.axis2.AxisFault;
 import org.apache.axis2.Constants.Configuration;
@@ -125,7 +127,13 @@
 
         } catch (Exception e) {
             ThreadContextMigratorUtil.performThreadCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);
-            throw ExceptionFactory.makeWebServiceException(e);
+            
+            // Make a webservice exception (which will strip out a unnecessary stuff)
+            WebServiceException wse = ExceptionFactory.makeWebServiceException(e);
+            
+            // The AxisEngine expects an AxisFault
+            throw AxisFault.makeFault(wse);
+            
         } 
 
         //This assumes that we are on the ultimate execution thread

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/ClassUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/ClassUtils.java?view=diff&rev=476565&r1=476564&r2=476565
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/ClassUtils.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/util/ClassUtils.java Sat Nov 18 08:58:26 2006
@@ -16,17 +16,9 @@
  */
 package org.apache.axis2.jaxws.util;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.List;
 
 import javax.jws.WebService;
 import javax.xml.ws.Holder;
@@ -34,7 +26,6 @@
 import javax.xml.ws.WebServiceClient;
 import javax.xml.ws.WebServiceProvider;
 
-import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -229,86 +220,7 @@
         return null;
     }
     
-    /**
-	 * This method will return all the Class names excluding the interfaces from a given package. 
-	 * @param pkg Package
-	 * @return
-	 * @throws ClassNotFoundException
-	 */
-    public static List<Class> getAllClassesFromPackage(Package pkg) throws ClassNotFoundException {
-        if (pkg == null) {
-            return new ArrayList<Class>();
-        }   
-        // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
-        String pckgname = pkg.getName();
-        ArrayList<File> directories = new ArrayList<File>();
-        try {
-            ClassLoader cld = Thread.currentThread().getContextClassLoader();
-            if (cld == null) {
-                if(log.isDebugEnabled()){
-                    log.debug("Unable to get class loader");
-                }
-                throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr1"));
-            }
-            String path = pckgname.replace('.', '/');
-            // Ask for all resources for the path
-            Enumeration<URL> resources = cld.getResources(path);
-            while (resources.hasMoreElements()) {
-                directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
-            }
-        } catch (UnsupportedEncodingException e) {
-            if(log.isDebugEnabled()){
-                log.debug(pckgname + " does not appear to be a valid package (Unsupported encoding)");
-            }
-            throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr2", pckgname));
-        } catch (IOException e) {
-            if(log.isDebugEnabled()){
-                log.debug("IOException was thrown when trying to get all resources for "+ pckgname);
-            }
-            throw new ClassNotFoundException(Messages.getMessage("ClassUtilsErr3", pckgname));
-        }
-        
-        ArrayList<Class> classes = new ArrayList<Class>();
-        // For every directory identified capture all the .class files
-        for (File directory : directories) {
-            if (log.isDebugEnabled()) {
-                log.debug("Adding classes from: " + directory.getName());
-            }
-            if (directory.exists()) {
-                // Get the list of the files contained in the package
-                String[] files = directory.list();
-                for (String file : files) {
-                    // we are only interested in .class files
-                    if (file.endsWith(".class")) {
-                        // removes the .class extension
-                        // TODO Java2 Sec
-                        try {
-                            Class clazz = Class.forName(pckgname + '.' + file.substring(0, file.length() - 6), 
-                                    false, 
-                                    Thread.currentThread().getContextClassLoader());
-                            // Don't add any interfaces or JAXWS specific classes.  
-                            // Only classes that represent data and can be marshalled 
-                            // by JAXB should be added.
-                            if(!clazz.isInterface() 
-                                    && getDefaultPublicConstructor(clazz) != null
-                                    && !isJAXWSClass(clazz)){
-                                if (log.isDebugEnabled()) {
-                                    log.debug("Adding class: " + file);
-                                }
-                                classes.add(clazz);
-                            }
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        }
-                        
-                    }
-                }
-            }
-        }
-        return classes;
-    }
-    
-	private static final Class[] noClass=new Class[] {};
+    private static final Class[] noClass=new Class[] {};
 	/**
 	 * Get the default public constructor
 	 * @param clazz

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/proxy/RPCProxyTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/proxy/RPCProxyTests.java?view=diff&rev=476565&r1=476564&r2=476565
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/proxy/RPCProxyTests.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/proxy/RPCProxyTests.java Sat Nov 18 08:58:26 2006
@@ -24,8 +24,10 @@
 
 import javax.xml.namespace.QName;
 import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
 import javax.xml.ws.Service;
 
+import org.apache.axis2.jaxws.dispatch.DispatchTestConstants;
 import org.apache.axis2.jaxws.proxy.rpclit.sei.RPCLit;
 
 import junit.framework.TestCase;
@@ -56,6 +58,20 @@
     }
     
     /**
+     * Utility Method to get a Dispatch<String>
+     * @return
+     * @throws MalformedURLException
+     */
+    public Dispatch<String> getDispatch() throws MalformedURLException {
+        File wsdl= new File(wsdlLocation); 
+        URL wsdlUrl = wsdl.toURL(); 
+        Service service = Service.create(null, serviceName);
+        service.addPort(portName, null, axisEndpoint);
+        Dispatch<String> dispatch = service.createDispatch(portName, String.class, Service.Mode.PAYLOAD);
+        return dispatch;
+    }
+    
+    /**
      * Simple test that ensures that we can echo a string to an rpc/lit web service
      */
     public void testSimple() throws Exception {
@@ -64,7 +80,74 @@
             String request = "This is a test...";
            
             String response = proxy.testSimple(request);
-            assert(response != null);
+            assertTrue(response != null);
+            assert(response.equals(request));
+        }catch(Exception e){ 
+            e.printStackTrace(); 
+            fail("Exception received" + e);
+        }
+    }
+    
+    public void testSimple_Dispatch() throws Exception {
+        // Send a payload that simulates
+        // the rpc message
+        String request = "<tns:testSimple xmlns:tns='http://org/apache/axis2/jaxws/proxy/rpclit'>" +
+        "<tns:simpleIn xsi:type='xsd:string' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
+        "PAYLOAD WITH XSI:TYPE" +
+        "</tns:simpleIn></tns:testSimple>";
+        Dispatch<String> dispatch = getDispatch();
+        String response = dispatch.invoke(request);
+
+        assertNotNull("dispatch invoke returned null", response);
+        System.out.println(response);
+        
+        // Check to make sure the content is correct
+        assertTrue(!response.contains("soap"));
+        assertTrue(!response.contains("Envelope"));
+        assertTrue(!response.contains("Body"));
+        assertTrue(!response.contains("Fault"));
+        assertTrue(response.contains("simpleOut"));
+        assertTrue(response.contains("testSimpleResponse"));
+        assertTrue(response.contains("PAYLOAD WITH XSI:TYPE"));
+    }
+    
+    public void _testSimple_DispatchWithoutXSIType() throws Exception {
+        // Send a payload that simulates
+        // the rpc message
+        String request = "<tns:testSimple xmlns:tns='http://org/apache/axis2/jaxws/proxy/rpclit'>" +
+        "<tns:simpleIn>" +
+        "PAYLOAD WITH XSI:TYPE" +
+        "</tns:simpleIn></tns:testSimple>";
+        Dispatch<String> dispatch = getDispatch();
+        String response = dispatch.invoke(request);
+        
+
+        assertNotNull("dispatch invoke returned null", response);
+        System.out.println(response);
+        
+        // Check to make sure the content is correct
+        assertTrue(!response.contains("soap"));
+        assertTrue(!response.contains("Envelope"));
+        assertTrue(!response.contains("Body"));
+        assertTrue(!response.contains("Fault"));
+        assertTrue(response.contains("simpleOut"));
+        assertTrue(response.contains("testSimpleResponse"));
+        assertTrue(response.contains("PAYLOAD WITH XSI:TYPE"));
+    }
+    
+    /**
+     * Simple test that ensures that we can echo a string to an rpc/lit web service
+     */
+    public void testStringList() throws Exception {
+        try{ 
+            RPCLit proxy = getProxy();
+            String[] request = new String[] {"Hello" , "World"};
+           
+            String[] response = proxy.testStringList2(request);
+            assertTrue(response != null);
+            assertTrue(response.length==2);
+            assertTrue(response[0].equals("Hello"));
+            assertTrue(response[1].equals("World"));
             assert(response.equals(request));
         }catch(Exception e){ 
             e.printStackTrace(); 



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