Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, January 30, 2020

The Modular Monolith

Having been a micro-services sceptic from the start, and a proponent of the Monolith First approach, I've found Kamil Grzybek's Modular Monolith article series quite insightful:

Starting with a well designed and internally modularised monolith does seem to be the way to go. When architectural drivers change, like different modules evolving at different rates, it comes natural to split up the monolith into a few modules that are life-cycled and deployed independently, essentially creating micro-services. Scalability concerns in a module is another example of an architectural driver that often leads to such a split up.

You've got several tools at your disposal to keep your monolith properly modularised.

  • Designing proper module interfaces used by other parts of the system to interact with the module.
  • Use of Java packages to encapsulate modules, while keeping an eye on cyclomatic complexity.
  • The Java 9 module system. (Although I haven't used this myself yet.)
  • Smart use of multi-module builds in Maven. If you get this right, extracting a module to become its own micro-service might be a relatively trivial matter.
My basic advice would be: focussing on creating properly designed, modularised and high quality software first will make sure micro-services come easy later on.

Friday, August 2, 2019

Adding a JDBC driver to Spring Cloud Data Flow server

A quick tech note on how you can add a JDBC driver dependency (jar) to the classpath when launching the spring-cloud-dataflow-server.

The Spring Cloud Data Flow documentation suggests rebuilding (!?!) when you need to add a custom JDBC driver. That seems a bit crazy to me so after a bit of Googling it turns out you can do it using the Spring Boot PropertiesLauncher:

java -cp spring-cloud-dataflow-server-2.2.0.RELEASE.jar -Dloader.path=lib \
   org.springframework.boot.loader.PropertiesLauncher \
   --spring.datasource.url=jdbc:mysql://localhost:3306/y9a?useSSL=false \
   --spring.datasource.username=root \
   --spring.datasource.password=password \
   --spring.datasource.driverClassName=com.mysql.jdbc.Driver
And you simply have to put the JDBC driver jar file in the lib/ directory:
spring-cloud-dataflow-server-2.2.0.RELEASE.jar
lib/
   mysql-connector-java-8.0.17.jar
Disco!

Tuesday, January 8, 2019

Building a WebSocket application with Spring Boot

This article shows you how to setup a very basic WebSocket application powered by Spring Boot. It uses the Java API for WebSocket (JSR-356) to define a WebSocket server endpoint and includes a very simple JavaScript WebSocket client.

As usual for a Spring Boot application, it all starts with the Maven POM:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <modelVersion>4.0.0</modelVersion>
      <groupId>com.ervacon.sb</groupId>
      <artifactId>websocket</artifactId>
      <version>0.0.1-SNAPSHOT</version>

      <!-- Inherit defaults from Spring Boot -->
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.1.1.RELEASE</version>
      </parent>

      <!-- Add typical dependencies for a websocket application -->
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-websocket</artifactId>
          </dependency>
      </dependencies>

      <!-- Package as an executable jar -->
      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
      </build>

  </project>
Notice how we pull in the spring-boot-starter-websocket dependency. This will make sure the Java API for WebSocket (javax.websocket) is on the classpath, together with Spring's support for WebSocket. When Spring Boot starts it will detect these dependencies and auto-configure the embedded Servlet engine (Tomcat by default) to handle the WebSocket protocol.

Next, we define our @SpringBootApplication class:

package com.ervacon.sb.websocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
The only special thing here is the fact that we register the ServerEndpointExporter, which will make sure our @ServerEndpoint annotated classes get registered with the WebSocket runtime.

We can now define our server side WebSocket endpoint:

package com.ervacon.sb.websocket;

import org.springframework.stereotype.Component;

import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;

@Component
@ServerEndpoint("/socket")
public class WebSocketEndpoint {

    @OnMessage
    public String echo(String message) {
        return "Echo: " + message;
    }
}
Nothing to surprising here: we're just using the Java API for WebSocket (JSR-356) to define a method that will handle incoming text messages by simply echoing them back to the client. That client is implemented using some basic JavaScript code in a simple HTML page (add this as index.html to src/main/resources/static in your Spring Boot application):
<html>
  <head>
      <title>WebSocket Client</title>
      <!-- based on https://www.nexmo.com/blog/2018/10/08/create-websocket-server-spring-boot-dr/ -->
  </head>
  <body>
  <div class="container">
      <div id="messages" style="border: 1px solid gray; padding: 1em;"></div>
      <div class="input-fields">
          <p>Type your message:</p>
          <input id="message"/>
          <button id="send">Send</button>
      </div>
  </div>
  </body>
  <script>
      const messageWindow = document.getElementById("messages");

      const sendButton = document.getElementById("send");
      const messageInput = document.getElementById("message");

      const socket = new WebSocket("ws://localhost:8080/socket");

      socket.onopen = function (event) {
          addMessageToWindow("Connected");
      };

      socket.onmessage = function (event) {
          addMessageToWindow(`Got Message: ${event.data}`);
      };

      sendButton.onclick = function (event) {
          sendMessage(messageInput.value);
          messageInput.value = "";
      };

      function sendMessage(message) {
          socket.send(message);
          addMessageToWindow("Sent Message: " + message);
      }

      function addMessageToWindow(message) {
          messageWindow.innerHTML += `<div>${message}</div>`
      }
  </script>
</html>
We can now launch our Spring Boot application using a simple mvn spring-boot:run and test it by accessing http://localhost:8080/.

Friday, March 2, 2018

Nested Enums

Little known fact that I also only just found out about: nested enum types are implicitly static in Java (see the JLS). However, it is permitted for the declaration of a nested enum type to redundantly specify the static modifier. In other words, the following two enum declarations are effectively equivalent:
public class Foo {

   public static enum Bar {
   }
}


public class Foo {

   public enum Bar {
   }
}

Thursday, May 18, 2017

File.listFiles Gotcha

I had another WTF!? moment trying to get to the bottom of a NullPointerException we've been seeing. It turns out File.listFiles returns null when you're trying to list something that's not actually a directory, or when an I/O error occurs!
/**
 * Returns an array of abstract pathnames denoting the files in the
 * directory denoted by this abstract pathname.

...

 * @return  An array of abstract pathnames denoting the files and
 *          directories in the directory denoted by this abstract pathname.
 *          The array will be empty if the directory is empty.  Returns
 *          {@code null} if this abstract pathname does not denote a
 *          directory, or if an I/O error occurs.
 *
 * @throws  SecurityException
 *          If a security manager exists and its {@link
 *          SecurityManager#checkRead(String)} method denies read access to
 *          the directory
 *
 * @since  1.2
 */
public File[] listFiles() {
Good luck trying to find out which I/O error occurred! I'm guessing just throwing an IOException would have been too easy. Luckily Java 8 provides Files.list as an alternative which does throw an IOException if needed.

Friday, November 25, 2016

Java 8 Update of Bitemporal Framework

Just to push this out to the world a bit more: I've updated the "com.ervacon.bitemporal" framework to bring it up-to-date with current-day Java:
  • Use Java 8's new time classes instead of JodaTime
  • Leverage Java 8's goodies where relevant: streams, diamond operator, ...
  • Switched to Hibernate 5
  • Use JUnit 4
Just as before, "com.ervacon.bitemporal" provides a good starting point for those that need to tackle temporal issues in their applications. For more information, check the GitHub page: https://github.com/klr8/bitemporal.

Monday, May 23, 2016

Java Bean Validation Gotcha

A well known trick for doing cross field validation using Java Bean Validation (JSR-303) is to simply put an @AssertTrue annotation on a method that actually does the validation, like so:
public class Document {

   @NotNull
   private Status status;   
   private Date signingDate;

   @AssertTrue(message = "A signed document should have a signing date")
   public boolean isASignedDocumentHasASigningDate() {
      return status != SIGNED || signingDate != null;
   }
}
The fact that the assertion method actually returns a boolean also makes unit testing easy. So far so good!

However, there is a little known gotcha related to this: the annotated validation method actually has to follow the naming conventions of a boolean bean property getter, i.e. getBla() or isBla(). In other words the following would not work:

   @AssertTrue(message = "A signed document should have a signing date")
   public boolean aSignedDocumentHasASigningDate() {
      return status != SIGNED || signingDate != null;
   }
That's quite unfortunate, and certainly doesn't follow the principle of least astonishment: we're explicitly annotating the method so there is no reason why the bean validator should not pick it up! Even worse, unless you're thoroughly testing all you bean validation annotations, it's easy to miss the fact that the validation is not actually happening. Something to keep in mind!

Friday, December 11, 2015

The Benefits of Building on Multiple Platforms

Organizational policy at a client of mine recently saw me switching my development setup from an Ubuntu Linux based machine to Windows 7 Enterprise. Before this switch everything was Linux based: development was done in Linux, continuous integration ran on Linux, and we were ultimately also deploying to Linux, albeit another distribution.

Making the switch to Windows unearthed a few subtle coding errors, mainly related to resource management. It's no secret Windows is a lot stricter when it comes to file manipulation. For instance, consider the following:

File f = new File("test.tmp");
try (FileOutputStream fout = new FileOutputStream(f)) {
 fout.write("foo".getBytes());
 fout.flush();
 Files.move(f.toPath(), new File("test.txt").toPath());
}
Using Java 8, this runs fine on Linux. However, on Windows you get an error:
java.nio.file.FileSystemException: test.tmp -> test.txt: The process cannot access the file because it is being used by another process.
Looking at the code again you can see that the file is being moved inside the try-with-resources block. In other words, we're attempting to move the file before we've closed the output stream!

In general I would advise different developers in your development team to use different platforms. That will highlight these kind of subtle errors early and will generally improve the quality of your system. It of course comes as little surprise that Juergen Hoeller (of Spring fame) told me on several occasions that he's still developing on Windows for exactly this reason! :-)

Friday, November 20, 2015

Bizar replaceAll tricks

Image you want to replace all asterisk (*) characters in an input string with \*. In other words you want to escape them. One way of doing this in Java is using the String.replaceAll() method:
"foo*bar".replaceAll("\\*", "\\\\*");
To understand what's going on here, let's remind ourselves of what replaceAll() actually does:
/**
 * Replaces each substring of this string that matches the given regular expression
 * with the given replacement.
 * ...
 */
public String replaceAll(String regex, String replacement) {
So that already explains why the first argument to replaceAll() is "\\*": for it to be a valid regular expression we need to escape the asterisk (which of course means zero or more times in a regular expression) using a backslash, and we all know that a backslash character in a Java String needs to be escaped.

But what about the second argument? Shouldn't that just be "\\*" also: a backslash followed by an asterisk? It turns out replaceAll() doesn't treat the replacement as a simple string literal. The Javadoc states the following:

* Note that backslashes (\) and dollar signs ($) in the
* replacement string may cause the results to be different than if it were
* being treated as a literal replacement string
So just having "\\*" as the replacement string would mean we have a backslash in there which we again need to escape! Hence the "\\\\*". It's interesting to note that in a funny twist of fate this actually makes the code less bizar. If the replacement string would have been a simple literal the code would have been "foo*bar".replaceAll("\\*", "\\*");. Imagine coming across that gem when trying to maintain some old piece of code... :-)

Friday, September 4, 2015

Java Exception Fun

Look at this:
public class Test {

  public void f() {
  }

  public void g() {
    try {
      f();
    } catch (Exception e) {
      throw e;
    }
  }
}
Does this compile? Notice that method g() is throwing an exception object declared to be of type Exception but does not actually mention this in its throws clause. In Java 6 this indeed does not compile:
Test.java:10: unreported exception java.lang.Exception; must be caught or declared to be thrown
      throw e;
      ^
1 error
But it came as somewhat of a surprise to me that this compiles just fine in both Java 7 and Java 8! Thinking back this was of course part of the exception improvements made in Java 7. Goes to show that you can still come across little fun nuggets like this after all these years :-).

Wednesday, October 1, 2014

SWF Humor

Funny little blast from the (Spring Web Flow) past. Back in 2006 while working on Spring Web Flow 1.0 we needed an exception class signaling a failure to parse a flow execution key. Keith Donald and myself jokingly considered calling it the FuckedUpFlowExecutionKeyException but ultimately settled for BadlyFormattedFlowExecutionKeyException. Indeed, it would be quite painful if a user was presented with a FuckedUpFlowExecutionKeyException stack trace after having accidentally corrupted the key in the URL of his browser. :-)

The joke continued for a little bit with the following piece of JavaDoc that you can find in the Spring Web Flow 1.0 source code:

package org.springframework.webflow.execution.repository;

/**
 * Thrown when an encoded flow execution key is badly formatted and could not be
 * parsed. We debated calling this the FuckedUpFlowExecutionKeyException.
 * 
 * @author Keith Donald
 * @author Erwin Vervaet
 */
public class BadlyFormattedFlowExecutionKeyException extends FlowExecutionRepositoryException {
This was not enough however, a particularly sensitive person actually complained about Spring Web Flow using offensive language! In the end this bit of nostalgia was kicked out in the 1.0.1 release. Still makes for a fun anecdote however! ;-)

Monday, June 16, 2014

Puzzling loop

Another fun Java puzzler that you would think you would never encounter in the wild but I happened to run across something similar a few days ago:
public class Puzzler {

 public static void main(String[] args) throws Exception {
  PuzzleFuction f = new PuzzleFuction();
  for (int i = 0; i < f.invoke(); i++) {
   System.out.println(i);
  }
 }

 public static class PuzzleFuction {

  private int invocationCount;

  public int invoke() {
   invocationCount++;
   return invocationCount < 2 ? 2 : 5;
  }
 }
}
What does this print? In other words: does the loop boundary (f.invoke()) get evaluated again every iteration? Of course it does! :-)
01234

