Kohei Nozaki's blog 

java.util.logging: Programmatic configuration and logging with Java8 lambdas


Posted on Monday Mar 30, 2015 at 06:24PM in Technology


Configuration

We can put configurations in following places (ordered by priority):

  1. java.util.logging.config.class system property. specify FQCN of a class here

  2. java.util.logging.config.file system property. specify the path to a property file here

  3. $JAVA_HOME/lib/logging.properties file. put JRE-wide configuration here

Use of java.util.logging.config.class is most flexible. in that way we can simply put a config class under src/test/java for unit tests. we need to put configuration procedures in the default constructor. an implementation would be something like following:

package testutil;

import java.util.logging.*;

public class LoggingConfig {
    public LoggingConfig() {
        try {
            // Load a properties file from class path that way can't be achieved with java.util.logging.config.file
            /*
            final LogManager logManager = LogManager.getLogManager();
            try (final InputStream is = getClass().getResourceAsStream("/logging.properties")) {
                logManager.readConfiguration(is);
            }
            */

            // Programmatic configuration
            System.setProperty("java.util.logging.SimpleFormatter.format",
                    "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] (%2$s) %5$s %6$s%n");

            final ConsoleHandler consoleHandler = new ConsoleHandler();
            consoleHandler.setLevel(Level.FINEST);
            consoleHandler.setFormatter(new SimpleFormatter());

            final Logger app = Logger.getLogger("app");
            app.setLevel(Level.FINEST);
            app.addHandler(consoleHandler);
        } catch (Exception e) {
            // The runtime won't show stack traces if the exception is thrown
            e.printStackTrace();
        }
    }
}

If you prefer configuration in a property file rather than a config class, following will work as the same to config class:

handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] (%2$s) %5$s %6$s%n

java.util.logging.ConsoleHandler.level=FINEST
app.level=FINEST

To set system property for every test execution, put following plugin definition to your pom.xml. note that IntelliJ IDEA respects this configuration in its test execution.

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18.1</version>
    <configuration>
        <systemPropertyVariables>
            <java.util.logging.config.class>
                testutil.LoggingConfig
            </java.util.logging.config.class>

            <!-- If you prefer a file this will work too -->
            <!--<java.util.logging.config.file>-->
                <!--src/test/resources/logging.properties-->
            <!--</java.util.logging.config.file>-->
        </systemPropertyVariables>
    </configuration>
</plugin>

Logging examples

Application class:

public class MyClass {
    private static final Logger log = Logger.getLogger(MyClass.class.getName());
    public String hello(String greetings, String name) {
        // entering will be logged as FINER
        log.entering(MyClass.class.getName(), "hello", new Object[]{greetings, name});

        // lambdas
        log.finest(() -> "finest: " + LocalDateTime.now());
        log.finer(() -> "finer: " + LocalDateTime.now());
        log.fine(() -> "fine: " + LocalDateTime.now());
        log.info(() -> "info: " + LocalDateTime.now());
        log.warning(() -> "warning: " + LocalDateTime.now());
        log.severe(() -> "severe: " + LocalDateTime.now());

        // exception logging

        // throwing will be logged as FINER
        log.throwing(MyClass.class.getName(), "hello", new Exception("test"));

        // exception + message logging with lambda
        log.log(Level.FINEST, new Exception("test"), () -> String.format("arg=%s", name));

        // exception + parameter logging with LogRecord
        final LogRecord record = new LogRecord(Level.FINEST, "arg={0}");
        record.setThrown(new Exception("test"));
        record.setLoggerName(log.getName()); // logger name will be null unless this
        record.setParameters(new Object[]{name});
        log.log(record);

        final String rc = greetings + ", " + name;

        // exiting will be logged as FINER
        log.exiting(MyClass.class.getName(), "hello", rc);
        return rc;
    }
}

Test:

