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 2007/09/05 23:10:19 UTC

svn commit: r573057 - in /webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async: AsyncResponse.java CallbackFuture.java

Author: scheu
Date: Wed Sep  5 14:10:18 2007
New Revision: 573057

URL: http://svn.apache.org/viewvc?rev=573057&view=rev
Log:
AXIS2-3169
Contributor:Nick Gallardo
Committer: Rich Scheuerle
Corrected the code in AsyncResponse to ensure that response is unmarshalled before
reporting that the response is available.  Also a small fix in CallbackFuture to only 
wait if not done.

Modified:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/AsyncResponse.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/CallbackFuture.java

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/AsyncResponse.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/AsyncResponse.java?rev=573057&r1=573056&r2=573057&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/AsyncResponse.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/AsyncResponse.java Wed Sep  5 14:10:18 2007
@@ -63,14 +63,12 @@
     private EndpointDescription endpointDescription;
     private Map<String, Object> responseContext;
 
-    /* 
-     * CountDownLatch is used to track whether we've received and
-     * processed the async response.  For example, the client app
-     * could be polling on 30 second intervals, and we don't receive
-     * the async response until the 1:15 mark.  In that case, the
-     * first few polls calling the .get() would hit the latch.await()
-     * which blocks the thread if the latch count > 0
-     */
+    // CountDownLatch is used to track whether we've received and
+    // processed the async response.  For example, the client app
+    // could be polling on 30 second intervals, and we don't receive
+    // the async response until the 1:15 mark.  In that case, the
+    // first few polls calling the .get() would hit the latch.await()
+    // which blocks the thread if the latch count > 0
     private CountDownLatch latch;
     private boolean cacheValid = false;
     private Object cachedObject = null;
@@ -80,9 +78,11 @@
     // This object is just a cache object.
     private ClassLoader classLoader = null;
     
-    // the object to be returned
-    private Object obj = null;
-    // we need to save an exception if processResponse fails
+    // The response business object to be returned
+    private Object responseObject = null;
+    
+    // The exception to be returned in the event of a fault or failure in 
+    // processing the response content.
     private ExecutionException savedException = null;
     
     protected AsyncResponse(EndpointDescription ed) {
@@ -103,7 +103,7 @@
     
     protected void onError(Throwable flt, MessageContext faultCtx) {
         if (log.isDebugEnabled()) {
-            log.debug("AsyncResponse received a fault.  Counting down latch.");
+            log.debug("AsyncResponse received a fault.");
         }
 
         fault = flt;
@@ -116,12 +116,15 @@
 
         Throwable t = processFaultResponse();
         
+        // JAXWS 4.3.3 conformance bullet says to throw an ExecutionException from here
+        savedException = new ExecutionException(t);
+         
+        // Countdown so that the Future object will know that procesing is complete.
+        latch.countDown();
+        
         if (log.isDebugEnabled()) {
             log.debug("New latch count = [" + latch.getCount() + "]");
         }
-        
-        // JAXWS 4.3.3 conformance bullet says to throw an ExecutionException from here
-        savedException = new ExecutionException(t);
     }
     
     private void setThreadClassLoader(final ClassLoader cl) {
@@ -160,7 +163,7 @@
 
     protected void onComplete(MessageContext mc) {
         if (log.isDebugEnabled()) {
-            log.debug("AsyncResponse received a MessageContext. Counting down latch.");
+            log.debug("AsyncResponse received a MessageContext.");
         }
 
         // A new message context invalidates the cached object retrieved
@@ -174,26 +177,25 @@
         response.setEndpointDescription(endpointDescription);
         
         // Check for cached attachment file(s) if attachments exist. 
-        if(response.getAxisMessageContext().getAttachmentMap() != null){
-        	AttachmentUtils.findCachedAttachment(response.getAxisMessageContext().getAttachmentMap());
+        if (response.getAxisMessageContext().getAttachmentMap() != null){
+            AttachmentUtils.findCachedAttachment(response.getAxisMessageContext().getAttachmentMap());
         }
         
-        /*
-         * TODO: review?
-         * We need to process the response right when we get it, instead of
-         * caching it away for processing when the client poller calls .get().
-         * Reason for this is that some platforms (or web containers) will close
-         * down their threads immediately after "dropping off" the async response.
-         * If those threads disappear, the underlying input stream object may also
-         * disappear, thus causing a NullPointerException later when we try to .get().
-         * The NPE would manifest itself way down in the parser.
-         */
+        // Process the response as soon as it is available.  This means making sure that
+        // no content is left unread in the response stream.  Leaving content there could
+        // result in an error if the runtime is greedy about cleaning up.
         try {
-            obj = processResponse();
+            responseObject = processResponse();
         } catch (ExecutionException e) {
             savedException = e;
+            if (log.isDebugEnabled()) {
+                log.debug("An error occurred while processing the response: " + e.getCause());
+            }
+            latch.countDown();
         }
 
+        // Countdown so that the Future object will know that procesing is complete.
+        latch.countDown();
         if (log.isDebugEnabled()) {
             log.debug("New latch count = [" + latch.getCount() + "]");
         }
@@ -236,7 +238,7 @@
             throw savedException;
         }
         
-        return obj;
+        return responseObject;
     }
 
     public Object get(long timeout, TimeUnit unit)
@@ -266,7 +268,7 @@
                     "The client timed out while waiting for an asynchronous response");
         }
 