Sunday, May 26, 2013

Doing JSON on CXF

Doing RESTful web services using Apache CXF can be an adventure. Unfortunately this adventure again requires some ploughing through mud. Let's look at a very simple JAX-RS resource implementing the canonical order-item example:
@Path("/orders")
public class OrderResource {

 @GET
 @Produces(MediaType.APPLICATION_JSON)
 public List<Order> getOrders() {
  List<Order> orders = new ArrayList<>();
  orders.add(new Order(123L, new Item("Foo", 2)));
  //orders.add(new Order(456L, new Item("Foo", 1), new Item("Bar", 3)));
  return orders;
 }

 public static class Order {

  private long id;
  private List<Item> items = new ArrayList<>();

  public Order(long id, Item... toAdd) {
   this.id = id;
   this.items.addAll(Arrays.asList(toAdd));
  }

  public long getId() {
   return id;
  }

  public List<Item> getItems() {
   return Collections.unmodifiableList(items);
  }
 }

 public static class Item {

  private String name;

  private int quantity;

  public Item(String name, int quantity) {
   this.name = name;
   this.quantity = quantity;
  }

  public String getName() {
   return name;
  }

  public int getQuantity() {
   return quantity;
  }
 }
}
Next step is deploying this on a JEE6 application server. I used GlassFish, which internally uses Jersey as JAX-RS implementation and Jackson as JSON provider. The resource spits out the following JSON:
[
  {
    "id":123,
    "items":[
      {
        "name":"Foo",
        "quantity":2
      }
    ]
  }
]
That's pretty much what you would expect: a list of orders which are made up of an id and a list of items. Uncommenting the second order in the Java code above confirms that the structure is consistent:
[
  {
    "id":123,
    "items":[
      {
        "name":"Foo",
        "quantity":2
      }
    ]
  },
  {
    "id":456,
    "items":[
      {
        "name":"Foo",
        "quantity":1
      },
      {
        "name":"Bar",
        "quantity":3
      }
    ]
  }
]
So far so good! Let's repeat this exercise and deploy the resource on CXF. The JSON with a single order now looks like this:
{
  "order":[
    {
      "id":123,
      "items":{
        "name":"Foo",
        "quantity":2
      }
    }
  ]
}
That's not quite what we expected: we've got a wrapping JSON map with a list of orders inside it labelled "order"! Furthermore, the list of items inside the order no longer appears to be a list! Note that there is are no square brackets surrounding it. Getting back the list of two orders makes things even more surprising:
{
  "order":[
    {
      "id":123,
      "items":{
        "name":"Foo",
        "quantity":2
      }
    },
    {
      "id":456,
      "items":[
        {
          "name":"Foo",
          "quantity":1
        },
        {
          "name":"Bar",
          "quantity":3
        }
      ]
    }
  ]
}
Wow, the list of items is back inside the order structure! Apparently you get a list if you have multiple items, and just the single item if you just have one. That's pretty bad since the JSON structure for an order is now no longer consistent, which of course makes parsing it a headache.

