本文讲述在IntelliJ IDEA中使用MRUnit 1.0.0测试Mapper派生类时因MapDriver.withInput(final K1 key, final V1 val)的key参数被错误设置成空字符串""导致No applicable class implementing Serialization的解决过程。

环境:Mac OS X 10.9.5, IntelliJ IDEA 13.1.4, Hadoop 1.2.1, MRUnit 1.0.0

Hadoop放在虚拟机中,宿主机通过SSH连接,IDE和数据文件在宿主机。IDEA自身运行于JDK 1.8,IDEA工程及Hadoop使用JDK 1.6。

这是个粗心的错误。

操作代码如下:

 @SuppressWarnings("all")
public class MapDriverTest {
private Mapper mapper;
private MapDriver driver; @Before
public void init() {
mapper = new TextMapper();
driver = new MapDriver(mapper);
} @Test
public void test() {
String content = "This is a simple test for TextMapper created by Michael";
try {
driver.withInput("", new Text(content))
.withOutput(new Text("this"), new IntWritable(1))
.withOutput(new Text("is"), new IntWritable(1))
.withOutput(new Text("a"), new IntWritable(1))
.withOutput(new Text("simple"), new IntWritable(1))
.withOutput(new Text("test"), new IntWritable(1))
.withOutput(new Text("for"), new IntWritable(1))
.withOutput(new Text("TextMapper"), new IntWritable(1))
.withOutput(new Text("created"), new IntWritable(1))
.withOutput(new Text("by"), new IntWritable(1))
.withOutput(new Text("Michael"), new IntWritable(1))
.runTest();
} catch (IOException e) {
e.printStackTrace();
}
}
}

相关类代码如下:

 public class TextMapper extends Mapper<Object, Text, Text, IntWritable> {
final IntWritable count = new IntWritable(1);
final Text text = new Text(); @Override
protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer tokenizer = new StringTokenizer(value.toString());
while (tokenizer.hasMoreTokens()) {
text.set(tokenizer.nextToken());
context.write(text, count);
}
}
}

执行结果如下:

设置成""是完成参考别人代码写的,所以我不知如此设置的原因,原因是Hadoop有一套专用数据类型,分别映射了java基本类型,这里设置成""将被当成设置为String类型,在序列化时因不是Hadoop的数据类型,因而报错(更新于2014.10.06)。下面描述解决过程。

第一步,对比了参考代码,无拼写错误。

第二步,第一次使用MRUnit,Hadoop也刚学习,没人指导,纯抓瞎。只能先验证测试代码本身能否跑起来。注释掉MapDriverTest.test()中driver调用部分,并在init()及test()、TextMapper的map(args)中加入日志,看看代码执行到哪里报错。主体代码示意如下:

MapDriverTest

 @Before
public void init() {
System.out.println("init BEGIN");
mapper = new TextMapper();
driver = new MapDriver(mapper);
System.out.println("init END");
} @Test
public void test() {
System.out.println("test BEGIN");
String content = "This is a simple test for TextMapper created by Michael";
/*try {
driver.withInput("", new Text(content))...*/
System.out.println("test END");
}

TextMapper

 @Override
protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String keyString = key == null ? "null" : key.toString();
String valueString = value == null ? "null" : value.toString();
String invokeString = "map(key = " + keyString +
", value = " + valueString + ") BEGIN";
System.out.println(invokeString);
StringTokenizer tokenizer = new StringTokenizer(value.toString());
while (tokenizer.hasMoreTokens()) {
System.out.println("while RUN");
text.set(tokenizer.nextToken());
context.write(text, count);
}
System.out.println("map END");
}

按预期,还没调用driver.run()或runtTest(),则TextMapper的map方法日志不会输出。现在执行,输出如下

init BEGIN
init END
test BEGIN
test END

符合预期,测试代码运行正常。

第三步,恢复test方法至上一版本,特别处理driver.withInput的输入参数,为key及value传入相同的值,观察运行结果。新代码如下:

 @Test