-        return obj;
+        return responseObject;
     }
 
     public boolean isCancelled() {
@@ -282,15 +284,10 @@
     }
 
     private Object processResponse() throws ExecutionException {
-        /*
-         * note the latch.countDown() here.  We have to make sure the countdown
-         * occurs everywhere we might leave the method, which could be a return
-         * or throw.
-         */
     	
         // If we don't have a fault, then we have to have a MessageContext for the response.
         if (response == null) {
-        	latch.countDown();
+            latch.countDown();
             throw new ExecutionException(ExceptionFactory.makeWebServiceException("null response"));
         }
 
@@ -300,15 +297,12 @@
             if (log.isDebugEnabled()) {
                 log.debug("Return object cached from last get()");
             }
-            latch.countDown();
             return cachedObject;
         }
 
         Object obj = null;
         try {
-            // TODO: IMPORTANT: this is the right call here, but beware that the messagecontext may be turned into
-            // a fault context with a fault message.  We need to check for this and, if necessary, make an exception and throw it.
-            // Invoke inbound handlers.
+            // Install the adapters and invoke inbound handlers.
             TransportHeadersAdapter.install(response);
             AttachmentsAdapter.install(response);
             HandlerInvokerUtils.invokeInboundHandlers(response.getMEPContext(),
@@ -316,20 +310,23 @@
                                                       HandlerChainProcessor.MEP.RESPONSE,
                                                       false);
 
-            // TODO: Check the type of the object to make sure it corresponds with
-            // the parameterized generic type.
+            // TODO: IMPORTANT: this is the right call here, but beware that the 
+            // messagecontext may be turned into a fault context with a fault message.  
+            // We need to check for this and, if necessary, make an exception and throw it.
             if (log.isDebugEnabled()) {
                 log.debug("Unmarshalling the async response message.");
             }
             
+            // Do the real work to unmarshall the response.
             obj = getResponseValueObject(response);
-            // Cache the object in case it is required again
-            cacheValid = true;
-            cachedObject = obj;
             
             if (log.isDebugEnabled() && obj != null) {
                 log.debug("Unmarshalled response object of type: " + obj.getClass());
             }
+            
+            // Cache the object in case it is required again
+            cacheValid = true;
+            cachedObject = obj;
 
             responseContext = new HashMap<String, Object>();
 
@@ -338,12 +335,7 @@
             ApplicationContextMigratorUtil.performMigrationFromMessageContext(Constants.APPLICATION_CONTEXT_MIGRATOR_LIST_ID,
                                                                               responseContext,
                                                                               response);
-            latch.countDown();
         } catch (Throwable t) {
-            if (log.isDebugEnabled()) {
-                log.debug("An error occurred while processing the response");
-            }
-            latch.countDown();
             throw new ExecutionException(ExceptionFactory.makeWebServiceException(t));
         }
 
@@ -363,26 +355,33 @@
                 // AttachmentsAdapter.install(faultMessageContext);
             	try {
                     // Invoke inbound handlers.
+            	    if (log.isDebugEnabled()) {
+            	        log.debug("Invoking the JAX-WS handler chain for the fault response.");
+            	    }
                     HandlerInvokerUtils.invokeInboundHandlers(faultMessageContext.getMEPContext(),
                                                           faultMessageContext.getInvocationContext()
                                                                              .getHandlers(),
                                                           HandlerChainProcessor.MEP.RESPONSE,
                                                           false);
             	} catch (Throwable t) {
-            		throwable = t;
+            	    if (log.isDebugEnabled()) {
+            	        log.debug("An error occurred (" + t.getClass() + " while processing " +
+            	        "the fault response handler chain.");
+            	    }
+            	    throwable = t;
             	}
             }
             if (throwable == null) {
+                // Do the real work to unmarshal the fault response.
                 throwable = getFaultResponse(faultMessageContext);
             }
-            latch.countDown();
+            
             if (throwable != null) {
                 return throwable;
             } else {
                 return ExceptionFactory.makeWebServiceException(fault);
             }
         } else {
-        	latch.countDown();
             return ExceptionFactory.makeWebServiceException(fault);
         }
     }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/CallbackFuture.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/CallbackFuture.java?rev=573057&r1=573056&r2=573057&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/CallbackFuture.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/client/async/CallbackFuture.java Wed Sep  5 14:10:18 2007
@@ -190,7 +190,9 @@
                  */
                 try {
                     synchronized (cft) {
-                        cft.wait(180000);  // 3 minutes
+                        if(!cft.done) {
+                            cft.wait(180000);  // 3 minutes
+                        }
                     }
                 } catch (InterruptedException e) {
                     if (debug) {
@@ -261,13 +263,13 @@
             // Now that the content is available, call the JAX-WS AsyncHandler class
             // to deliver the response to the user.
             ClassLoader cl = handler.getClass().getClassLoader();
-        	if (log.isDebugEnabled()) {
-        		log.debug("Setting up the thread's ClassLoader");
-        		log.debug(cl.toString());
-        	}
-        	Thread.currentThread().setContextClassLoader(cl);
-        	
-        	if (debug) {
+            if (log.isDebugEnabled()) {
+                log.debug("Setting up the thread's ClassLoader");
+                log.debug(cl.toString());
+            }
+            Thread.currentThread().setContextClassLoader(cl);
+
+            if (debug) {
                 log.debug("Calling JAX-WS AsyncHandler with the Response object");
                 log.debug("AyncHandler class: " + handler.getClass());
             }



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