public class MyClassTest {
    @org.junit.Test
    public void testHello() throws Exception {
        MyClass sut = new MyClass();
        Assert.assertEquals("Hello, Kyle", sut.hello("Hello", "Kyle"));
    }
}

Output:

2015-03-30 18:01:19.362 FINER   [app.MyClass] (app.MyClass hello) ENTRY Hello Kyle
2015-03-30 18:01:19.425 FINEST  [app.MyClass] (app.MyClass hello) finest: 2015-03-30T18:01:19.425
2015-03-30 18:01:19.427 FINER   [app.MyClass] (app.MyClass hello) finer: 2015-03-30T18:01:19.427
2015-03-30 18:01:19.428 FINE    [app.MyClass] (app.MyClass hello) fine: 2015-03-30T18:01:19.428
2015-03-30 18:01:19.429 INFO    [app.MyClass] (app.MyClass hello) info: 2015-03-30T18:01:19.429
2015-03-30 18:01:19.431 WARNING [app.MyClass] (app.MyClass hello) warning: 2015-03-30T18:01:19.430
2015-03-30 18:01:19.433 SEVERE  [app.MyClass] (app.MyClass hello) severe: 2015-03-30T18:01:19.433
2015-03-30 18:01:19.434 FINER   [app.MyClass] (app.MyClass hello) THROW
java.lang.Exception: test
	at app.MyClass.hello(MyClass.java:27)
	at app.MyClassTest.testHello(MyClassTest.java:10)
...

2015-03-30 18:01:19.439 FINEST  [app.MyClass] (app.MyClass hello) arg=Kyle
java.lang.Exception: test
	at app.MyClass.hello(MyClass.java:30)
	at app.MyClassTest.testHello(MyClassTest.java:10)
...

2015-03-30 18:01:19.442 FINEST  [app.MyClass] (app.MyClass hello) arg=Kyle
java.lang.Exception: test
	at app.MyClass.hello(MyClass.java:34)
	at app.MyClassTest.testHello(MyClassTest.java:10)
...

2015-03-30 18:01:19.447 FINER   [app.MyClass] (app.MyClass hello) RETURN Hello, Kyle


Lean example of integration test Maven project for WildFly


Posted on Monday Feb 23, 2015 at 11:20PM in Technology


I created similar example before, but it was redundant. I created more lean version so leave here with some notes. check my GitHub repository for details.

The project contains AppServer class, which extends ExternalResource so it can be used with @Rule annotation of JUnit as follows. note that mavenit is the name of WAR file to be tested.

public class HelloImplIT {

    @ClassRule
    public static AppServer appServer = new AppServer();
    private static Hello sut;

    @BeforeClass
    public static void beforeClass() {
        sut = appServer.lookup("mavenit", HelloImpl.class, Hello.class);
    }

    @Test
    public void test() {
        Assert.assertEquals("Hello world!", sut.hello());
    }
}

The project is easy to use with both of IDE and standalone. to run IT classes with IDE, you need to launch the application server, deploy the project as WAR package, then run a IT class from IDE. if you launched the server at not 8080 port, specify the port in app-server.port system property.

To run IT classes in standalone Maven, use following command. it automatically launches WildFly instance with port offset of 30000, deploy the WAR file, running IT classes, undeploy the WAR and stops WildFly. the command is intended to use from a Jenkins job.

mvn verify -Pintegration-test-with-wildfly \
 -Djava.home=/Library/Java/JavaVirtualMachines/jdk8/Contents/Home/jre \
 -Djboss-as.home=/Users/kyle/servers/wildfly-8.2.0.Final \
 -Dwildfly.port=39990 \
 -Dapp-server.port=38080 \
 -Dwildfly.jvmArgs="-Djboss.server.base.dir=/Users/kyle/servers/wildfly-8.2.0.Final/standalone-mavenit -Djboss.socket.binding.port-offset=30000 -ea"