The reason for all of this madness is the fact that CXF is at it's core an XML framework (notice the X in CXF). Doing JSON with CXF involves a bit of trickery. Internally, CXF will first use JAXB to marshall your objects into XML. Actually, I was cheating earlier: you can't directly deploy the OrderResource class shown above on CXF. First you'll have to add JAXB annotations, getters and setters, and other such frivolities to appease JAXB:

@XmlRootElement
public class Order {

 private long id;
 private List<Item> items = new ArrayList<>();

 public long getId() {
  return id;
 }

 public void setId(long id) {
  this.id = id;
 }

 public List<Item> getItems() {
  return items;
 }

 public void setItems(List<Item> items) {
  this.items = items;
 }
}
JAXB produces XML but we want JSON! To resolve this conundrum CXF uses a StAX implementation called Jettison which does not actually write XML but instead outputs JSON. Clever! The downside here is that JSON is produced from XML, not from Java objects. Consequently, Java type information is no longer available when JSON is written out. Looking at the XML produced by JAXB for an order with a single item clarifies things:
<orders>
  <order>
    <id>123</id>
    <items>
      <name>Foo</name>
      <quantity>2</quantity>
    </items>
  </order>
</orders>
Looking at this XML, you have no way of knowing that you can have multiple <items> elements. Since Java type information is no longer available, Jettison cannot see that items is actually a java.util.List and consequently it omits the list in the JSON structure:
{
  "order":[
    {
      "id":123,
      "items":{
        "name":"Foo",
        "quantity":2
      }
    }
  ]
}
If you have an order with multiple items, multiple <items> elements will be present in the XML and as a result the JSON will contain a list.

