Here is the error case:
try to run a cascading application with hadoop in local job tracker
mode;
$HADOOP_HOME/bin/hadoop jar my_app.jar my.cacascading.AppMain
with mapred.job.tracker set to 'local'.
-----
During running hadoop in local job tracker mode, hadoop RunJar
utility loads my_app.jar and registeres all the classeses on the
thread context classloader.
Since ObjectInputStream, which cascading.util.Util.deserializeBase64
method creates and uses, only uses the defining class loader of
cascading.util.Util, it cannot deserialize classes defined in
my_app.jar. It makes org.apache.hadoop.util.ReflectionUtils.setJobConf
fail.
You may think that this is not a common case; if I want to test a
cacading application in local, I can run it without hadoop RunJar. But
in the case that I want to switch the running mode between local mode
and distributed mode at runtime, I need to run my local jobs in this
way.
This patch, which makes ObjectInputStream try using thread context
classloader once, will make things all right and make cascading users
happy, including me.
can be applied on cascading 1.0.17-hadoop-0.19.1+ version:
--- cascading-1.0.17.old/src/core/cascading/util/Util.java 2009-11-08
06:19:53.000000000 +0900
+++
cascading-1.0.17.new/src/core/cascading/util/Util.java 2009-11-13
15:16:37.000000000 +0900
@@ -26,6 +26,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
@@ -91,7 +92,21 @@
try
{
ByteArrayInputStream bytes = new ByteArrayInputStream
( Base64.decodeBase64( string.getBytes() ) );
- ObjectInputStream in = new ObjectInputStream( bytes );
+ ObjectInputStream in = new ObjectInputStream( bytes ) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException
+ {
+ String name = desc.getName();
+ try
+ {
+ return Class.forName(name, false, Thread.currentThread
().getContextClassLoader());
+ }
+ catch (ClassNotFoundException ex)
+ {
+ return super.resolveClass(desc);
+ }
+ }
+ };
return in.readObject();
}