【问题标题】:MRUnit with Avro NullPointerException in Serialization序列化中带有 Avro NullPointerException 的 MRUnit
【发布时间】:2013-03-05 17:39:09
【问题描述】:

我正在尝试使用 MRUnit 测试 Hadoop .mapreduce Avro 作业。我收到如下所示的 NullPointerException。我附上了一部分 pom 和源代码。任何援助将不胜感激。

谢谢

我得到的错误是:

java.lang.NullPointerException
at org.apache.hadoop.mrunit.internal.io.Serialization.copy(Serialization.java:73)
at org.apache.hadoop.mrunit.internal.io.Serialization.copy(Serialization.java:91)
at org.apache.hadoop.mrunit.internal.io.Serialization.copyWithConf(Serialization.java:104)
at org.apache.hadoop.mrunit.TestDriver.copy(TestDriver.java:608)
at org.apache.hadoop.mrunit.MapDriverBase.setInputKey(MapDriverBase.java:64)
at org.apache.hadoop.mrunit.MapDriverBase.setInput(MapDriverBase.java:104)
at org.apache.hadoop.mrunit.MapDriverBase.withInput(MapDriverBase.java:218)
at org.lab41.project.mapreduce.ParseMetadataAsTextIntoAvroTest.testMap(ParseMetadataAsTextIntoAvroTest.java:115)
.....

pom sn-p:

<dependency>
    <groupId>org.apache.mrunit</groupId>
    <artifactId>mrunit</artifactId>
    <version>0.9.0-incubating</version>
    <classifier>hadoop2</classifier>
    <scope>test</scope>
</dependency>


<avro.version>1.7.4</avro.version>
<hadoop.version>2.0.0-mr1-cdh4.1.3</hadoop.version>

