Blog do projektu Open Source JavaHotel

piątek, 7 sierpnia 2020

HDP 3.1, HBase Phoenix and IBM Java

 I spent several sleepless nights trying to sort a nasty problem. While connecting to HBase Phoenix, the Phoenix client was stalled before displaying the prompt.
Setting property: [incremental, false]
Setting property: [isolation, TRANSACTION_READ_COMMITTED]
issuing: !connect jdbc:phoenix: none none org.apache.phoenix.jdbc.PhoenixDriver
Connecting to jdbc:phoenix:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/hdp/!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/hdp/!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See for an explanation.
20/08/07 11:28:08 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

What's more, there was no single error message, neither from the client nor in the HBase log file, Master or Region Servers. Simply nothing, no clue. Besides that, everything was healthy and running soundly.

The first step toward the solution was to enable tracing in Phoenix client. This setting is not managed by Ambari and requires manual modification.

vi /usr/hdp/

After TRACING was enabled, the sqlline client was more talkative and provided the first clue. INFO client.RpcRetryingCallerImpl: Call exception, tries=6, retries=36, started=4724 ms ago, cancelled=false, msg=Call to failed on local exception: Failure to initialize security context [Caused by org.ietf.jgss.GSSException, major code: 13, minor code: 0
major string: Invalid credentials
minor string: SubjectCredFinder: no JAAS Subject], details=row 'SYSTEM:CATALOG' on table 'hbase:meta' at region=hbase:meta,,1.1588230740,,16020,1596794212924, seqNum=-1
The HDP cluster was Kerberized and the problem seemed to be related to Kerberos authentication. Kerberos is the source of many problems but everything except this worked smoothly here.
Finally, I found the hint under this link. The culprit was IBM Java. The cluster is running under control of  OpenJDK Java but the sqlline client is using default host Java. update-alternatives --config java

There are 3 programs which provide 'java'.

Selection Command
*+ 1 /usr/lib/jvm/java-1.8.0-ibm-
2 /usr/jdk64/java-1.8.0-openjdk-
3 /usr/java/jdk1.8.0_202-amd64/jre/bin/java

So the solution was extremely simple, just switch to OpenJDK Java and Phoenix client works like a dream.

piątek, 31 lipca 2020

DB2 ODBC FDW PostgreSQL extension

I reinvigorated my Postgresql DB2 wrapper. Now it works also with PostgreSQL 11 and 12. The source code and installation instruction are available here.

It took me some time to accomplish it. The PostgreSQL failed because of memory violation related problem after returning from GetForeignPaths function. The crashed happened inside the server code. What's more, it worked after recompiling the server directly from source code so nailing down the problem was impossible. Finally, the solution was to migrate the db2odbc_fdw.c to pure C code and get rid of all warnings. Probably the reason for the failure was a discrepancy between data types in C function signature and launching sequence.

wtorek, 30 czerwca 2020

My TPC/DS, new features


I uploaded a new version of mytpcds, a wrapper around TPC/DS benchmark allowing easy and quick roll-out of TPC/DS test against leading RDMS including Hadoop SQL engines. Just deploy, configure using a template provided and run. In the new version, the implementation of Query Validation Test is added.

Query Validation Test

Query Validation Test verifies the accuracy of SQL engine. RDBMS is to run a sequence of SQL statements, called Validation Queries, on Qualification database and compare the result data set against the expected data set. During Validation Test, the queries should come back with the same result. The Validation Queries are standard TPC/DS queries templates having where query parameters are substituted by predefined constants.
The substitution values for Validation Queries are defined in "TPC-DS Specification" manual, chapter "Appendix B: Business Questions". It is a mundane and error-prone task to prepare Validation Queries manually in 99 queries templates and I wanted also to avoid having two different versions of TPC/DS queries. So I decided to make the process automatic. Firstly I extracted all parameters and substitution values into separate configuration files. The name convention is <n>.par. The <n> maps to appropriate TPC/DS query. For instance, 1.par contains substitution values for query1.tpl.
The launcher contains a separate task: ./ queryqualification. This task replaces all parameters placeholder with the corresponding validation values and put them in <TPC/DS root dir>/work/{dbtype}queries directory ready to be picked up by other tasks.
TPC/DS package comes with expected data sets for Query Validation. It is included in <TPC/DS root>/answer_sets. Unfortunately, the format of answer sets is not consistent which makes impossible the automated verification. So I prepared my own version of answer sets using DB2 output. Unfortunately, it does not comply with output from other RDBMS including Hive, so it is still a pending task which output is invalid.