You can configure following parameters through command line argument:

  • JAVA_HOME-Djava.home

  • WildFly distribution ⇒ -Djboss-as.home

  • jboss.server.base.dir ⇒ inside -Dwildfly.jvmArgs

  • Port offset ⇒ -Djboss.socket.binding.port-offset inside -Dwildfly.jvmArgs. you need to set -Dwildfly.port and -Dapp-server.port accordingly.


Switching EJB remote interface to local interface accordingly to environment


Posted on Monday Feb 23, 2015 at 01:33PM in Technology


Sometimes I need to create both of remote and local interface for EJBs. most of cases that were for integration testing. usually I used this way but that way still has some disadvantages as follows:

  • Annoying creation of both of interface (local and remote) is needed for all of each EJBs

  • Remote interface is redundant for most cases in production environment

To overcome these issues, I moved declarations of EJB from annotation to ejb-jar.xml. XML files are easy to be filtered with build tools such as Maven plugins. consider following case:

Business interface

public interface MyBean {
    String hello();
}

Implementation

public class MyBeanImpl implements MyBean {
    @Override
    public String hello() {
        return "Hello";
    }
}

Injection point

@WebServlet(name = "MyServlet", urlPatterns = "/")
public class MyServlet extends HttpServlet {
    @EJB
    MyBean myBean;
...
}

Test class

public class MyBeanIT {
    static Context ctx;
    static MyBean myBean;

    @BeforeClass
    public static void before() throws Exception {
        Properties props = new Properties();
        // ... put application server specific configuration here ...
        ctx = new InitialContext(props);
        myBean = (MyBean) ctx.lookup("ejb:/ejbxmltest//MyBeanImpl!org.nailedtothex.ejbxmltest.MyBean");
    }

    @AfterClass
    public static void after() throws Exception {
        ctx.close();
    }

    @Test
    public void test() throws Exception {
        org.junit.Assert.assertEquals("Hello", myBean.hello());
    }
}

ejb-jar.xml

<ejb-jar 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/ejb-jar_3_1.xsd"
         version="3.1">
    <enterprise-beans>
        <session>
            <ejb-name>MyBeanImpl</ejb-name>

            <!-- Will be replaced by business-local with replacer-plugin for production -->
            <business-remote>org.nailedtothex.ejbxmltest.MyBean</business-remote>

            <ejb-class>org.nailedtothex.ejbxmltest.MyBeanImpl</ejb-class>
            <session-type>Stateless</session-type>
        </session>
    </enterprise-beans>
</ejb-jar>

Remote interface and bean definition are presented in ejb-jar.xml instead of annotations. that definition will be used by IDE as default. EJBs will be deployed with a remote interface to the application server in development environment so we can test the bean through remote interface. a trick is in a profile named business-local in pom.xml which intended to use for production environment:

<profile>
	<id>business-local</id>
	<build>
		<!-- Following plugin definitions will be ignored by IDEA -->
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<warSourceExcludes>WEB-INF/ejb-jar.xml</warSourceExcludes>
				</configuration>
			</plugin>
			<plugin>
				<groupId>com.google.code.maven-replacer-plugin</groupId>
				<artifactId>replacer</artifactId>
				<version>1.5.3</version>
				<executions>
					<execution>
						<phase>prepare-package</phase>
						<goals>
							<goal>replace</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<file>src/main/webapp/WEB-INF/ejb-jar.xml</file>
					<outputFile>target/${project.artifactId}/WEB-INF/ejb-jar.xml</outputFile>
					<token><![CDATA[(?<=</?)business-remote(?=>)]]></token>
					<value>business-local</value>
				</configuration>
			</plugin>
		</plugins>
	</build>
</profile>

maven-replacer-plugin replaces all of business-remote elements by business-local and put it into WEB-INF directory in the target directory, and tell maven-war-plugin to stop copying original WEB-INF/ejb-jar.xml so all of remote interfaces will be local interfaces in production environment. it is disabled by default and you have to enable it with invoke Maven with -P business-local argument. as to injection point (MyServlet) we don’t need to make any modification. @EJB or @Inject will work nevertheless whether the interface is local or remote.