This type of translation from XML to JSON is called the mapped convention. CXF (or rather Jettison) also supports the BadgerFish convention, but it's much more esoteric.

By default CXF uses Jettison to produce JSON. Although this might be useful if you're using JAXB for other reasons, it might be better to configure CXF to use Jackson if you're just doing JAX-RS with JSON. Luckily this is easy to do.

Thursday, February 14, 2013

@Transactional mud

More wading through mud today at work, @Transactional mud on this occasion. The @Transactional annotation is Spring's way of specifying a method needs transactional semantics. It sounds simple enough: all you need is <tx:annotation-driven/> in your application context to tell Spring you'll be using annotations to demarcate transactions, and a few of those @Transactional annotations sprinkled around your code, like so:
@Service
@Transactional(rollbackFor = Throwable.class, readOnly = true)
public class MyService {

  @Transactional(readOnly = false)
  public void doStuff() throws SomeCheckedException {
    // ...
  }
}
Following the principle of least astonishment, I assumed the code above defined the doStuff() method as running in a read-write transaction (readOnly = false) which rolls back for all types of exceptions (rollbackFor = Throwable.class). The cool thing here is that you can use a class level annotation to setup useful defaults while the method level annotation adjusts settings as required for a particular method.

It took quite a bit of head scratching to realize this is not actually true! With the above code, no rollback would occur if doStuff() threw SomeCheckedException! The reason is that the transaction attributes in the method level annotation replace those in the class level annotation rather that the two being merged together. If you think about it this makes sense: Spring has no way of knowing at run-time whether you explicitly specified the rollbackFor on the annotation or just used the default value! Since the default rollback behavior is to not rollback on checked exceptions, this can give quite surprising results.

