January 23, 2017

Elliptic Curve Keys with OpenSSL

List pre-defined curves in OpenSSL:

$ openssl ecparam -list_curves | grep prime256v1
  prime256v1: X9.62/SECG curve over a 256 bit prime field

Generate private key:

$ openssl ecparam -name prime256v1 -genkey -noout -out prime256v1.key.pem

Generate public key:

$ openssl ec -in prime256v1.key.pem -pubout -out prime256v1.pem

Reference: https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations

January 12, 2017

Jackson Standard JSON library for Java

Introduction

Jackson is build up by the following modules:

  • Streaming: "jackson-core"
  • Annotations: "jackson-annotations"
  • Databind: "jackson-databind" implements data-binding (and object serialization)

Maven

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.5</version>
</dependency>
$ mvn dependency:tree
...
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.5:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile
[INFO] |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.5:compile
...

Jackson JSON Parser and Generator

To do JSON parsing and generation you only need one class com.fasterxml.jackson.databind.ObjectMapper.

To parse a json file.

{
    "name": "volvo",
    "weight": 350,
    "active": true,
    "lastUsed": "2017-01-17",
    "properties": {
        "name A": "gold",
        "name B": "silver"
    }
}
public class Vehicle {
    private String name;
    private int weight;
    private boolean active;
    private Date lastUsed;
    private Map<String, String> properties = new HashMap<>();

    public Vehicle() {
    }