public void test() {
System.out.println("test BEGIN");
String content = "This is a simple test for TextMapper created by Michael";
try {
//driver.withInput("", new Text(content))
driver.withInput(new Text(content), new Text(content)) // pass the same params to withInput, see how it acts.
.withOutput(new Text("This"), new IntWritable(1))
.withOutput(new Text("is"), new IntWritable(1))
.withOutput(new Text("a"), new IntWritable(1))
.withOutput(new Text("simple"), new IntWritable(1))
.withOutput(new Text("test"), new IntWritable(1))
.withOutput(new Text("for"), new IntWritable(1))
.withOutput(new Text("TextMapper"), new IntWritable(1))
.withOutput(new Text("created"), new IntWritable(1))
.withOutput(new Text("by"), new IntWritable(1))
.withOutput(new Text("Michael"), new IntWritable(1))
.runTest();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("test END");
}

按资料说明,key参数表示每行的字节偏移量[1]。之前传入"",现在传入与value相同的值,不要位置数据了。走一个,看看啥情况。似乎成功了,看图。

现在,可以认定是key传递""导致的错误了。

再做一次调整,传递key = new Text(),观察执行结果。

通过了。

什么,你要试试传递key = null。会报错的。另外,日志打印用的key == null ? "null" : key.toString()语句,意义不大,因为传递null会导致java.lang.NullPointerException。网上的资料好多是传递null的,我这边测试会报空指向异常。怀疑是RMUnit版本问题。

第一次使用RMUnit,遇到这个问题,即使目前不知原因,但还是勉强跑起来了,继续尝试。

参考

[1]Chuck Lam. Hadoop In Action. Manning Publications. 2010

Hadoop on Mac with IntelliJ IDEA - 3 解决MRUnit - No applicable class implementing Serialization问题的更多相关文章

  1. Hadoop on Mac with IntelliJ IDEA - 7 解决failed to report status for 600 seconds. Killing!问题

    本文讲述作业在Hadoop 1.2.1完成map后ruduce阶段遇到failed to report status for 600 seconds. Killing!问题的解决过程. 环境:Mac ...

  2. Hadoop on Mac with IntelliJ IDEA - 1 解决input path does not exist问题

    本文讲述使用IntelliJ IDEA时遇到Hadoop提示input path does not exist(输入路径不存在)的解决过程. 环境:Mac OS X 10.9.5, IntelliJ ...

  3. Hadoop on Mac with IntelliJ IDEA - 6 解决KeyValueTextInputFormat读取时只有key值问题

    本文讲述使用KeyValueTextInputFormat在Hadoop 0.x正常工作.Hadoop 1.2.1失效的解决过程. 环境:Mac OS X 10.9.5, IntelliJ IDEA ...

  4. Hadoop on Mac with IntelliJ IDEA - 5 解决java heap space问题

    本文讲述在CentOS 6.5中提交作业到hadoop 1.2.1于reduce阶段遇到Error: java heap space错误导致作业重新计算的解决过程.解决办法适用Linux.Mac OS ...

  5. Hadoop on Mac with IntelliJ IDEA - 2 解决URI错误导致Permission denied

    本文讲述在IntelliJ IDEA中使用FileSystem.copyFromLocalFile操作Hadoop时因URI格式有误导致Permission denied的解决过程. 环境:Mac O ...

  6. Hadoop on Mac with IntelliJ IDEA - 9 解决Type mismatch in value from map问题

    修改陆喜恒. Hadoop实战(第2版)5.3排序的代码时遇到IO异常. 环境:Mac OS X 10.9.5, IntelliJ IDEA 13.1.5, Hadoop 1.2.1 异常具体信息如下 ...

  7. Hadoop on Mac with IntelliJ IDEA - 8 单表关联NullPointerException

    简化陆喜恒. Hadoop实战(第2版)5.4单表关联的代码时遇到空指向异常,经分析是逻辑问题,在此做个记录. 环境:Mac OS X 10.9.5, IntelliJ IDEA 13.1.5, Ha ...

  8. Hadoop on Mac with IntelliJ IDEA - 4 制作jar包

    本文讲述使用IntelliJ IDEA打包Project的过程,即,打jar包. 环境:Mac OS X 10.9.5, IntelliJ IDEA 13.1.4, Hadoop 1.2.1 Hado ...

  9. Hadoop on Mac with IntelliJ IDEA - 10 陆喜恒. Hadoop实战(第2版)6.4.1(Shuffle和排序)Map端 内容整理

    下午对着源码看陆喜恒. Hadoop实战(第2版)6.4.1  (Shuffle和排序)Map端,发现与Hadoop 1.2.1的源码有些出入.下面作个简单的记录,方便起见,引用自书本的语句都用斜体表 ...

随机推荐

  1. erlang reduction

    “首先明确一点,Erlang的process的调度是抢占式的,而非couroutine的协作式的.其次,Erlang早期版本是只有一个调度器,运行在一个线程上,随着erts的发展,现在erlang的调 ...

  2. Android 实现emoji表情的demo

    Android 实现emoji表情的例子,网上看到的,记录一下. 请看下图 : 项目下载地址:http://download.csdn.net/detail/abc13939746593/741397 ...

  3. ECshop 二次开发模板教程2

    不知道大家是学会用循环了呢,还是我的言语实在有问题,大家实在无法完成阅读哦,居然大家都没有问题,暂时心里安慰,把他当做好事情,大家都会调用了,呵呵,那我们继续循环调用商品了!好,继续在我们昨天的基础上 ...

  4. [Everyday Mathematics]20150105

    设 $f\in C^1(a,b)$ 适合 $$\bex \lim_{x\to a^+}f(x)=+\infty,\quad \lim_{x\to b^-}f(x)=-\infty, \eex$$ 并且 ...

  5. 获取手机中已安装apk文件信息(PackageInfo、ResolveInfo)(应用图片、应用名、包名等)

    众所周知,通过PackageManager可以获取手机端已安装的apk文件的信息,具体代码如下: PackageManager packageManager = this.getPackageMana ...

  6. HDU 1892-See you(二维BIT)

    题意: 最多1000*1000的方格,各方格开始有一本书 有四种操作:对指定方格把书拿走或向里面放书,从一个方格那一定量的书放到另一个方格,查询给定对角线顶点的坐标的矩形范围内包含的书的总数 分析: ...

  7. 马上着手开发Mac应用程序

    你是否想要开发 Mac 应用程序却又不知道从哪里入手?本路线图提供了 Mac 应用程序开发的绝佳起点,即使你已经是一个 iOS 开发专家,本路线图对你依然适用.Apple让开发应用程序和提交应用程序到 ...

  8. 对象指针与this指针

    对象指针分为三大类 [1]指向对象的指针 [2]指向对象成员的指针(数据类) [3]指向对象成员的指针(函数类) #include<iostream> using namespace st ...

  9. 多校6 1003 HDU5795 A Simple Nim (sg函数)

    思路:直接打表找sg函数的值,找规律,没有什么技巧 还想了很久的,把数当二进制看,再类讨二进制中1的个数是必胜或者必败状态.... 打表: // #pragma comment(linker, &qu ...

  10. [算法] 选择排序 Selection sort

    选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然 ...