it-swarm.com.ru

Hadoop: Java.lang.IncompatibleClassChangeError: найден интерфейс org.Apache.hadoop.mapreduce.JobContext, но ожидался класс

Мои задания MapReduce выполняются нормально при сборке в Eclipse со всеми возможными банками Hadoop и Hive, включенными в проект Eclipse в качестве зависимостей. (Это файлы, поставляемые с одним узлом, локальная установка Hadoop). 

Тем не менее, при попытке запустить ту же программу, собранную с помощью проекта Maven (см. Ниже), я получаю: 

 Exception in thread "main" Java.lang.IncompatibleClassChangeError: Found interface org.Apache.hadoop.mapreduce.JobContext, but class was expected

Это исключение происходит, когда программа собирается с использованием следующего проекта Maven: 

<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.bigdata.hadoop</groupId>
  <artifactId>FieldCounts</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>FieldCounts</name>
  <url>http://maven.Apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
     <dependency>
        <groupId>org.Apache.hadoop</groupId>
        <artifactId>hadoop-hdfs</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>org.Apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>2.2.0</version>
    </dependency>
<dependency>
    <groupId>org.Apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.Apache.Hive.hcatalog</groupId>
    <artifactId>hcatalog-core</artifactId>
    <version>0.12.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>16.0.1</version>
</dependency>
  </dependencies>     
    <build>
    <plugins>
      <plugin>
        <groupId>org.Apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
            <source>${jdk.version}</source>
            <target>${jdk.version}</target>
        </configuration>
      </plugin>       
  <plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-Assembly-plugin</artifactId>
    <executions>
      <execution>
         <goals>
           <goal>attached</goal>
         </goals>
         <phase>package</phase>
         <configuration>
           <descriptorRefs>
             <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.bigdata.hadoop.FieldCounts</mainClass>
            </manifest>
          </archive>
        </configuration>
     </execution>
  </executions>
</plugin>
 </plugins>
 </build>       
</project>

* Посоветуйте, пожалуйста, где и как найти совместимые банки Hadoop? *

[update_1] Я использую Hadoop 2.2.0.2.0.6.0-101

Как я нашел здесь: https://github.com/kevinweil/elephant-bird/issues/247

Hadoop 1.0.3: JobContext - это класс

Hadoop 2.0.0: JobContext - это интерфейс

В моем pom.xml у меня есть три банки с версией 2.2.0 

hadoop-hdfs 2.2.0
hadoop-common 2.2.0
hadoop-mapreduce-client-jobclient 2.2.0
hcatalog-core 0.12.0

Единственное исключение - hcatalog-core, версия которого 0.12.0, я не смог найти более позднюю версию этого фляги и мне это нужно!

Как я могу найти, какой из этих 4 банок производит Java.lang.IncompatibleClassChangeError: Found interface org.Apache.hadoop.mapreduce.JobContext, but class was expected?

Пожалуйста, дайте мне идею, как решить эту проблему. (Единственное решение, которое я вижу, - это скомпилировать все из исходного кода!)

[/ update_1]

Полный текст моей работы MarReduce:

package com.bigdata.hadoop;

import Java.io.IOException;
import Java.util.*;

import org.Apache.hadoop.conf.*;
import org.Apache.hadoop.io.*;
import org.Apache.hadoop.mapreduce.*;
import org.Apache.hadoop.util.*;
import org.Apache.hcatalog.mapreduce.*;
import org.Apache.hcatalog.data.*;
import org.Apache.hcatalog.data.schema.*;
import org.Apache.log4j.Logger;

public class FieldCounts extends Configured implements Tool {

    public static class Map extends Mapper<WritableComparable, HCatRecord, TableFieldValueKey, IntWritable> {

        static Logger logger = Logger.getLogger("com.foo.Bar");

        static boolean firstMapRun = true;
        static List<String> fieldNameList = new LinkedList<String>();
        /**
         * Return a list of field names not containing `id` field name
         * @param schema
         * @return
         */
        static List<String> getFieldNames(HCatSchema schema) {
            // Filter out `id` name just once
            if (firstMapRun) {
                firstMapRun = false;
                List<String> fieldNames = schema.getFieldNames();
                for (String fieldName : fieldNames) {
                    if (!fieldName.equals("id")) {
                        fieldNameList.add(fieldName);
                    }
                }
            } // if (firstMapRun)
            return fieldNameList;
        }

        @Override
      protected void map( WritableComparable key,
                          HCatRecord hcatRecord,
                          //org.Apache.hadoop.mapreduce.Mapper
                          //<WritableComparable, HCatRecord, Text, IntWritable>.Context context)
                          Context context)
            throws IOException, InterruptedException {

            HCatSchema schema = HCatBaseInputFormat.getTableSchema(context.getConfiguration());

           //String schemaTypeStr = schema.getSchemaAsTypeString();
           //logger.info("******** schemaTypeStr ********** : "+schemaTypeStr);

           //List<String> fieldNames = schema.getFieldNames();
            List<String> fieldNames = getFieldNames(schema);
            for (String fieldName : fieldNames) {
                Object value = hcatRecord.get(fieldName, schema);
                String fieldValue = null;
                if (null == value) {
                    fieldValue = "<NULL>";
                } else {
                    fieldValue = value.toString();
                }
                //String fieldNameValue = fieldName+"."+fieldValue;
                //context.write(new Text(fieldNameValue), new IntWritable(1));
                TableFieldValueKey fieldKey = new TableFieldValueKey();
                fieldKey.fieldName = fieldName;
                fieldKey.fieldValue = fieldValue;
                context.write(fieldKey, new IntWritable(1));
            }

        }       
    }