Query Validation Test requires comparing the current result sets against a reference result set. Unfortunately, the output from different RDBS using the command line client varies significantly which make automated comparison impossible. So I decided to prepare my own Java QueryRunner using JDBC and have the full control of how the result is produced. The target jar is produced by mvn package command. The only prerequisite for every database is JDBC driver jar. So far, I tested the QueryRunner for: NPS/Netezza, DB2, IBM BigSql, SqlServer and Hadoop Hive.

QueryRunner, Hive and Kerberos

Because life is never an easy road free of stones, the real challenge was to execute QueryRunner for Hadoop/Hive in Kerberized environment. The parameters regarding Kerberos cannot be included in URL connection string. Before executing DriverManager.getConnection(url, user, password);  the client should authenticate in Hadoop cluster using Hadoop related libraries. Of course, I wanted to avoid keeping two versions of QueryRunner and have the development consistent. So I developed a separate package HadoopAuth and in Hadoop/Hive environment, the Hadoop Kerberos authentication is done using HadoopAuth package but through Java reflection feature. This way I was able to keep QueryRunner clean. How to configure QueryRunner for Hadoop/Hive is described here.

Next steps

  • Further analysis of reference QueryValidation answer tests.
  • Add Microsoft SqlServer to RDBMS supported by myTPC-DS.
  • Enable QueryRunner for all RDBMS supported.

niedziela, 31 maja 2020

Simple RestService library continued


I enhanced my Simple RestService library to a little more complex but still simple.
The full source code is here
The sample application depending on it is here.
The principle behind this project is to set up a RestAPI server based on Java only without any additional dependencies. I added two features: SSL and Kerberos authentication.


Java source code: here
Allows to set up HTTPS RestService. The certificate can be self-signed or CA signed. Client certificate authentication is not supported.


Java Source code: here
Allows Kerberos authentication. Tested with AD and MIT KDC. Only authentication is implemented, no DoAs action.

czwartek, 30 kwietnia 2020

My private CA Center

Certificates, self-signed certificates, certificates signed by Certificate Authority, sounds complicated. But the devil is not so black as he's painted. It is easy to create a self-signed certificate but sometimes one needs to have a CA-signed certificate without paying fees. So be the authority for yourselves. I found a very good article on how to create private CA using open-source tools. But following the procedure manually is not a good method of spending your free time, so I created a solution which automates it all.
The solution and description are available here. The solution comes with three components.
  • Bash script  Script automates procedure described in the article. Creates a new Certificate Authority containing root and intermediate certificates. Also produces a certificate signed by the CA using CSR (Certificate Signing Request) or by providing all necessary data including CN.
  • Java server Rest/API. Assuming CA is created, the Java server generates signed certificate through Rest/API.
  • Docker script. The CA centre is created during Docker image creation and the container exposes Rest/API for certificate signing.

poniedziałek, 23 marca 2020

HDP 3.1.5, OpenJDK, Infra Solr and AD/Kerberos