Actually I really want to use Arquillian instead of remote EJB but unfortunately it doesn’t have some flexibility on my use case such as control of deployment timing at the present time.

The project used in test is available in my GitHub repository. the test was done with WildFly 8.2.0.Final.

CAUTION: invoking EJBs via local interface will call by reference but invoking via remote interface will call by value. you will get serious problems that different behavior between invoking local and remote interfaces. consider keep using remote interface on production (with accepting some performance degradation) or using modern testing framework such as Arquillian if necessary.


Using DatabaseConfiguration of Commons Configuration


Posted on Sunday Feb 22, 2015 at 10:50PM in Technology


Commons Configuration is a very useful library which manages configurations of an application. it supported various data stores including RDBMS. I’ve done some test against RDBMS so leave this posting as a note. test was done against Commons Configuration 1.10. the project which used in test is can be obtained from my GitHub repository.

app_config Table

Assume now we have following data in a table named app_config.

Table 1. app_config Table
name value

anyJob.someProp1

abc

anyJob.someProp2

def

someJob.list

1,2,3,4,5

someJob.someProp

${anyJob.someProp1}

Create Configuration instance

First, we need to create a DatabaseConfiguration instance with following procedure:

Configuration config = new DatabaseConfiguration(dataSource, "app_config", "name", "value");

Obtain all of configuration

We can obtain all of configurations as follows:

// Obtain all of keys
for (Iterator<String> keys = config.getKeys(); keys.hasNext(); ) {
	String key = keys.next();
	Object value = config.getProperty(key);
	System.out.println(key + "=" + value);
}

It produces:

anyJob.someProp1=abc
anyJob.someProp2=gef
someJob.list=[1, 2, 3, 4, 5]
someJob.someProp=${anyJob.someProp1}

Obtain keys with particular prefix

Sometimes we’d like to filter using prefixes. this time we get keys prefixed with someJob.

// Obtain keys with particular prefix
for (Iterator<String> keys = config.getKeys("someJob"); keys.hasNext(); ) {
	String key = keys.next();
	Object value = config.getProperty(key);
	System.out.println(key + "=" + value);
}

It produces:

someJob.list=[1, 2, 3, 4, 5]
someJob.someProp=${anyJob.someProp1}

Obtain list

We can obtain comma-separated values as List as follows:

// Obtain list
System.out.println(config.getList("someJob.list")); // [1, 2, 3, 4, 5]
System.out.println(config.getString("someJob.list")); // 1

It produces:

[1, 2, 3, 4, 5]
1

Note that invocation of getString() returns only the first value.

Obtain referencing value

The value ${anyJob.someProp1} in the key someJob.someProp resolved as abc with getString() method as follows:

// Referencing a value of other key
System.out.println(config.getString("someJob.someProp")); // abc

It produces:

abc

Update

The library reflects a update of database immediately even after instantiation of DatabaseConfiguration. consider following procedure was executed after instantiation of the configuration instance.

// update value of a row
try (Connection cn = dataSource.getConnection()) {
	try (Statement st = cn.createStatement()) {
		st.executeUpdate("update app_config set value='hij' where name='anyJob.someProp1'");
	}
}

// check updated value
System.out.println(config.getString("anyJob.someProp1")); // hij
System.out.println(config.getString("someJob.someProp")); // hij

It produces:

hij
hij


Using JSL Inheritance with JBeret


Posted on Sunday Feb 22, 2015 at 06:28PM in Technology


In practical use, many boilerplate code will appear to Job definition XMLs of JSR352 batch such as definition of Listeners, Properties and attribute such as item-count of chunk element. to overcome this, there is the specification of JSL Inheritance but it deferred to next version of JBatch spec but JBeret supports this specification already. it’s very useful to eliminate annoying fragments appear repeatedly so I tested it. WildFly 8.2.0.Final was used for test.