    public static class Reduce extends Reducer<TableFieldValueKey, IntWritable,
                                       WritableComparable, HCatRecord> {

        protected void reduce( TableFieldValueKey key,
                               Java.lang.Iterable<IntWritable> values,
                               Context context)
                               //org.Apache.hadoop.mapreduce.Reducer<Text, IntWritable,
                               //WritableComparable, HCatRecord>.Context context)
            throws IOException, InterruptedException {
            Iterator<IntWritable> iter = values.iterator();
            int sum = 0;
            // Sum up occurrences of the given key 
            while (iter.hasNext()) {
                IntWritable iw = iter.next();
                sum = sum + iw.get();
            }

            HCatRecord record = new DefaultHCatRecord(3);
            record.set(0, key.fieldName);
            record.set(1, key.fieldValue);
            record.set(2, sum);

            context.write(null, record);
        }
    }

    public int run(String[] args) throws Exception {
        Configuration conf = getConf();
        args = new GenericOptionsParser(conf, args).getRemainingArgs();

        // To fix Hadoop "META-INFO" (http://stackoverflow.com/questions/17265002/hadoop-no-filesystem-for-scheme-file)
        conf.set("fs.hdfs.impl",
                org.Apache.hadoop.hdfs.DistributedFileSystem.class.getName());
        conf.set("fs.file.impl",
                org.Apache.hadoop.fs.LocalFileSystem.class.getName());

        // Get the input and output table names as arguments
        String inputTableName = args[0];
        String outputTableName = args[1];
        // Assume the default database
        String dbName = null;

        Job job = new Job(conf, "FieldCounts");

        HCatInputFormat.setInput(job,
                InputJobInfo.create(dbName, inputTableName, null));
        job.setJarByClass(FieldCounts.class);
        job.setMapperClass(Map.class);
        job.setReducerClass(Reduce.class);

        // An HCatalog record as input
        job.setInputFormatClass(HCatInputFormat.class);

        // Mapper emits TableFieldValueKey as key and an integer as value
        job.setMapOutputKeyClass(TableFieldValueKey.class);
        job.setMapOutputValueClass(IntWritable.class);

        // Ignore the key for the reducer output; emitting an HCatalog record as
        // value
        job.setOutputKeyClass(WritableComparable.class);
        job.setOutputValueClass(DefaultHCatRecord.class);
        job.setOutputFormatClass(HCatOutputFormat.class);

        HCatOutputFormat.setOutput(job,
                OutputJobInfo.create(dbName, outputTableName, null));
        HCatSchema s = HCatOutputFormat.getTableSchema(job);
        System.err.println("INFO: output schema explicitly set for writing:"
                + s);
        HCatOutputFormat.setSchema(job, s);
        return (job.waitForCompletion(true) ? 0 : 1);
    }

    public static void main(String[] args) throws Exception {
        String classpath = System.getProperty("Java.class.path");
        //System.out.println("*** CLASSPATH: "+classpath);       
        int exitCode = ToolRunner.run(new FieldCounts(), args);
        System.exit(exitCode);
    }
}

И класс для сложного ключа:

package com.bigdata.hadoop;

import Java.io.DataInput;
import Java.io.DataOutput;
import Java.io.IOException;

import org.Apache.hadoop.io.WritableComparable;

import com.google.common.collect.ComparisonChain;

public class TableFieldValueKey  implements WritableComparable<TableFieldValueKey> {

      public String fieldName;
      public String fieldValue;

      public TableFieldValueKey() {} //must have a default constructor
      //

      public void readFields(DataInput in) throws IOException {
        fieldName = in.readUTF();
        fieldValue = in.readUTF();
      }

      public void write(DataOutput out) throws IOException {
        out.writeUTF(fieldName);
        out.writeUTF(fieldValue);
      }

      public int compareTo(TableFieldValueKey o) {
        return ComparisonChain.start().compare(fieldName, o.fieldName)
            .compare(fieldValue, o.fieldValue).result();
      }

    }
9
dokondr

Hadoop прошел огромный рефакторинг кода с Hadoop 1.0 на Hadoop 2.0. Одним из побочных эффектов является то, что код, скомпилированный с использованием Hadoop 1.0, не совместим с Hadoop 2.0 и наоборот . Однако исходный код в основном совместим, и поэтому нужно просто перекомпилировать код с целевым Распределением Hadoop.

Исключение «Found interface X, but class was expected» очень распространено, когда вы запускаете Код, скомпилированный для Hadoop 1.0 на Hadoop 2.0 или наоборот.

Вы можете найти правильную версию hadoop, используемую в кластере, а затем указать эту версию hadoop в файле pom.xml. Создайте свой проект с той же версией hadoop, которая использовалась в кластере, и разверните ее.

10
SachinJ

Вам нужно перекомпилировать "hcatalog-core" для поддержки Hadoop 2.0.0 . В настоящее время "hcatalog-core" поддерживает только Hadoop 1.0

1
akshat thakar

Очевидно, что у вас есть несовместимость версий между версиями Hadoop и Hive. Вам необходимо обновить (или понизить) версию Hadoop или версию Hive.

Это связано с несовместимостью между Hadoop 1 и Hadoop 2.

0
Chiron

Даже я пробежал эту проблему. Пытался использовать HCatMultipleInputs с Hive-hcatalog-core-0.13.0.jar. Мы используем hadoop 2.5.1.

Следующее изменение кода помогло мне решить проблему:

 // JobContext ctx = новый JobContext (conf, jobContext.getJobID ()); 
 JobContext ctx = новое Job (conf); 

0
Abhiram

Посмотрите на записи, как это

<dependency>
            <groupId>org.Apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>1.2.1</version>
</dependency>

в вашем pom.xml . Они определяют версию hadoop для использования. Измените их или удалите их в соответствии с вашими требованиями.

0
nikoo28