Author: cwiklik
Date: Wed Aug  9 23:44:31 2017
New Revision: 1804614

URL: http://svn.apache.org/viewvc?rev=1804614&view=rev
Log:
UIMA-5529 improved serialization of exceptions

Modified:
    
uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jp/HttpWorkerThread.java
    
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/DuccAbstractProcessContainer.java
    
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaASProcessContainer.java
    
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaProcessContainer.java

Modified: 
uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jp/HttpWorkerThread.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jp/HttpWorkerThread.java?rev=1804614&r1=1804613&r2=1804614&view=diff
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jp/HttpWorkerThread.java
 (original)
+++ 
uima/uima-ducc/trunk/uima-ducc-transport/src/main/java/org/apache/uima/ducc/transport/configuration/jp/HttpWorkerThread.java
 Wed Aug  9 23:44:31 2017
@@ -308,8 +308,19 @@ public class HttpWorkerThread implements
                                                                break;
                                                        }
                                                        IMetaCas mc = 
transaction.getMetaCas();
-                                                       // strip 
InvocationTargetException
-                                                       byte[] 
serializedException = serializeException(ee.getCause());
+                                                       //byte[] 
serializedException = null;
+                                                       Method 
getLastSerializedErrorMethod = 
processorInstance.getClass().getDeclaredMethod("getLastSerializedError");
+                                                       byte[] 
serializedException =
+                                                           
(byte[])getLastSerializedErrorMethod.invoke(processorInstance);
+                       
+//                                                     if ( ee.getCause() 
instanceof DuccUimaProcessException ) {
+//                                                             // The 
process() exception had been serialized on the user side of the JP since
+//                                                             // only there 
the Classloader has all the classes to serialize the exception.
+//                                                             
serializedException = 
((DuccUimaProcessException)ee.getCause()).getSerializedException();
+//                                                     } else {
+//                                                             // strip 
InvocationTargetException
+//                                                             
serializedException = serializeException(ee.getCause());
+//                                                     }
                                                        /*
                                                        ByteArrayOutputStream 
baos = new ByteArrayOutputStream();
                                                    ObjectOutputStream oos = 
new ObjectOutputStream(baos);

Modified: 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/DuccAbstractProcessContainer.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/DuccAbstractProcessContainer.java?rev=1804614&r1=1804613&r2=1804614&view=diff
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/DuccAbstractProcessContainer.java
 (original)
+++ 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/DuccAbstractProcessContainer.java
 Wed Aug  9 23:44:31 2017
@@ -43,6 +43,8 @@ import org.apache.uima.resource.metadata
 import org.apache.uima.resource.metadata.TypePriorities;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
 import org.apache.uima.util.CasCreationUtils;
+import org.apache.uima.util.Level;
+import org.apache.uima.util.Logger;
 
 public abstract class DuccAbstractProcessContainer implements 
IProcessContainer{
        // Container implementation must implement the following methods
@@ -51,7 +53,9 @@ public abstract class DuccAbstractProces
     protected abstract void doStop() throws Exception;
     protected abstract List<Properties>  doProcess(Object subject) throws 
Exception;
     protected  AnalysisEngineMetaData analysisEngineMetadata;
-
+    // Stores errors caught in doProcess() with key= current thread id. Each 
thread
+    // clears previous error in process() below before calling doProcess()
+    protected Map<Long, Throwable> errorMap = new HashMap<Long, Throwable>();
     protected int scaleout=1;
     // Map to store DuccUimaSerializer instances. Each has affinity to a thread
        protected static Map<Long, DuccUimaSerializer> serializerMap =
@@ -134,7 +138,10 @@ public abstract class DuccAbstractProces
                // a context cl before calling user code. 
                ClassLoader savedCL = 
Thread.currentThread().getContextClassLoader();
                
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
-         try {
+        // Clear previous error this thread may have added in doProcess()
+               errorMap.remove(Thread.currentThread().getId());
+        
+               try {
                return doProcess(xmi);
          }finally {
                        Thread.currentThread().setContextClassLoader(savedCL);
@@ -164,10 +171,14 @@ public abstract class DuccAbstractProces
             t.printStackTrace(new PrintWriter(sw));
             serializedCause =  sw.toString();
         } catch (Throwable e) {
-                       e.printStackTrace();
+                       try {
+                               Logger logger = 
UIMAFramework.getLogger(DuccAbstractProcessContainer.class);
+                               logger.log(Level.WARNING, "Unable to Stringfiy 
"+t.getClass().getName());
+                               
+                       } catch( Exception ee) {}
                        // Unable to serialize user Exception (not 
Serializable?)
                        // Just send a simple msg telling user to check service 
log
-                       serializedCause = "Unable to Serialize User Exception - 
Please Check JP Log File For More Details";
+                       serializedCause = "Unable to Stringifiy Exception 
"+t.getClass().getName()+" - Please Check JP Log File For More Details";
                }
         return serializedCause;
     }
@@ -178,16 +189,44 @@ public abstract class DuccAbstractProces
                try {
                        oos.writeObject(t);
                } catch (Exception e) {
-                       e.printStackTrace();
-                       // Unable to serialize user Exception (not 
Serializable?)
-                       // Create a new Exception and serialize it
-                       RuntimeException re 
-                          = new RuntimeException("Unable to Serialize User 
Exception - Please Check JP Log File For More Details");
-                       oos.writeObject(re);
+                       try {
+                               Logger logger = 
UIMAFramework.getLogger(DuccAbstractProcessContainer.class);
+                               logger.log(Level.WARNING, "Unable to Serialize 
"+t.getClass().getName()+" - Will Stringify It Instead");
+                               
+                       } catch( Exception ee) {}
+                       throw e;
+               } finally {
+                       oos.close();
                }
-               oos.close();
+               
                return baos.toByteArray();
        }
+       protected byte[] getLastSerializedError() throws Exception {
+               byte[] result = null;
+               if (errorMap.containsKey(Thread.currentThread().getId())) {
+                       Throwable lastError = 
+                                       
errorMap.get(Thread.currentThread().getId());
+
+                       if ( System.getProperty("SendExceptionAsString")!= null 
) {
+                               // the client of this JP/Service does not have 
user classpath
+                               // to be able to deserialize this exception. 
Instead of serializing
+                               // the exception as a java object, stringify it 
first and wrap it.
+                               // The client process might want to log this 
error.
+                               result = serialize(new 
RuntimeException(serializeAsString(lastError)));
+                       } else {
+                               try {
+                                       // try to serialize as java Object
+                                       result = serialize(lastError);
+                               } catch( Exception e) {
+                                       // Fallback is to stringify the 
exception and wrap it
+                                       result = serialize(new 
RuntimeException(serializeAsString(lastError)));
+                               }
+
+                       }
+               }
+               return result;
+       }
+
     private Socket connectWithAgent() throws Exception {
        InetAddress host = null;
         int statusUpdatePort = -1;

Modified: 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaASProcessContainer.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaASProcessContainer.java?rev=1804614&r1=1804613&r2=1804614&view=diff
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaASProcessContainer.java
 (original)
+++ 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaASProcessContainer.java
 Wed Aug  9 23:44:31 2017
@@ -41,7 +41,6 @@ import org.apache.uima.aae.client.UimaAs
 import org.apache.uima.aae.client.UimaAsynchronousEngine;
 import org.apache.uima.aae.monitor.statistics.AnalysisEnginePerformanceMetrics;
 import org.apache.uima.adapter.jms.client.BaseUIMAAsynchronousEngine_impl;
-import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
 import org.apache.uima.cas.CAS;
 import org.apache.uima.collection.EntityProcessStatus;
 import org.apache.uima.ducc.IUser;
@@ -314,7 +313,19 @@ public class UimaASProcessContainer  ext
                        if ( enablePerformanceBreakdownReporting ) {
                                List<AnalysisEnginePerformanceMetrics> 
perfMetrics =
                                                new 
ArrayList<AnalysisEnginePerformanceMetrics>();
-                               uimaASClient.sendAndReceiveCAS(cas, 
perfMetrics);
+                               
+                               try {
+                                       uimaASClient.sendAndReceiveCAS(cas, 
perfMetrics);
+                               } catch( Throwable t) {
+                                       // save the error
+                                       
errorMap.put(Thread.currentThread().getId(), t);
+                                       // AE failed, throw an exception. The 
HttpWorketThread will 
+                                       // subsequently call 
getLastSerializedException() on this class
+                                       // to fetch serialized exception saved 
in 'lastError' above.
+                                       // The 'lastError' is reset each time 
super.process() is called.
+                                       throw new RuntimeException(); 
+                               }
+                               
                                for( AnalysisEnginePerformanceMetrics metrics : 
perfMetrics ) {
                                        Properties p = new Properties();
                                        p.setProperty("name", 
metrics.getName());
@@ -333,7 +344,19 @@ public class UimaASProcessContainer  ext
                                }
                        } else {
                                // delegate processing to the UIMA-AS service 
and wait for a reply
-                               uimaASClient.sendAndReceiveCAS(cas);//, 
perfMetrics);
+                               try {
+                                       uimaASClient.sendAndReceiveCAS(cas);
+                               } catch( Throwable t) {
+                                       // save the error
+                                       
errorMap.put(Thread.currentThread().getId(), t);
+                                       // AE failed, throw an exception. The 
HttpWorketThread will 
+                                       // subsequently call 
getLastSerializedException() on this class
+                                       // to fetch serialized exception saved 
in errorMap above.
+                                       // The map entry for each thread is 
reset in super.process().
+
+                                       throw new RuntimeException();  
+                               }
+                               
                                // convert UIMA-AS metrics into properties so 
that we can return this
                                // data in a format which doesnt require 
UIMA-AS to digest
                                Properties p = new Properties();
@@ -346,15 +369,16 @@ public class UimaASProcessContainer  ext
 
                        return metricsList;
                } catch( Throwable t ) {
-                       Logger logger = UIMAFramework.getLogger();
-                       logger.log(Level.WARNING, "UimaProcessContainer", t);
-                       throw new RuntimeException(super.serializeAsString(t));
+                       throw t;
                } finally {
                        if ( cas != null) {
                                cas.release();
                        }
                }
        }
+       public byte[] getLastSerializedError() throws Exception {
+       return super.getLastSerializedError();
+       }
        private String getPID(final String fallback) {
                // the following code returns '<pid>@<hostname>'
                String name = ManagementFactory.getRuntimeMXBean().getName();

Modified: 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaProcessContainer.java
URL: 
http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaProcessContainer.java?rev=1804614&r1=1804613&r2=1804614&view=diff
==============================================================================
--- 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaProcessContainer.java
 (original)
+++ 
uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/jp/UimaProcessContainer.java
 Wed Aug  9 23:44:31 2017
@@ -21,7 +21,6 @@ package org.apache.uima.ducc.user.jp;
 
 
 import java.io.File;
-import java.io.PrintWriter;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -34,7 +33,6 @@ import java.util.concurrent.atomic.Atomi
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.analysis_engine.AnalysisEngine;
 import org.apache.uima.analysis_engine.AnalysisEngineManagement;
-import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
 import org.apache.uima.cas.CAS;
 import org.apache.uima.ducc.user.common.UimaUtils;
 import 
org.apache.uima.ducc.user.jp.uima.UimaAnalysisEngineInstancePoolWithThreadAffinity;
@@ -107,6 +105,7 @@ public class UimaProcessContainer extend
            return scaleout;              
        }
 
+
        public int doInitialize(Properties props, String[] args) throws 
Exception {
                        return configureAndGetScaleout(args);
        }
@@ -186,7 +185,22 @@ public class UimaProcessContainer extend
                        // the following checks out AE instance pinned to this 
thread
                        ae = instanceMap.checkout();
                        List<AnalysisEnginePerformanceMetrics> beforeAnalysis = 
getMetrics(ae);
-                       ae.process(cas);
+                       
+                       // Handle AnalysisEngineProcessException
+                       try {
+                               ae.process(cas);
+                       } catch( Throwable t) {
+                               // save the error
+                               errorMap.put(Thread.currentThread().getId(), t);
+                               // AE failed, throw an exception. The 
HttpWorketThread will 
+                               // subsequently call 
getLastSerializedException() on this class
+                               // to fetch serialized exception saved in 
errorMap above.
+                               // The map entry for each thread is reset in 
super.process().
+                               throw new RuntimeException(); 
+                       }
+                       // *****************************************************
+                       // No exception in process() , return metrics as a List
+                       // *****************************************************
                        List<AnalysisEnginePerformanceMetrics> afterAnalysis = 
getMetrics(ae);
 
                        // get the delta
@@ -210,11 +224,9 @@ public class UimaProcessContainer extend
                                metricsList.add(p);
                        }
                        return metricsList;
-               } catch( Throwable t ) {
-                       Logger logger = UIMAFramework.getLogger();
-                       logger.log(Level.WARNING, "UimaProcessContainer", t);
-                       throw new RuntimeException(super.serializeAsString(t));
-               }
+               } catch( Throwable tt ) {
+                       throw tt;
+               }
                finally {
                        if (ae != null) {
                                instanceMap.checkin(ae);
@@ -224,6 +236,9 @@ public class UimaProcessContainer extend
                        }
                }
        }
+       public byte[] getLastSerializedError() throws Exception {
+              return super.getLastSerializedError();
+       }
           private List<AnalysisEnginePerformanceMetrics> 
getMetrics(AnalysisEngine ae)
                        throws Exception {
                List<AnalysisEnginePerformanceMetrics> 
analysisManagementObjects = new ArrayList<AnalysisEnginePerformanceMetrics>();


Reply via email to