web-dev-qa-db-ja.com

Hadoop:Java.lang.IncompatibleClassChangeError:インターフェースorg.Apache.hadoop.mapreduce.JobContextが見つかりましたが、クラスが必要でした

私のMapReduceジョブは、Eclipseプロジェクトに依存関係として含まれている可能性のあるすべてのHadoopおよびHive jarを使用してEclipseでアセンブルすると、正常に実行されます。 (これらは、単一ノードのローカルHadoopインストールに付属するjarです)。

しかし、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>

*互換性のあるHadoopjarを見つける場所と方法を教えてください。 *

[update_1]Hadoop2.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のjarが3つあります。

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です。このjarの最新バージョンが見つかりませんでした。必要です。

これらの4つのjarファイルのどれが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();
      }

    }
10
dokondr

Hadoopは、Hadoop 1.0からHadoop 2.0への巨大なコードリファクタリングを経てきました。副作用の1つは、Hadoop1.0に対してコンパイルされたコードがHadoop2.0と互換性がないことです。その逆も同様です。ただし、ソースコードはほとんど互換性があるため、ターゲットのHadoopディストリビューションを使用してコードを再コンパイルする必要があります。

例外「Found interface X, but class was expected」は、Hadoop2.0でHadoop1.0用にコンパイルされたコードを実行している場合、またはその逆の場合に非常に一般的です。

クラスターで使用されている正しいHadoopバージョンを見つけて、pom.xmlファイルでそのHadoopバージョンを指定します。クラスターで使用されているのと同じバージョンのHadoopを使用してプロジェクトをビルドし、デプロイします。

11
SachinJ

Hadoop 2.0.0をサポートするには、「hcatalog-core」を再コンパイルする必要があります。現在、「hcatalog-core」はHadoop1.0のみをサポートしています

1
akshat thakar

明らかに、HadoopバージョンとHiveバージョンの間にバージョンの非互換性があります。 HadoopバージョンまたはHiveバージョンをアップグレード(またはダウングレード)する必要があります。

これは、Hadoop1とHadoop2の非互換性によるものです。

0
Chiron

私でさえこの問題に遭遇しました。 Hive-hcatalog-core-0.13.0.jarでHCatMultipleInputsを使用しようとしていました。 Hadoop2.5.1を使用しています。

次のコード変更は、問題の修正に役立ちました。

 
 // JobContext ctx = new JobContext(conf、jobContext.getJobID()); 
 JobContext ctx = new 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