Category: Code Demo

AsyncHbase Client Code Demo

Although Hbase has intrinsic non async client API, an async client API derived from OpenTSDB OpenTSDB/asynchbase outperforms the former.
In this blog, we demonstrate its basic put and scan async API which return Deferred object, the equivalent one to Java 8 CompletableFuture.  The code demo does the following 3 operations in sequential order.

  1. Verify specified table and column family of a hbase cluster
  2. Puts several number of records asynchronously
  3. After put operations succeed, perform a total scan
    public static Deferred putData() throws Exception {
        String rowKey = UUID.randomUUID().toString();
        String data = "value " + counter.incrementAndGet();
        PutRequest putRequest = new PutRequest(tableName.getBytes(),
                rowKey.getBytes(), columnFamily.getBytes(),
                qualifier.getBytes(),
                data.getBytes());
        return hBaseClient.put(putRequest).addCallbacks(
                arg -> {
                    System.out.println("put data: rowkey=" + rowKey + ", value=" + data);
                    return null;
                },
                new Callback<Object, Exception>() {
            @Override
            public Object call(Exception arg) throws Exception {
                arg.printStackTrace();
                return null;
            }
        });

    }

To coordinate the order of verify phase and put phase, CountDownLatch is used whereas Deferred.group for put and scan coordination.

        List<Deferred<Object>> putDeferredList = new ArrayList<>();
        int total = 100;
        for (int i = 0; i < total; i++) {
            putDeferredList.add(putData());
        }
        Deferred.group(putDeferredList).addCallback(
                cb -> {
                    System.out.println("All put finished");
                    startProcessScan();
                    return null;
                }
        );

The maven project is downloadable @ hbaseasyncclientdemo.

Screen snapshot of the code in ME-Mydoc
code_asynchbase

Java RSA encrypt and decrypt using generated key pair

The code demo generates RSA key pair and persists it to local file using Java specific object serialization format. The demo then restores private/public key objects by de-serializing from files it just created. Further, the public key is used to encrypt a clear text and the private key to decrypt.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import sun.security.tools.keytool.CertAndKeyGen;

/**
 * RSA encryption/decryption util.
 *
 */
public class RSAUtil {

    private RSAPublicKey pubkey;
    private RSAPrivateKey prikey;

    public RSAUtil(RSAPrivateKey prikey, RSAPublicKey pubkey) {
        this.prikey = prikey;
        this.pubkey = pubkey;
    }

    public byte[] encrypt(byte[] bytes) throws BadPaddingException, IllegalBlockSizeException,
            InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubkey);
        return cipher.doFinal(bytes);
    }

    public byte[] decrypt(byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, prikey);
        return cipher.doFinal(bytes);
    }

    public static RSAUtil loadKeys(String privateKeyFile, String publicKeyFile) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(privateKeyFile));
        RSAPrivateKey privateKey = (RSAPrivateKey) ois.readObject();

        ois = new ObjectInputStream(new FileInputStream(publicKeyFile));
        RSAPublicKey publicKey = (RSAPublicKey) ois.readObject();
        return new RSAUtil(privateKey, publicKey);
    }

    public static void genRSAKeyPair(String privateKeyFile, String publicKeyFile) {
        try {
            CertAndKeyGen keyPair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);

            keyPair.generate(1024);
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivateKey();

            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublicKey();

            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(privateKeyFile));
            oos.writeObject(privateKey);
            oos.flush();
            oos.close();

            oos = new ObjectOutputStream(new FileOutputStream(publicKeyFile));
            oos.writeObject(publicKey);
            oos.flush();
            oos.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        String clearText = "this is the text";
        genRSAKeyPair("privatekey", "publickey");
        RSAUtil rsaUtil = loadKeys("privatekey", "publickey");
        byte[] encryptedBytes = rsaUtil.encrypt(clearText.getBytes(StandardCharsets.UTF_8));
        String decryptedText = new String(rsaUtil.decrypt(encryptedBytes), StandardCharsets.UTF_8);
        System.out.println(decryptedText.equals(clearText));
    }
}

Java symmetric encryption decryption demo

In symmetric cryptograph, there are padding mode and blocking cipher that have restrictions on input byte length. SymmetricCryptoUtil in this demo adopts AES/CFB8/NoPadding mode that accepts any input without byte length restriction. In the Java main method, a string is first encrypted as byte array and then decrypted to string again without any loss.

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * Symmetric key encryption/decryption util.
 *
 */
public class SymmetricCryptoUtil {

    private String secretKey = "18345678800knarf";
    private String iv = "S23r87I090qYer9z";
    private static final String CIPHER_MODE = "AES/CFB8/NoPadding";

    private SecretKey keySpec;
    private IvParameterSpec ivSpec;

    public SymmetricCryptoUtil() {
        try {
            keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
            ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public byte[] encrypt(byte[] bytes) throws BadPaddingException, IllegalBlockSizeException,
            InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(CIPHER_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        return cipher.doFinal(bytes);
    }

    public byte[] decrypt(byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(CIPHER_MODE);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return cipher.doFinal(bytes);
    }

    public static void main(String[] args) throws Exception {
        String clearText = "this is the text";
        SymmetricCryptoUtil cryptoUtil = new SymmetricCryptoUtil();
        byte[] encryptedBytes = cryptoUtil.encrypt(clearText.getBytes(StandardCharsets.UTF_8));
        String decryptedText = new String(cryptoUtil.decrypt(encryptedBytes), StandardCharsets.UTF_8);
        System.out.println(decryptedText.equals(clearText));
    }
}

Spring boot project with bean loading info

Download source code spring-boot-debug.zip

The spring boot demo project is taken from spring boot guide. We can build the project with either gradle or maven.
gradle build
mvn package
In addition to the spring boot project in its official tutorial, I configured debug info because sometimes, we are confused about bean loading status, such as what beans are loaded and in what sequence. We can pass debug level info in command line such as

java -jar build/libs/gs-spring-boot-0.1.0.jar --debug
or having a application.properties file with following content

debug=true  # When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate and Spring) are configured to output more information. Enabling the debug mode does not configure your application log all messages with DEBUG level.
logging.level.root=DEBUG  # more comprehensive debug level

Reference @ Spring boot logging.

Bean loading report and log are partly extracted as follows

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------------

AuditAutoConfiguration.AuditEventRepositoryConfiguration matched
- @ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.AuditEventRepository; SearchStrategy: all) found no beans (OnBeanCondition)

DispatcherServletAutoConfiguration matched
- @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition)
- found web application StandardServletEnvironment (OnWebApplicationCondition)

DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched
- @ConditionalOnClass classes found: javax.servlet.ServletRegistration (OnClassCondition)
- no ServletRegistrationBean found (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
2016-02-18 20:43:52.124  INFO 9431 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2016-02-18 20:43:52.127 DEBUG 9431 --- [           main] o.s.b.a.e.jmx.EndpointMBeanExporter      : Located managed bean 'requestMappingEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=requestMappingEndpoint]
2016-02-18 20:43:52.189 DEBUG 9431 --- [           main] o.s.b.a.e.jmx.EndpointMBeanExporter      : Located managed bean 'environmentEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=environmentEndpoint]
2016-02-18 20:43:52.201 DEBUG 9431 --- [           main] o.s.b.a.e.jmx.EndpointMBeanExporter      : Located managed bean 'healthEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=healthEndpoint]

Powered by WordPress & Theme by Anders Norén