Parent XML

Parent XML begins as follows:

<?xml version="1.0" encoding="UTF-8"?>
<job id="parent" abstract="true" version="1.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee">

    <properties>
        <property name="someJobProp" value="someJobPropValue"/>
    </properties>

    <listeners>
        <listener ref="myJobListener"/>
    </listeners>

Declared property named someJobProp become visible from child XMLs. myJobListener will be included implicitly in child XMLs as well.

Parent XML has an abstract step element which will be referenced from child XMLs as follows. these properties and listeners for a step will be included implicitly too. we can override javax.transaction.global.timeout at there. it will be affected to all of child steps.

    <step id="mySimpleStep" abstract="true">
        <properties>
            <property name="javax.transaction.global.timeout" value="1800"/>
        </properties>
        <listeners>
            <listener ref="myStepListener"/>
        </listeners>
    </step>

It is the same for chunk based step. it can be used to eliminate defining item-count for all of chunk steps.

    <step id="myChunkStep" abstract="true">
        <properties>
            <property name="javax.transaction.global.timeout" value="900"/>
            <property name="jberet.local-tx" value="true"/>
        </properties>
        <listeners>
            <listener ref="myStepListener"/>
            <listener ref="myChunkListener"/>
        </listeners>
        <chunk item-count="3"/>
    </step>

</job>

Child XML

Child XML became very simple thanks to inheritance as follows. you need to specify parent and jsl-name attributes to reference its parent. parent means the name of parent attribute. jsl-name means XML file name of referencing element.

<?xml version="1.0" encoding="UTF-8"?>
<job id="child" parent="parent" jsl-name="parent" version="1.0" xmlns="http://xmlns.jcp.org/xml/ns/javaee">

    <step id="simpleStep" next="chunkStep" parent="mySimpleStep" jsl-name="parent">
        <batchlet ref="myBatchlet"/>
    </step>

    <step id="chunkStep" parent="myChunkStep" jsl-name="parent">
        <chunk>
            <reader ref="myItemReader"/>
            <writer ref="myItemWriter"/>
        </chunk>
    </step>

</job>

Launching example job

  1. Clone the repository

  2. Build the WAR and deploy it to your WildFly

  3. Run a JUnit test class named JobTest. it invokes the job through remote EJB invocation.

Log

You can see Properties, Listeners and item-count attribute were inherited as expected.

(Batch Thread - 1) Job child starting
(Batch Thread - 1) Job child, Step simpleStep starting
(Batch Thread - 1) hello world!
(Batch Thread - 1) jobProps: {someJobProp=someJobPropValue}
(Batch Thread - 1) stepProps: {javax.transaction.global.timeout=1800}
(Batch Thread - 1) Job child, Step simpleStep done
(Batch Thread - 1) Job child, Step chunkStep starting
(Batch Thread - 1) jobProps: {someJobProp=someJobPropValue}
(Batch Thread - 1) stepProps: {jberet.local-tx=true, javax.transaction.global.timeout=900}
(Batch Thread - 1) Job child, Step chunkStep chunk starting
(Batch Thread - 1) write: [1, 2, 3]
(Batch Thread - 1) Job child, Step chunkStep chunk done
(Batch Thread - 1) Job child, Step chunkStep chunk starting
(Batch Thread - 1) write: [4, 5, 6]
(Batch Thread - 1) Job child, Step chunkStep chunk done
(Batch Thread - 1) Job child, Step chunkStep chunk starting
(Batch Thread - 1) write: [7, 8, 9]
(Batch Thread - 1) Job child, Step chunkStep chunk done
(Batch Thread - 1) Job child, Step chunkStep chunk starting
(Batch Thread - 1) write: [0]
(Batch Thread - 1) Job child, Step chunkStep chunk done
(Batch Thread - 1) Job child, Step chunkStep done
(Batch Thread - 1) Job child done