I spent several sleepless nights caused by very nasty problem coming up after HDP 3.1.5 Kerberization. The Infra Solr components could not start just blocking the whole cluster. The message in the Ambari Console was saying.
Skip /infra-solr/configs and /infra-solr/collections
Set world:anyone to 'cr' on  /infra-solr/configs and /infra-solr/collections
KeeperErrorCode = NoAuth for /infra-solr/configs
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /infra-solr/configs
 at org.apache.zookeeper.KeeperException.create(
 at org.apache.zookeeper.KeeperException.create(
 at org.apache.zookeeper.ZooKeeper.setACL(

It looked that infra-solr user could not update the ZooKeeper /infra-solr znode because of not sufficient privileges. But the ACL privileges looked correct.
[zk: localhost:2181(CONNECTED) 0] getAcl /infra-solr
: cdrwa
: r
[zk: localhost:2181(CONNECTED) 1]

After closer examination, I discovered strange stuff in ZooKeeper log. 2020-03-23 01:33:12,260 - INFO [NIOServerCxn.Factory:] - Successfully authenticated client: authenticationID=$6O1000-3NO0GILCOJUA@FYRE.NET; authorizationID=infra-solr/
2020-03-23 01:33:12,261 - INFO [NIOServerCxn.Factory:] - Setting authorizedID: $6O1000-3NO0GILCOJUA
2020-03-23 01:33:12,261 - INFO [NIOServerCxn.Factory:] - adding SASL authorization for authorizationID: $6O1000-3NO0GILCOJUA
2020-03-23 01:33:24,011 - WARN [NIOServerCxn.Factory:] - caught end of stream exception
EndOfStreamException: Unable to read additional data from client sessionid 0x17104ad52230007, likely client has closed socket
So it seemed that Zookeeper to apply authorization rights was using not AD principal name (infra-solr) but sAMAccountName attribute of infra-solr AD principal ($6O1000-3NO0GILCOJUA). Ambari Kerberos Wizard is filling this attribute with random data only to keep it unique.
The problem is described here, it is the bug coming with 1.8.0_242 version of OpenJDK.
The only workaround is to downgrade the OpenJDK to 232 level or switch to Oracle JDK.
yum downgrade java*

java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)

And last but not least.
Block the Java upgrade unless the bug is fixed.
vi /etc/yum.conf


sobota, 29 lutego 2020

Simple RestService library

REST API is the mean of choice to communicate between different loosely coupled applications. There are plenty of REST API implementations but I was looking for a solution as simple as possible with minimal external dependencies or prerequisites. Finally, I ended up with the compact library utilizing existing in Java JDK HttpServer.
Intellij IDEA project, source code and javadoc.
Sample project utilizing the RestService project.
Another project having RestService dependency.
  • Very lightweight, no external dependency, just Java JDK.
  • Can be dockerized, sample Dockerfile.
  • Adds-on making a life of developer easier.
    • Validating and extracting URL query parameters including type control.
    • Upload data
    • CORS relaxation
    • Sending data with valid HTTP response code.
  • "Dynamic" and "static" REST API call. "Dynamic" means that specification of particular REST API endpoint can be defined after the request reached the server but before handling the request thus allowing providing different custom logic according to the URL path.
The service class should extend RestHelper.RestServiceHelper abstract class and implements two methods:
  • getParams : delivers REST API call specification (look below) including URL query parameter definition. The method is called after the REST API request accepted by HTTP Server but before validating and running the call. 
  • servicehandle: custom logic to serve the particular REST API endpoint. The method should conclude handling the request by proper "produceresponse" call. The "servicehandle" can take a URL query parameters and utilize several helper methods.
REST API specification
The REST API endpoint specification is defined through RestParams class. The specification consists of:
  • HTTP request method: GET, POST, PUT etc
  • List of allowed  URL query parameters. Three parameters type are supported: BOOLEAN, INT and STRING (meaning any other).
  • CORS should be relaxed for this particular endpoint.
  • Response type content (TEXT, JSON or not specified), Content-Type.
  • List of methods allowed in the response header, Access-Control-Allow-Methods.
The main class should extend RestStart abstract class.