Lesson learned: check!

Tuesday, January 8, 2013

Check caching of HTTP resources

Setting up HTTP caching can be a bit of pain. Essentially the HTTP response needs to contain appropriate cache control headers, either an Expires header or a Cache-Control max-age directive. Here's a quick Java program using the HttpClient and HttpClient Cache (both part of the Apache HttpComponents) to test client-side caching of HTTP responses.
public class TestHttpCaching {

 public static void main(String[] args) throws Exception {
  CacheConfig config = new CacheConfig();
  config.setMaxObjectSize(Long.MAX_VALUE);
  HttpClient httpClient = new CachingHttpClient(config);

  doGetRequest(httpClient, args[0]);
  doGetRequest(httpClient, args[0]);
 }

 private static void doGetRequest(HttpClient httpClient, String url) throws Exception {
  HttpGet httpGet = new HttpGet(url);
  HttpContext httpContext = new BasicHttpContext();
  try {
   System.out.print("Getting... ");
   System.out.print(httpClient.execute(httpGet, httpContext).getStatusLine());
   System.out.println(": " + httpContext.getAttribute(CachingHttpClient.CACHE_RESPONSE_STATUS));
  } finally {
   httpGet.releaseConnection();
  }
 }
}
The standard DefaultHttpClient does not do any caching. Instead you have to use the CachingHttpClient which wraps a DefaultHttpClient and adds caching functionality. Also notice how the cache is configured with a very large maximum object size. This avoids resources not being cached because they are too large for the standard in-memory cache (BasicHttpCacheStorage).