    public Vehicle(String name, int weight, boolean active, Date lastUsed, Map<String, String> properties) {
        this.name = name;
        this.weight = weight;
        this.active = active;
        this.lastUsed = lastUsed;
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "Vehicle [name=" + name + ", weight=" + weight + ", active=" + active + ", lastUsed=" + lastUsed
                + ", properties=" + properties + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public Date getLastUsed() {
        return lastUsed;
    }

    public void setLastUsed(Date lastUsed) {
        this.lastUsed = lastUsed;
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    public void setProperties(Map<String, String> properties) {
        this.properties = properties;
    }
}
ObjectMapper mapper = new ObjectMapper();

String file = JacksonTest.class.getClassLoader().getResource("Vehicle.json").getFile();
Vehicle vehicle = mapper.readValue(new File(file), Vehicle.class);
System.out.println(vehicle);

And to generate json.

Vehicle newVehicle = new Vehicle("saab", 200, true, new Date(), new HashMap<String, String>() {
    {
        put("Code A", "foo");
        put("Code B", "bar");
        put("Code C", "code");
    }
});
String json = mapper.writeValueAsString(newVehicle);
System.out.println(json);

Different ObjectMapper#readValue(...) and ObjectMapper#writeValue(...)

Different parse methods:

  • com.fasterxml.jackson.databind.ObjectMapper.readValue(File, Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(URL, Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(String, Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(Reader, Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(InputStream, Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(byte[], Class<T>)
  • com.fasterxml.jackson.databind.ObjectMapper.readValue(DataInput, Class<T>)

Different generation methods:

  • com.fasterxml.jackson.databind.ObjectMapper.writeValue(File, Object)
  • com.fasterxml.jackson.databind.ObjectMapper.writeValue(OutputStream, Object)
  • com.fasterxml.jackson.databind.ObjectMapper.writeValue(DataOutput, Object)
  • com.fasterxml.jackson.databind.ObjectMapper.writeValue(Writer, Object)
  • com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(Object)
  • com.fasterxml.jackson.databind.ObjectMapper.writeValueAsBytes(Object)

Configure ObjectMapper

mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
mapper.setSerializationInclusion(Include.NON_EMPTY);

January 6, 2017

BDD Testing with Cucumber, Java and JUnit

Introduction

BDD (Behaviour-Driven Development) is about designing code by defining your application in terms of behavior.

You start by gathering Tester, Developer and Product Owner (The Three Amigos) and define User Stories. These User Stories are given a Feature name and each Feature is broken down into a Scenario with Steps defines with the keywords: Given, When and Then

Cucumber

Now in Cucumber you write your User Stories (=Feature) in a language called Gherkin. Example:


Feature: Cash withdrawal 

Scenario: Withdrawal from an account in credit 
    Given I have deposited $100.00 in my account 
    When I withdraw $20 
    Then $20 should be dispensed 

Maven Dependency

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>${cucumber.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>${cucumber.version}</version>
    <scope>test</scope>
</dependency>

Cucumber Code Structure

All code (production code, test code and gherkin code) must be placed in the same catalog structure.

  • Production Code - src/main/java/se/magnuskkarlsson/examples/cucumber/Account.java
  • Test Code - src/test/java/se/magnuskkarlsson/examples/cucumber/AccountTest.java
  • Test Code - src/test/java/se/magnuskkarlsson/examples/cucumber/AccountSteps.java
  • Gherkin Code - src/test/resources/se/magnuskkarlsson/examples/cucumber/cash_withdrawal.feature

Cucumber Test Code

We need two classes: one JUnit wrapper class and one Cucumber class that implements the steps in your Gherkin Code.

package se.magnuskkarlsson.examples.cucumber;

import org.junit.runner.RunWith;

import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
public class AccountTest {

}
package se.magnuskkarlsson.examples.cucumber;

import static org.hamcrest.CoreMatchers.is;

import org.junit.Assert;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AccountSteps {

    Account account = new Account();

    @Given("^I have deposited \\$(\\d+) in my account$")
    public void deposit(int amount) {
        account.deposit(amount);
    }

    @When("^I withdraw \\$(\\d+)$")
    public void withdraw(int amount) {
        account.withdraw(amount);
    }

    @Then("^My balance should be \\$(\\d+)$")
    public void verifyBalance(int balance) {
        Assert.assertThat(balance, is(account.getBalance()));
    }
}

Verify

You can now either run you JUnit test class AccountTest inside your IDE or run complete test from command line as usual in maven: mvn clean install.

January 5, 2017

JDK Logger/Java Logging API

Background

Since JDK 1.4 there is a default Logging API in Java. The entire Logging API is contained in the package java.util.logging.

Reference: https://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html

Usage

import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggerTest {

    private static final Logger log = Logger.getLogger(LoggerTest.class.getName());

    public void something() throws Exception {
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Enter something()...");
        }

        log.info("Logging result");

        log.warning("Another logging result");

        log.log(Level.SEVERE, "Nullpoint here", new NullPointerException("divide by zero"));

        if (log.isLoggable(Level.FINEST)) {
            log.finest("Exit something()");
        }
    }
}

Default Logging Configuration

Java comes with a default logging configuration file, that only contains a ConsoleHandler and writes to standard error.

$JAVA_HOME/lib/logging.properties

############################################################
#       Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.  
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#       Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler 
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# Example to customize the SimpleFormatter output format 
# to print one-line log message like this:
#     <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE

Configuration

To change default configuration, create a new configuration file and add a system property java.util.logging.config.file to you java process, which point to yours configuration file. Example:

java ... -Djava.util.logging.config.file=/tmp/logging.properties ...

The available handlers/appenders and their configuration are:

# Default logging.properties $JRE_HOME/lib/logging.properties
# java -Djava.util.logging.config.file=logging.properties
handlers                                   = java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Global Logging Level.
.level                                     = INFO

# See https://docs.oracle.com/javase/8/docs/api/java/util/logging/FileHandler.html
# Do NOT limit the messages here, it's controlled by global and/or specific classes
java.util.logging.FileHandler.level        = ALL
java.util.logging.FileHandler.formatter    = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.encoding     = UTF-8
java.util.logging.FileHandler.limit        = 50000
java.util.logging.FileHandler.count        = 10
java.util.logging.FileHandler.pattern      = %h/java-%g.log
java.util.logging.FileHandler.append       = true

# See https://docs.oracle.com/javase/8/docs/api/java/util/logging/ConsoleHandler.html
# Do NOT limit the messages here, it's controlled by global and/or specific classes
java.util.logging.ConsoleHandler.level     = ALL
java.util.logging.ConsoleHandler.encoding  = UTF-8

# See https://docs.oracle.com/javase/8/docs/api/java/util/logging/StreamHandler.html
# Do NOT limit the messages here, it's controlled by global and/or specific classes
java.util.logging.StreamHandler.level      = ALL
java.util.logging.StreamHandler.encoding   = UTF-8

# See https://docs.oracle.com/javase/8/docs/api/java/util/logging/SocketHandler.html
# Do NOT limit the messages here, it's controlled by global and/or specific classes
java.util.logging.SocketHandler.level      = ALL
java.util.logging.SocketHandler.encoding   = UTF-8
java.util.logging.SocketHandler.host       =
java.util.logging.SocketHandler.port       =

# See https://docs.oracle.com/javase/8/docs/api/java/util/logging/MemoryHandler.html
# Do NOT limit the messages here, it's controlled by global and/or specific classes
java.util.logging.MemoryHandler.level      = ALL
java.util.logging.MemoryHandler.size       =
java.util.logging.MemoryHandler.push       =
java.util.logging.MemoryHandler.target     =

# Customize the SimpleFormatter output format
# See https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#syntax 
java.util.logging.SimpleFormatter.format   = %1$tF'T'%1$tT.%1$tL%1$tz [%4$s] %2$s - %5$s %6$s%n
#return String.format(format,                                    // java.util.logging.SimpleFormatter.format
#                     dat,                                       // %1$t<conversion>
#                     source,                                    // %2$s    
#                     record.getLoggerName(),                    // %3$s
#                     record.getLevel().getLocalizedLevelName(), // %4$s
#                     message,                                   // %5$s
#                     throwable);                                // %6$s

# Specific logging level for classes or packages
se.magnuskkarlsson.examples.lambda.level = FINEST

Log Levels

Java Logging API has the following levels: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL

You define a global log level with .level, then if you need specific configuration you add: <package>[.class].level=<level>

NOTE: ConsoleHandler is special, for that you need to set ConsoleHandler.level for others you don't!

Log Formatter

There exists only two formatter and you typically want to use the SimpleFormatter.

NOTE: Most handlers uses the SimpleFormatter as default, but some do not. For them you need to set the formatter configuration.

Configure java.util.logging.SimpleFormatter

The default format is quite odd, so you want to change that.

The configuration is done with java.util.logging.SimpleFormatter.format. And the value is for the java call in java.util.logging.SimpleFormatter.format(LogRecord)

return String.format(format,                                    // java.util.logging.SimpleFormatter.format
                     dat,                                       // %1$t<conversion>
                     source,                                    // %2$s    
                     record.getLoggerName(),                    // %3$s
                     record.getLevel().getLocalizedLevelName(), // %4$s
                     message,                                   // %5$s
                     throwable);                                // %6$s

To understand the java.lang.String.format(String, Object...) syntax, read https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#syntax.

Configuration in Java EE 6

Background

Dependency Injection has come strong in Java EE 6, which is widely influenced from Spring Framework.

You can use the same pattern to handle configuration.

Code

import java.util.HashMap;
import java.util.Map;

import javax.enterprise.inject.spi.InjectionPoint;

import org.apache.log4j.Logger;

@javax.ejb.Startup
@javax.ejb.Singleton
public class Configuration {

    private final Logger log = Logger.getLogger(Configuration.class);

    private final Map<String, String> configuration = new HashMap<String, String>();

    @javax.annotation.PostConstruct
    public void fetchConfiguration() {
        // load configuration from preferred place and add to map
        configuration.put("se.magnuskkarlsson.examples.lambda.FruitBoundary.noFruits", "999");
    }

    @javax.enterprise.inject.Produces
    public String getString(InjectionPoint point) {
        String fieldClass = point.getMember().getDeclaringClass().getName();
        String fieldName = point.getMember().getName();
        log.info(" >> fieldName : " + fieldClass);
        log.info(" >> fieldName Class : " + fieldName);
        String fieldKey = fieldClass + "." + fieldName;
        String fieldValue = configuration.get(fieldKey);
        log.info("Loaded " + fieldKey + "='" + fieldValue + "'");
        return fieldValue;
    }

    @javax.enterprise.inject.Produces
    public int getInteger(InjectionPoint point) {
        String stringValue = getString(point);
        if (stringValue == null) {
            return 0;
        }
        return Integer.parseInt(stringValue);
    }
}

And to use it

import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/fruit")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public class FruitBoundary {

    @Inject
    private int noFruits;

    @GET
    @Path("/{fruitId}")
    public Fruit getById(@PathParam("fruitId") long fruitId) {
        Fruit fruit = new Fruit();
        fruit.setId(fruitId);
        fruit.setName("Apple " + noFruits);
        fruit.setWeight(35);
        return fruit;
    }
}

And finally you need to add and empty WEB-INF/beans.xml to your achieve to make CDI work.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

</beans>