복붙노트

[HADOOP] Hadoop : java.lang.IncompatibleClassChangeError : 인터페이스 org.apache.hadoop.mapreduce.JobContext가 발견되었지만 클래스가 예상되었습니다.

HADOOP

Hadoop : java.lang.IncompatibleClassChangeError : 인터페이스 org.apache.hadoop.mapreduce.JobContext가 발견되었지만 클래스가 예상되었습니다.

내 MapReduce 작업은 Eclipse 프로젝트에서 종속성으로 포함 된 가능한 모든 Hadoop 및 Hive jar를 사용하여 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의 세 가지 jar가 있습니다.

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를 생성하는 것을 어떻게 찾을 수 있습니까? 인터페이스 org.apache.hadoop.mapreduce.JobContext가 발견되었지만 클래스가 예상 되었습니까?

이 문제를 해결하는 방법을 알려주세요. (내가 본 유일한 해결책은 소스에서 모든 것을 컴파일하는 것입니다!)

[/ 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();
      }

    }

해결법

  1. ==============================

    1.Hadoop은 Hadoop 1.0에서 Hadoop 2.0으로 거대한 코드 리팩토링을 수행했습니다. 하나의 부작용 Hadoop 1.0 용으로 컴파일 된 코드는 Hadoop 2.0과 호환되지 않으며 그 반대도 마찬가지입니다. 그러나 소스 코드는 대부분 호환되므로 대상을 가진 코드를 다시 컴파일해야합니다. Hadoop 배포판.

    Hadoop은 Hadoop 1.0에서 Hadoop 2.0으로 거대한 코드 리팩토링을 수행했습니다. 하나의 부작용 Hadoop 1.0 용으로 컴파일 된 코드는 Hadoop 2.0과 호환되지 않으며 그 반대도 마찬가지입니다. 그러나 소스 코드는 대부분 호환되므로 대상을 가진 코드를 다시 컴파일해야합니다. Hadoop 배포판.

    "인터페이스 X가 발견되었지만 클래스가 예상되었습니다."예외는 실행 중일 때 매우 일반적입니다. Hadoop 2.0에서 Hadoop 1.0 용으로 컴파일 된 코드.

    클러스터에서 사용되는 올바른 hadoop 버전을 찾은 다음 pom.xml 파일에 hadoop 버전을 지정하십시오. 클러스터에 사용 된 동일한 버전의 hadoop을 사용하여 프로젝트를 빌드하고 배포하십시오.

  2. ==============================

    2.Hadoop 2.0.0을 지원하려면 "hcatalog-core"를 다시 컴파일해야합니다. 현재 "hcatalog-core"는 Hadoop 1.0 만 지원합니다.

    Hadoop 2.0.0을 지원하려면 "hcatalog-core"를 다시 컴파일해야합니다. 현재 "hcatalog-core"는 Hadoop 1.0 만 지원합니다.

  3. ==============================

    3.분명히 Hadoop과 Hive 버전 사이에 버전이 호환되지 않습니다. Hadoop 버전 또는 Hive 버전을 업그레이드 (또는 다운 그레이드)해야합니다.

    분명히 Hadoop과 Hive 버전 사이에 버전이 호환되지 않습니다. Hadoop 버전 또는 Hive 버전을 업그레이드 (또는 다운 그레이드)해야합니다.

    이는 Hadoop 1과 Hadoop 2의 비 호환성 때문입니다.

  4. ==============================

    4.이런 항목을 찾으십시오.

    이런 항목을 찾으십시오.

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

    귀하의 pom.xml. 이것들은 사용할 hadoop 버전을 정의합니다. 요구 사항에 따라 변경하거나 제거하십시오.

  5. ==============================

    5.심지어 나는이 문제를 겪었다. hive-hcatalog-core-0.13.0.jar를 사용하여 HCatMultipleInputs를 사용하려고했습니다. 우리는 hadoop 2.5.1을 사용하고 있습니다.

    심지어 나는이 문제를 겪었다. hive-hcatalog-core-0.13.0.jar를 사용하여 HCatMultipleInputs를 사용하려고했습니다. 우리는 hadoop 2.5.1을 사용하고 있습니다.

    다음 코드 변경으로 문제를 해결할 수있었습니다.

    
    //JobContext ctx = new JobContext(conf,jobContext.getJobID());
    JobContext ctx = new Job(conf);
    
    
  6. from https://stackoverflow.com/questions/22630323/hadoop-java-lang-incompatibleclasschangeerror-found-interface-org-apache-hadoo by cc-by-sa and MIT license