Saturday, November 10, 2012

Getting started with Spring Shell

I thought I'd write up a quick getting-started guide for Spring Shell. Spring Shell is the new Spring portfolio project that helps you in building easy to use command line interfaces for whatever commands you provide. Commands can really be anything. For instance, on most projects the developers end up writing a bunch of tools and utilities automating tedious tasks such as setting up a database schema, scanning through log files or doing some code generation. All of these would be perfect examples for what a Spring Shell command can be. Using Spring Shell to house all of your tooling and utility commands in a coherent shell makes them self documenting and easier to use for other developers on the team.

Let's setup a trivial Spring Shell application to get started. In follow-up posts I'll cover more advanced Spring Shell functionality. I'll be using Maven in this example because I think that's what most people are familiar with (Spring Shell itself is built with Gradle).

Here's the POM for the spring-shell-demo project (available on GitHub):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.ervacon</groupId>
 <artifactId>spring-shell-demo</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>Spring Shell Demo</name>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <repositories>
  <!-- see https://jira.springsource.org/browse/SHL-52 -->
  <repository>
   <id>ext-release-local</id>
   <url>http://repo.springsource.org/simple/ext-release-local/</url>
  </repository>
 </repositories>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell</artifactId>
    <version>1.0.0.RELEASE</version>
   </dependency>
  </dependencies>
 </dependencyManagement>
 
 <dependencies>
  <dependency>
   <groupId>org.springframework.shell</groupId>
   <artifactId>spring-shell</artifactId>
  </dependency>
 </dependencies>
 
 <build>
  <plugins>
   <!-- copy all dependencies into a lib/ directory -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.1</version>
    <executions>
     <execution>
      <id>copy-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
       <goal>copy-dependencies</goal>
      </goals>
      <configuration>
       <outputDirectory>${project.build.directory}/lib</outputDirectory>
       <overWriteReleases>true</overWriteReleases>
       <overWriteSnapshots>true</overWriteSnapshots>
       <overWriteIfNewer>true</overWriteIfNewer>
      </configuration>
     </execution>
    </executions>
   </plugin>
   
   <!-- make the jar executable by adding a Main-Class and Class-Path to the manifest -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
     <archive>
      <manifest>
       <addClasspath>true</addClasspath>
       <classpathPrefix>lib/</classpathPrefix>
       <mainClass>org.springframework.shell.Bootstrap</mainClass>
      </manifest>
     </archive>
    </configuration>
   </plugin>
  </plugins>
 </build>

</project>

