本文讲述在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. PHP单元测试工具PHPUnit初体验

    今天接到了个任务,需要对数字进行计算,因为涉及到整数,小数,和科学计数法等很多条件,所以人工测试非常麻烦,于是想到了PHP的单元测试工具PHPUnit,所以写个文档备查. 看了PHPUnit的文档之后 ...

  2. <十>面向对象分析之UML核心元素之关系

    关系        --->在UML中关系是非常重要的语义,它抽象出对象之间的联系,让对象构成特定的结构.        一,关联关系(association)

  3. sql给数据库加锁问题

    加锁是在操作数据时进行了,不能事后加锁. 例: begin   tran           insert   表   with(TABLOCKX)     --加锁           (字段列表) ...

  4. 【MySQL】Java对SQL时间类型的操作(获得当前、昨天、前年。。时间)

    Java获得当前时间 java.util.Date date = new java.util.Date(); Timestamp time = new Timestamp(date.getTime() ...

  5. 如何使用 orachk 工具

    Oracle RAC 安装完毕后的健壮性是一个令人头疼的问题.之前Oracle为之专门推出了raccheck工具,确实方便了我们这些个苦逼的DBA.现在Oracle在raccheck的基础之上又推出了 ...

  6. Android-关于android:scrollbarStyle属性

    1. activity_maim.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android ...

  7. How to Download APK Files from Google Play Store

    Evozi, an Android app developer, offers a one-click online APK download app that lets you download t ...

  8. 用命令行(CMD)中启动和关闭ORACLE服务

    lsnrctl start开启监听 lsnrctl stop停止监听 net start oracleserviceoracle开启oracle服务 net stop oracleserviceora ...

  9. linux 标准 GPIO 操作

    Linux 提供了GPIO 操作的 API,具体初始化及注册函数在 driver/gpio/lib_gpio.c 中实现.   #include    int gpio_request(unsigne ...

  10. 高性能Server---Reactor模型-----Socket

    高性能Server---Reactor模型   原文地址:http://www.ivaneye.com/2016/07/23/iomodel.html 无处不在的C/S架构 在这个充斥着云的时代,我们 ...