本文讲述在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. Android下fragment切换的动画效果

    网上看到的例子,转过来记录一下,学习一下,感谢原作者的辛勤编码,效果非常好 基于Android3.0新增的动画api,效果很赞 共21种动画效果: <item>X轴缩放</item& ...

  2. SpringMVC——hello SpringMVC

    概述: Spring的web框架围绕DispatcherServlet设计. DispatcherServlet的作用是将请求分发到不同的处理器. 与其它web MVC框架一样,Spring的web ...

  3. 【转】如何在eclipse里关联查看android源码

    原文网址:http://fengbohaishang.blog.51cto.com/5106297/1339556 以前没怎么注意过这个问题,不怎么看源码,现在发现源码确实是很好的学习资源. 直入正题 ...

  4. 去除 waring Method 'CreateNew' hides virtual method of base type 'TCustomForm'

    最近整理前人的代码,有好多的hint和waring, 其中整理到Method 'CreateNew' hides virtual method of base type 'TCustomForm', ...

  5. 为在MyEclipse中配置Tomcat服务器郁闷的朋友们解决郁闷

    是不是很郁闷!为了在MyEclipse配置Tomcat 服务器,竟然弄了你几乎一个上午,最后也没弄成功,也许你本该早注意到Tomcat 5.x要有这个JDK的支持,配置才能成功. 一上午辛辛苦苦也没解 ...

  6. ASP.NET MVC+Bootstrap个人博客之修复UEditor编辑时Bug(四)

    我的个人博客站在使用百度富文本编辑器UEditor修改文章时,遇到了一些问题,(不知是bug,还是我没有配置好).但总算找到了解决方法,在此记录下来. 小站首页文章列表显示为(显示去除HTML标签后的 ...

  7. codeforces 687B - Remainders Game 数学相关(互质中国剩余定理)

    题意:给你x%ci=bi(x未知),是否能确定x%k的值(k已知) ——数学相关知识: 首先:我们知道一些事情,对于k,假设有ci%k==0,那么一定能确定x%k的值,比如k=5和ci=20,知道x% ...

  8. 我的Myeclipse黑色主题

  9. csv文件与DataTable互相导入处理

    封装处理下,以后项目用到可以直接使用,比较简单. 1.首先看封装好的类 using System; using System.Data; using System.IO; using System.T ...

  10. 感知器Perceptron

    Perceptron: 1.一种基于监督的线性分类器,其特点是:1)模型简单,具有很少的学习参数:2)具有可视性,一条直线即可划分:3)基于人工神经网络的原理. 其结构图为:  2.学习的关键技术: ...