<dependency>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro</artifactId>
    <version>${avro.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>${hadoop.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-core</artifactId>
    <version>${hadoop.version}</version>
    <scope>provided</scope>
 </dependency>
 <dependency>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro-mapred</artifactId>
    <version>${avro.version}</version>
    <classifier>hadoop2</classifier>
 </dependency>

这是测试的摘录:

import static org.junit.Assert.*;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.apache.avro.mapred.AvroKey;
import org.apache.avro.hadoop.io.AvroSerialization;
import org.apache.avro.mapred.AvroValue;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mrunit.mapreduce.MapDriver;
import org.apache.hadoop.mrunit.types.Pair;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.lab41.project.domain.DataRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ParseMetadataAsTextIntoAvroTest {

    Logger logger = LoggerFactory
            .getLogger(ParseMetadataAsTextIntoAvroTest.class);
    private MapDriver<LongWritable, Text, AvroKey<Long>, AvroValue<DataRecord>> mapDriver;

    @BeforeClass
    public static void setUpClass() {
    }

    @AfterClass
    public static void tearDownClass() {
    }

    @Before
    public void setUp() throws IOException {
        ParseMetadataAsTextIntoAvroMapper mapper = new ParseMetadataAsTextIntoAvroMapper();

        mapDriver = new MapDriver<LongWritable, Text, AvroKey<Long>, AvroValue<DataRecord>>();
        mapDriver.setMapper(mapper);
        mapDriver.getConfiguration().setStrings("io.serializations", new String[]{  
            AvroSerialization.class.getName()
        });
    }

    @Test
    public void testMap() throws ParseException, IOException {
        Text testInputText = new Text(test0);

        DataRecord record = new DataRecord();
       ….

        AvroKey<Long> expectedPivot = new AvroKey<Long>(1L);
        AvroValue<DataRecord> expectedRecord = new AvroValue<DataRecord>(record);

        mapDriver.withInput(new Pair<LongWritable, Text>(new LongWritable(1), testInputText));
        mapDriver.withOutput(new Pair<AvroKey<Long>, AvroValue<DataRecord>>(expectedPivot, expectedRecord));
        mapDriver.runTest();

    }
}

【问题讨论】:

    标签: hadoop mapreduce avro mrunit


    【解决方案1】:

    为了使其工作,您已将AvroSerializatio 添加到默认序列化。您还必须配置AvroSerializationn

     @Before
    public void setUp() throws IOException {
        ParseMetadataAsTextIntoAvroMapper mapper = new ParseMetadataAsTextIntoAvroMapper();
        mapDriver = new MapDriver<LongWritable, Text, AvroKey<Long>, AvroValue<NetworkRecord>>();
        mapDriver.setMapper(mapper);
    
        //Copy over the default io.serializations. If you don't do this then you will 
        //not be able to deserialize the inputs to the mapper
        String[] strings = mapDriver.getConfiguration().getStrings("io.serializations");
        String[] newStrings = new String[strings.length +1];
        System.arraycopy( strings, 0, newStrings, 0, strings.length );
        newStrings[newStrings.length-1] = AvroSerialization.class.getName();
    
        //Now you have to configure AvroSerialization by sepecifying the key
        //writer Schema and the value writer schema.
        mapDriver.getConfiguration().setStrings("io.serializations", newStrings);
        mapDriver.getConfiguration().setStrings("avro.serialization.key.writer.schema", Schema.create(Schema.Type.LONG).toString(true));
        mapDriver.getConfiguration().setStrings("avro.serialization.value.writer.schema", NetworkRecord.SCHEMA$.toString(true));
    }
    

    【讨论】:

    • 由于已发布补丁的 MRUnit 错误 (MRUNIT-193),NPE 未附带说明性错误消息。
    • 真的讨厌这样问,但这是一个非常具体的问题,能回答的人很少。由于您在这里的回答帮助我克服了问题的前半部分,我希望您也能帮助我克服下一部分:stackoverflow.com/questions/22591342/…
    【解决方案2】:

    这也解决了问题,优点是代码更短更清晰。

            MapDriver driver = MapDriver.newMapDriver(your mapper);
    
            Configuration conf = driver.getConfiguration();
            AvroSerialization.addToConfiguration(conf);
            AvroSerialization.setKeyWriterSchema(conf, your schema);
            AvroSerialization.setKeyReaderSchema(conf, your schema);
            Job job = new Job(conf);
            job.set... your job settings;
            AvroJob.set... your avro job settings;
    

    可能是 mrunit 的错误,没有正确设置 io.serializations 相反,我认为应该由 job.setInputFormatClass(AvroKeyInputFormat.class) 设置。

    【讨论】:

      【解决方案3】:

      您必须将AvroSerialization 添加到默认序列化并配置AvroSerialization

      @Before
      public void setUp() throws IOException {
          ParseMetadataAsTextIntoAvroMapper mapper = new ParseMetadataAsTextIntoAvroMapper();
          mapDriver = new MapDriver<LongWritable, Text, AvroKey<Long>, AvroValue<NetworkRecord>>();
          mapDriver.setMapper(mapper);
          Configuration configuration = mapDriver.getConfiguration();
      
          // Add AvroSerialization to the configuration
          // (copy over the default serializations for deserializing the mapper inputs)
          String[] serializations = configuration.getStrings(CommonConfigurationKeysPublic.IO_SERIALIZATIONS_KEY);
          String[] newSerializations = Arrays.copyOf(serializations, serializations.length + 1);
          newSerializations[serializations.length] = AvroSerialization.class.getName();
          configuration.setStrings(CommonConfigurationKeysPublic.IO_SERIALIZATIONS_KEY, newSerializations);
      
          //Configure AvroSerialization by specifying the key writer and value writer schemas
          AvroSerialization.setKeyWriterSchema(configuration, Schema.create(Schema.Type.LONG));
          AvroSerialization.setValueWriterSchema(configuration, NetworkRecord.SCHEMA$)
      }
      

      【讨论】:

      • Karthik 的回答是绝对正确的,我在这里为那些想要复制/粘贴的人做一些清理工作,因为我对他的回答的编辑被拒绝了。
      【解决方案4】:

      【讨论】:

      • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(相对于另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
      猜你喜欢
      • 2020-10-05
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 2020-03-04
      相关资源
      最近更新 更多