/* * Copyright © 2016 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.internal.app.runtime.batch.dataset.input; import co.cask.cdap.api.app.AbstractApplication; import co.cask.cdap.api.data.batch.Input; import co.cask.cdap.api.data.batch.Output; import co.cask.cdap.api.dataset.lib.KeyValueTable; import co.cask.cdap.api.mapreduce.AbstractMapReduce; import co.cask.cdap.api.mapreduce.MapReduceContext; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; /** * App used to test that a MapReduce using multiple mappers must be of same output key/value types. */ public class AppWithMapReduceUsingInconsistentMappers extends AbstractApplication { @Override public void configure() { setName("AppWithMapReduceUsingInconsistentMappers"); setDescription("Application with MapReduce jobs, to test Mapper type checking"); addMapReduce(new MapReduceWithConsistentMapperTypes()); addMapReduce(new MapReduceWithInconsistentMapperTypes()); addMapReduce(new MapReduceWithInconsistentMapperTypes2()); // the types of the datasets do not matter, because we never actually write or read to/from them createDataset("input1", KeyValueTable.class); createDataset("input2", KeyValueTable.class); createDataset("output", KeyValueTable.class); } /** * Performs no data operations, but simply runs to test mapper output type checking. */ private abstract static class BaseMapReduce extends AbstractMapReduce { @Override public void beforeSubmit(MapReduceContext context) throws Exception { // the inputs will be set in child classes context.addOutput(Output.ofDataset("output")); Job job = context.getHadoopJob(); job.setReducerClass(SomeReducer.class); } } /** * MapReduce job that has two mapper classes, both with the same output types. */ public static final class MapReduceWithConsistentMapperTypes extends BaseMapReduce { @Override public void beforeSubmit(MapReduceContext context) throws Exception { context.addInput(Input.ofDataset("input1"), OriginalMapper.class); context.addInput(Input.ofDataset("input2"), ConsistentMapper.class); super.beforeSubmit(context); } } /** * MapReduce job that has two mapper classes, each with different output types, both set through the CDAP APIs. */ public static final class MapReduceWithInconsistentMapperTypes extends BaseMapReduce { @Override public void beforeSubmit(MapReduceContext context) throws Exception { context.addInput(Input.ofDataset("input1"), OriginalMapper.class); context.addInput(Input.ofDataset("input2"), InconsistentMapper.class); Job job = context.getHadoopJob(); // none of the inputs default to the job-defined mapper, so an inconsistent mapper defined here gives no issue job.setMapperClass(InconsistentMapper.class); super.beforeSubmit(context); } } /** * MapReduce job that has two mapper classes, each with different output types (one set through CDAP APIs and one set * directly on the job). */ public static final class MapReduceWithInconsistentMapperTypes2 extends BaseMapReduce { @Override public void beforeSubmit(MapReduceContext context) throws Exception { context.addInput(Input.ofDataset("input1"), OriginalMapper.class); context.addInput(Input.ofDataset("input2")); Job job = context.getHadoopJob(); job.setMapperClass(InconsistentMapper.class); super.beforeSubmit(context); } } /** * Simple Mapper class. */ public static class OriginalMapper extends Mapper<LongWritable, Text, LongWritable, Text> { } /** * Mapper class that has output types, same as {@link OriginalMapper}. */ public static class ConsistentMapper extends Mapper<LongWritable, Text, LongWritable, Text> { } /** * Mapper class that has output types being different than {@link OriginalMapper}. */ public static class InconsistentMapper extends Mapper<LongWritable, Text, IntWritable, Text> { } /** * Simple Reducer class. */ public static class SomeReducer extends Reducer<LongWritable, Text, String, String> { } }