You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hbase.apache.org by "Michael Jin (JIRA)" <ji...@apache.org> on 2018/03/27 12:10:00 UTC

[jira] [Created] (HBASE-20295) TableOutputFormat.checkOutputSpecs throw NullPointerException Exception

Michael Jin created HBASE-20295:
-----------------------------------

             Summary: TableOutputFormat.checkOutputSpecs throw NullPointerException Exception
                 Key: HBASE-20295
                 URL: https://issues.apache.org/jira/browse/HBASE-20295
             Project: HBase
          Issue Type: Bug
          Components: Client
    Affects Versions: 1.4.0
         Environment: Spark 2.2.1, HBase 1.4.0
            Reporter: Michael Jin


I am using spark write data to HBase by using RDD.

saveAsNewAPIHadoopDataset function, it works fine with hbase 1.3.1, but when update my hbase dependency to 1.4.0 in pom.xml, it throw java.lang.NullPointerException, it is caused by a logic error in TableOutputFormat.checkOutputSpecs function, please check below details:

first let's take a look at SparkHadoopMapReduceWriter.write function in SparkHadoopMapReduceWriter.scala
{code:java}
// SparkHadoopMapReduceWriter.write (org.apache.spark.internal.io.SparkHadoopMapReduceWriter.scala)

def write[K, V: ClassTag](
    rdd: RDD[(K, V)],
    hadoopConf: Configuration): Unit = {
  // Extract context and configuration from RDD.
  val sparkContext = rdd.context
  val stageId = rdd.id
  val sparkConf = rdd.conf
  val conf = new SerializableConfiguration(hadoopConf)

  // Set up a job.
  val jobTrackerId = SparkHadoopWriterUtils.createJobTrackerID(new Date())
  val jobAttemptId = new TaskAttemptID(jobTrackerId, stageId, TaskType.MAP, 0, 0)
  val jobContext = new TaskAttemptContextImpl(conf.value, jobAttemptId)
  val format = jobContext.getOutputFormatClass

  if (SparkHadoopWriterUtils.isOutputSpecValidationEnabled(sparkConf)) {
    // FileOutputFormat ignores the filesystem parameter
    val jobFormat = format.newInstance
    jobFormat.checkOutputSpecs(jobContext)
  }

  val committer = FileCommitProtocol.instantiate(
    className = classOf[HadoopMapReduceCommitProtocol].getName,
    jobId = stageId.toString,
    outputPath = conf.value.get("mapreduce.output.fileoutputformat.outputdir"),
    isAppend = false).asInstanceOf[HadoopMapReduceCommitProtocol]
  committer.setupJob(jobContext)
...{code}
in "write" function if output spec validation is enabled, it will call checkOutputSpec function in TableOutputFormat class, but the job format is simply created by "vall jobFormat = format.newInstance", this will NOT initialize "conf" member variable in TableOutputFormat class, let's continue check checkOutputSpecs function in TableOutputFormat class

 
{code:java}
// TableOutputFormat.checkOutputSpecs (org.apache.hadoop.hbase.mapreduce.TableOutputFormat.java) HBASE 1.4.0
@Override
public void checkOutputSpecs(JobContext context) throws IOException,
    InterruptedException {

  try (Admin admin = ConnectionFactory.createConnection(getConf()).getAdmin()) {
    TableName tableName = TableName.valueOf(this.conf.get(OUTPUT_TABLE));
    if (!admin.tableExists(tableName)) {
      throw new TableNotFoundException("Can't write, table does not exist:" +
          tableName.getNameAsString());
    }

    if (!admin.isTableEnabled(tableName)) {
      throw new TableNotEnabledException("Can't write, table is not enabled: " +
          tableName.getNameAsString());
    }
  }
}
{code}
 

"ConnectionFactory.createConnection(getConf())", as mentioned above "conf" class member is not initialized, so getConf() will return null, so in the next UserProvider create instance process, it throw the NullPointException(Please part of stack trace at the end), it is a little confused that, context passed by function parameter is actually been properly constructed, and it contains Configuration object, why context is never used? So I suggest to use below code to partly fix this issue:

 
{code:java}
// code placeholder
@Override
public void checkOutputSpecs(JobContext context) throws IOException,
    InterruptedException {
  Configuration hConf = context.getConfiguration();
  if(hConf == null)
    hConf = this.conf;

  try (Admin admin = ConnectionFactory.createConnection(hConf).getAdmin()) {
    TableName tableName = TableName.valueOf(hConf.get(OUTPUT_TABLE));
    if (!admin.tableExists(tableName)) {
      throw new TableNotFoundException("Can't write, table does not exist:" +
              tableName.getNameAsString());
    }

    if (!admin.isTableEnabled(tableName)) {
      throw new TableNotEnabledException("Can't write, table is not enabled: " +
              tableName.getNameAsString());
    }
  }
}
{code}
In hbase 1.3.1, this issue is not exists because checkOutputSpecs has a blank function body

 

 

Part of stack trace:

Exception in thread "main" java.lang.NullPointerException
 at org.apache.hadoop.hbase.security.UserProvider.instantiate(UserProvider.java:122)
 at org.apache.hadoop.hbase.client.ConnectionFactory.createConnection(ConnectionFactory.java:214)
 at org.apache.hadoop.hbase.client.ConnectionFactory.createConnection(ConnectionFactory.java:119)
 at org.apache.hadoop.hbase.mapreduce.TableOutputFormat.checkOutputSpecs(TableOutputFormat.java:177)
 at org.apache.spark.internal.io.SparkHadoopMapReduceWriter$.write(SparkHadoopMapReduceWriter.scala:76)
 at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsNewAPIHadoopDataset$1.apply$mcV$sp(PairRDDFunctions.scala:1085)
 at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsNewAPIHadoopDataset$1.apply(PairRDDFunctions.scala:1085)
 at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsNewAPIHadoopDataset$1.apply(PairRDDFunctions.scala:1085)
 at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
 at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
 at org.apache.spark.rdd.RDD.withScope(RDD.scala:362)
 at org.apache.spark.rdd.PairRDDFunctions.saveAsNewAPIHadoopDataset(PairRDDFunctions.scala:1084)

 

 



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)