There's quite a bit going on in this POM. First thing to note is the declaration of the ext-release-local SpringSource repository. This is needed to be able to resolve one of Spring Shell's dependencies: JLine (check SHL-52 for more background info). Hopefully this will no longer be necessary in future versions of Spring Shell. Next there's a dependency on Spring Shell itself. No surprise there. Finally, the POM customizes the build by copying all dependencies into a lib/ directory and adding a Main-Class and Class-Path property to the manifest of the generated jar file. Doing this produces the following directory structure in your target folder:

target/
 spring-shell-demo-1.0-SNAPSHOT.jar
 lib/
  all dependencies
You can simply package this up and distribute your shell. It will be fully self-contained and launching it is trivial:
java -jar spring-shell-demo-1.0-SNAPSHOT.jar

Hold on there, we're getting ahead of ourselves. Before launching the shell let's first add an echo command that just prints its input text back out to the console. Here's the code, which lives in the com.ervacon.ssd package:

@Component
public class DemoCommands implements CommandMarker {

 @CliCommand(value = "echo", help = "Echo a message")
 public String echo(
   @CliOption(key = { "", "msg" }, mandatory = true, help= "The message to echo") String msg) {
  return msg;
 }
}

As you can see, a Spring Shell command is just a @CliCommand annotated method on a Java class tagged with the CommandMarker interface. Our echo method takes a single argument which will be a mandatory @CliOption for the command. By using both the empty string and msg as keys for the option, you'll be able to invoke the command both as echo test and echo --msg test. The method simply returns the message: Spring Shell will make sure it gets printed to the console.

Alright, we've got our command implemented! We still have to tell Spring Shell about it. Since Spring Shell is Spring based, adding a command simply means defining a Spring bean. On start up, Spring Shell will automatically load the application context defined in classpath:/META-INF/spring/spring-shell-plugin.xml. You typically setup component scanning and simply mark your command classes as @Components, making development of new commands trivial since the shell will automatically detect them. Here's the application context definition:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

 <context:component-scan base-package="com.ervacon.ssd" />

</beans>

And that's it! We're ready to build and launch our shell:

mvn package
java -jar target/spring-shell-demo-1.0-SNAPSHOT.jar

Thursday, October 25, 2012

More mud: SimpleDateFormat and the Gregorian calendar

I spent another few hours wading through mud at work the other day, SimpleDateFormat related mud this time around. You would assume "yyyy/MM/dd HH:mm z" to be a pretty solid date format for representing a timestamp with minute precision:
  • yyyy/MM/dd: the date, e.g. "2012/10/23"
  • HH:mm: the time in 24-hour format, e.g. "18:32"
  • z: the timezone, e.g. "CET"
This date format can be used to store dates in a text file (or any other textual format for that matter, e.g. XML). Let's go one step further and always use UTC as the time zone for the dates stored in our text file. That avoids all confusion when parsing the file again: all dates are expressed in UTC. Here's a bit of code that does what we need: it takes an input Date object and formats it as a UTC date string, it then parses that UTC date again and verifies that the input and output are the same.
Date input = new Date(-62135773200000L); // "0001/01/01 00:00 CET"

SimpleDateFormat utc = new SimpleDateFormat("yyyy/MM/dd HH:mm z");
utc.setTimeZone(TimeZone.getTimeZone("UTC"));

String str = utc.format(input);

Date output = utc.parse(str);

if (input.equals(output)) {
 System.out.println("Equal!");
} else {
 System.out.println(input + " != " + output);
}
For most dates this would print Equal!. However, I used a special date in the code above: midnight on January 1st of the year 1 expressed in CET. The output on my machine is:
Sat Jan 01 00:00:00 CET 1 != Sun Jan 01 00:00:00 CET 2
What!? Year 1 became 2? Let's look at the string produced by the date formatting:
0001/12/31 23:00 UTC
The time becomes 23:00 UTC because CET is one hour ahaid of UTC. To understand why the day jumped to December 31st of the year 1, you have to realize that the Gregorian calendar, on which UTC and CET are based, does not have a year 0. This means the timeline looks like this (BC is Before Christ, AD is Anno Domini, the era indicator in SimpleDateFormat terms):
..., 2 BC, 1 BC, 1 AD, 2 AD, ...

The date formatting assumes January first of the year 1 to be AD. To move from midnight CET to 23:00 UTC, we end up in the previous day: December 31st of the year 1 BC. However, our date format does not encode the era (BC / AD), so when the date is parsed, year 1 is again assumed to be AD, which leads to the rather surprising result that year 1 AD becomes year 2 AD after the UTC to CET time adjustment.

Luckily fixing the problem is easier than understanding it! You simply need to add the era indicator to the date format pattern: "yyyy/MM/dd HH:mm z G", and the above code will work as expected.

PS: This problem popped up during an XStream version upgrade. Check XSTR-556 and XSTR-711 in the XStream JIRA for more information.

Thursday, November 24, 2011

JDK8 and the future of JVM based languages

Last week at Devoxx 2011 I attended a number of sessions covering new JVM based programming languages such as Kotlin and Ceylon. Of course there were also a number of sessions talking about the usual suspects: Groovy, Scala and JRuby.

There were also a considerable amount of talks covering JDK8 and how that's shaping up. I got the strong impression that Oracle certainly doesn't want to see JDK8 turn into another multi-year debacle. Progress on JDK8 (vitual extension functions, closures, ...) seems impressive and I got a real sense of direction and focus from those involved.

I've been following the whole other languages on the JVM movement that has been going on the last couple of years with interest, but mostly as a by-stander: I'm not a hard-core, opinionated programming language expert like some. However, if I look at the input I gathered at Devoxx I can't help but make a few observations:
  • Although some of the new JVM languages have interesting ideas and are definately a step up from Java, they didn't trigger that aha-erlebnis I had when I first started using Java 1.02 after having used C.
  • The infectuation with dynamic typing seems to be largely over: everybody is back in agreement that strong static typing is the way to go.
  • Scale can't get any love and seems destined to remain an interesting language experiment.
  • Oracle is on somewhat of a mission to deliver JDK8 sooner rather than later.
All of this makes me wonder if Java's successor will actually be Java itself, but in it's 8th incarnation, and whether or not Java 8 will effectively blow all new contenders out of the water? I'm looking forward to seeing how this unfolds!

Friday, October 28, 2011

Java puzzler

Take a look at the following piece of code:
package test;

import java.util.Date;

public class Test {

 public static String format(Date date) {
  return String.valueOf(date);
 }

 public static String format(long millis) {
  return format(new Date(millis));
 }

 public static String format(Instant instant) {
  return format(instant == null ? null : instant.getMillis());
 }

 public static class Instant {

  private long millis;

  public Instant(long millis) {
   this.millis = millis;
  }

  public long getMillis() {
   return millis;
  }
 }

 public static void main(String[] args) {
  Instant instant = null;
  format(instant);
 }
}
Any idea what the output will be? Turns out this throws a NullPointerException:
Exception in thread "main" java.lang.NullPointerException
 at test.Test.format(Test.java:16)
 at test.Test.main(Test.java:34)
Interesting. Line 16 is clearly fishy: The idea is that if the instant is null, the format(Date) method should be called, while format(long) should be called otherwise. It turns out things are much more contrived at the bytecode level (use javap -c):
public static java.lang.String format(test.Test$Instant);
  Code:
   0: aload_0
   1: ifnonnull 8
   4: aconst_null
   5: goto 15
   8: aload_0
   9: invokevirtual #35; //Method test/Test$Instant.getMillis:()J
   12: invokestatic #41; //Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
   15: invokevirtual #46; //Method java/lang/Long.longValue:()J
   18: invokestatic #49; //Method format:(J)Ljava/lang/String;
   21: areturn
This actually translates to the following Java code, which clearly explains the NullPointerException:
public static String format(Instant instant) {
 return format((instant != null ? Long.valueOf(instant.getMillis()) : null).longValue());
}
Sometimes autoboxing can really rear its ugly head!

Tuesday, July 19, 2011

Java SE 7

It was a long time in the making but all JSRs constituting Java SE 7 have crossed the finish line! The actual Java SE 7 software release is just around the corner (July 28th). Exciting stuff!