Spring Boot @WebMvcTest and MessageSource

Spring Boot makes it really easy to translate your application. As soon as a message.properties and accompanying message_*.properties are on the class path, it configures a org.springframework.context.MessageSource which can be used in view templates or inside a controller layer through org.springframework.context.support.MessageSourceAccessor as I have done here.

If you wanna test this, either your controller or if your translating your views correctly and you are using the new Spring Boot 1.4 test improvements, you’ll have to manually configure the MessageSourceAutoConfiguration, which isn’t done by @WebMvcTest like so:

@RunWith(SpringRunner.class)
@WebMvcTest(
        controllers = BikesController.class,
        secure = false        
)
@ImportAutoConfiguration(MessageSourceAutoConfiguration.class)
public class BikesControllerTest {
}

See complete example here.

This took me a while to figure out, so I thought that this is maybe useful.

| Comments (0) »

04-Aug-16


DOAG Konferenz und Ausstellung 2016

13 years ago, I visited my first IT conference ever, the DOAG in Mannheim 2003. This year, I will be speaking myself at #DOAG2016 about creating database centric applications with Spring Boot and jOOQ in German (see abstract below).

After a successful premier of speaking in the IT circus earlier this year at Spring I/O about custom Spring Boot starters (btw, I’m also at W-JAX this year with a refined version of that talk), I’m really happy to be accepted at DOAG.

I’ve been very deeply into all things databases since the beginning of my career. My company runs several applications which changed their faces many times over the last decade, but the relational model stood the test of time, often only added to, never completely rewritten.

When visiting DOAG in 2003 and later my company was looking for alternatives to Oracle Forms 6i, whose end off error correction support was announced for the end of 2004 and extended support ending 2008.

Back then we where depending on Client / Server support and Oracle Forms 9 only available as a 3-tier architecture wasn’t an option for us.

I saw lot of different approaches: The whole J2EE stack (yes, it was called that way back then) which was a nightmare to me, lot of different approaches for automagically converting old Forms applications to new ones or the J2EE or to Java clients, which were working equally bad for us, Oracle ADF, Oracle APEX and so on.

Personally, I spent some time in Ruby on Rails land (being back in Java land since 2010), my company opted for Java Swing where desktop clients where needed and Grails respectively pure Spring / Spring Boot with various view technologies otherwise.

Now, more than a decade later, one powerful and given that power, relatively easy to understand technology stack for database centric application with a nice UI for me is Spring Boot using jOOQ to access the database and rendering a nice UI with Oracle JET.

For me, there’s no easier way to start a modern Webapplication then with Spring Boot. The stuff just works and it has an automatic configuration for jOOQ as well.

For accessing relational databases I’d actually prefer an ORM used together with Spring Data JPA for many tasks, but when it comes to reporting and batch inserting, why not using the power of your database, for which you probably have spent a lot of money for? Why computing it on the application server or even worse, at client side? Here is where SQL shines and jOOQ is really great way to write type safe SQL and throw it your database.

In my demo I’ll use my scrobbled (like Last.FM) music data from the last 10 years to build up a chart reporting engine. The graphs will be rendered inside a simple Oracle JET dashboard.

The demo will facilitate Docker (through the Maven Docker Plugin) for creating the development database instance and will be runnable as a fat jar presenting itself like this:

If you want to hear more about that, meet me in Nürnberg, somewhere between 15th an 18th November.

And, as promised, the abstract in German:

Datenbankzentrische Anwendungen mit Spring Boot und jOOQ

In diesem Vortrag wird eine Variante datenbankzentrischer Anwendungen mit einer modernen Architektur vorgestellt, die sowohl in einer klassischen Verteilung als auch “cloud native” genutzt werden kann und dabei eine sehr direkte Interaktion mit Datenbanken erlaubt.

jOOQ ist eine von vielen Möglichkeiten, Datenbankzugriff in Java zu realisieren, aber weder eine Objektrelationale Abbildung (ORM) noch “Plain SQL”, sondern eine typsichere Umsetzung aktueller SQL Standards in Java. jOOQ “schützt” den Entwickler nicht vor SQL Code, sondern unterstützt ihn dabei, typsicher Abfragen in Java zu schreiben.

Spring Boot setzt seit 2 Jahren neue Standards im Bereich der Anwendungsentwicklung mit dem Spring Framework. Waren vor wenigen Jahren noch aufwändige XML Konfigurationen notwendig, ersetzen heute “opinionated defaults” manuelle Konfiguration. Eine vollständige Spring Boot Anwendung passt mittlerweile in einen Tweet.

Der Autor setzt die Kombination beider Technologien erfolgreich zur Migration einer bestehenden, komplexen Oracle Forms Client Server Anwendung mit zahlreichen Tabellen und PL/SQL Stored Procedures hinzu einer modernen Architektur ein. Das Projekt profitiert sehr davon, die Datenbankstrukturen nicht in einen ORM “zu zwängen”.

Nach einer kurzen Einführung dieser Themen wird eine Demo “from scratch” entwickelt, die zuerst die niedrige Einstiegshürde in die Spring basierte Entwicklung mit Java und danach die einfache Verwendung moderner SQL Konstrukte zeigt, ohne das ein ORM oder stringbasierte SQL Statements im Weg stehen. Der Abschluss der Demo wird eine JSON Api sein, die von einer OracleJET Clientanwendung genutzt wird.

Die Besucher kennen im Abschluss eine schlanke Alternative sowohl zur aufwändigen JPA basierten Entwicklung als auch zu APEX Anwendungen.

| Comments (5) »

28-Jul-16


arc42 documentation: Building block intent from JavaDoc

Here’s a quick post to get the week started: Recently I was working on my arc42 example project, enforcing Sun / Oracle coding conventions through Checkstyle and it bugged me that my project was missing several package-info.java files.

While adding them and writing something useful I was happy that I chose good slices that fit exactly my building blocks.

As I was pretty much duplicating the docs, I tried to get the JavaDoc into my AsciiDoc documentation.

Including other files and parts of other files in AsciiDoc is easy, see include directive:

==== bikes (Blackbox)
 
Intent/Responsibility::
 
include::../main/java/ac/simons/biking2/bikes/package-info.java[tags=intent]

(see 05_building_block_view.adoc)

That means: go to package-info.java and get all the text between “tag::intent[]” and “end::intent[]”.

What I was struggling with was to come up with a formatting of the JavaDoc that works well in JavaDoc and in AsciiDoc. This is my solution:

/**
 <!-- tag::intent[] -->
   `bikes` provides the external API for reading, creating and manipulating
   bikes and their milages as well as computing statistics and generating charts.
 <!-- end::intent[] -->
 */
package ac.simons.biking2.bikes;

(see package-info.java)

That results in:


JavaDoc result

and


AsciiDoc result

Well, I think that AsciiDoc is indeed a pretty good way to write technical documentation, though I still am more fluent in Markdown. I’m using the AsciiDoctor Maven plugin for my projects, Ralf has a nice blog post published today that helps you getting started with AsciiDoc using Gradle: Simple AsciiDoc Build with Gradle.

| Comments (0) »

11-Jul-16


Implementing builders in Java


Note: Much improved versions of this post have been published to JAXenter.de and JAXenter.com:
Erzeugungsmuster mit Java 8 Lambdas
Creational patterns with Java 8 lambdas

I hope you enjoy reading them as much as I enjoyed writing them!

Sometimes I’m under the impression that one of my favorite DI frameworks, Spring, is the butt of a gazillion jokes regarding factories. For example it has a SimpleBeanFactoryAwareAspectInstanceFactory.

The name is actually well chosen: You’ll get a factory that produces instances of aspects by using another factory. It must be a factory, as you want to have polymorphism:

“In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created.”

“Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.”

Factory method pattern

Though I find factories useful, I’m under the impression that they are most useful in frameworks, providing groundworks for other stuff, for example for decorators through aspects.

Application wise I often need builders:

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.

Builder pattern

Sometimes it’s actually correct, to end up with a “MyClassBuilderGenerationFactory” (though I’d probably call it MyClassFactoryBuilder, saying that it is a builder to create factories producing instances of MyClass):

So, what’s my favorite way of implementing builders using Java? Well, I pretty much have the idea from the great Venkat Subramaniam (if you have the chance to see one of his talks, go!). The example comes from a real world project (our temperature monitor) and builds a sensor:

import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;
import java.util.function.Consumer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
 
public class Sensor {
 
    // (1)
    private final DocumentBuilder documentBuilder;
 
    private final XPathExpression xPathExpression;
 
    private final DateTimeFormatter dateTimeFormatter;
 
    private final String url;
 
    // (2)
    Sensor(Builder builder) {
        try {
            this.documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            this.xPathExpression = XPathFactory.newInstance().newXPath().compile("/wx/temperature/current");
        } catch (ParserConfigurationException | XPathExpressionException ex) {
            throw new RuntimeException("Could not create DocumentBuilder or XPath", ex);
        }
 
        this.dateTimeFormatter = DateTimeFormatter
                .ofPattern(builder.dateTimePattern, builder.locale)
                .withZone(builder.timeZone.toZoneId());
 
        this.url = builder.url;
    }
 
    // (3)
    public static Sensor forUrl(final String url, final Consumer<Builder> cfg) {
        final Builder builder = new Builder(url);
        cfg.accept(builder);
        return new Sensor(builder);
    }
 
    public static class Builder {
 
        private String url;
 
        // (4)
        private String dateTimePattern = "dd.MM.yyyy (HH:mm)";
 
        private Locale locale = Locale.GERMAN;
 
        private TimeZone timeZone = TimeZone.getTimeZone("Europe/Berlin");
 
        // (5)
        private Builder(String url) {            
            this.url = url;
        }
 
        public Builder withUrl(String url) {
            // (6)
            if (url == null || url.isEmpty()) {
                throw new IllegalArgumentException("URL may not be empty!");
            }
            this.url = url;
            return this;
        }
 
        public Builder withDateTimePattern(String dateTimePattern) {
            this.dateTimePattern = dateTimePattern;
            return this;
        }
 
        public Builder withLocale(Locale locale) {
            this.locale = locale;
            return this;
        }
 
        public Builder withTimeZone(TimeZone timeZone) {
            this.timeZone = timeZone;
            return this;
        }
    }
 
    public static void main(String... a) {
        // (7)
        final Sensor sensor = Sensor.forUrl("http://wetter-aachen-brand.de/mwlive.xml", cfg -> cfg
                .withTimeZone(TimeZone.getTimeZone("Europe/Berlin"))
                .withLocale(Locale.GERMAN)
        );
    }
}

What do we have here?

  1. An immutable sensor object, all values are final, including the ones that take more than one information to configure (i.e. the dateTimeFormatter).
  2. A sensor cannot be build without the builder, so you won’t end up with invalid objects. Also, you won’t end up with a telescoping constructor (adding more and more arguments or overloading constructors). As you can see I don’t mind some intelligence in a constructor, but you could move the instantiation of the stuff that throws exceptions into the builder
  3. Several things going on here:
    A “speaking” method: I’ll always want to have a sensor for a given URL. Also note that I want to make clear which values are obligatory. A sensor without an URL is useless. If you add Project Lombok you can get rid of the manuell checks in (6)
    The creational method takes a Consumer as an argument. Together with the private Builder constructor in (5) this leads to the fact that the builder cannot be instantiated without the context of a Sensor. This clarifies the fact, the this builder here should be used once and only once. The creational method does the build, not the external caller.
  4. Decouple the builder properties from the actual needed properties. The builder knows a format pattern, the resulting object the formatter.
  5. Don’t allow the builder to be used standalone, only in the context of (3).
  6. Check for required arguments in the builder methods.
  7. Finally: A fluent API to configure your objects in a very concise way.

But can we do better than that? What if the creation of stuff depends on an order? It’s actually pretty easy to implement and you’ll get a very clean interface, without the need for purely functional languages by just using Java 8 idioms:

import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;
import java.util.function.Function;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
 
public class Sensor {
 
    private final DocumentBuilder documentBuilder;
 
    private final XPathExpression xPathExpression;
 
    private final DateTimeFormatter dateTimeFormatter;
 
    private final String url;
 
    // (1)
    Sensor(BuilderStep3 builder) {
        this.documentBuilder = builder.documentBuilder;
        this.xPathExpression = builder.xPathExpression;
        this.dateTimeFormatter = builder.dateTimeFormatter;
        this.url = builder.url;
    }
 
    public static class Builder {
 
        private String url;
 
        private Builder(String url) {
            this.url = url;
        }
 
        // (2)
        public BuilderStep2 withDateTimePattern(final String dateTimePattern) {
            return new BuilderStep2(url, dateTimePattern);
        }
    }
 
    public static class BuilderStep2 {
 
        private final String url;
 
        private String dateTimePattern = "dd.MM.yyyy (HH:mm)";
 
        private Locale locale = Locale.GERMAN;
 
        private TimeZone timeZone = TimeZone.getTimeZone("Europe/Berlin");
 
        public BuilderStep2(final String url, final String dateTimePattern) {
            this.url = url;
            this.dateTimePattern = dateTimePattern;
        }
 
        public BuilderStep2 withDateTimePattern(String dateTimePattern) {
            this.dateTimePattern = dateTimePattern;
            return this;
        }
 
        public BuilderStep2 withLocale(Locale locale) {
            this.locale = locale;
            return this;
        }
 
        public BuilderStep2 withTimeZone(TimeZone timeZone) {
            this.timeZone = timeZone;
            return this;
        }
 
        // (3)
        public BuilderStep3 withPath(final String path) {
            return new BuilderStep3(url, DateTimeFormatter
                    .ofPattern(this.dateTimePattern, this.locale)
                    .withZone(this.timeZone.toZoneId()), path);
        }
 
    }
 
    // (4)
    public static class BuilderStep3 {
 
        private final String url;
 
        private final DateTimeFormatter dateTimeFormatter;
 
        private final DocumentBuilder documentBuilder;
 
        private final XPathExpression xPathExpression;
 
        public BuilderStep3(String url, DateTimeFormatter dateTimeFormatter, String path) {
            this.url = url;
            this.dateTimeFormatter = dateTimeFormatter;
            try {
                this.documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                this.xPathExpression = XPathFactory.newInstance().newXPath().compile(path);
            } catch (ParserConfigurationException | XPathExpressionException ex) {
                throw new RuntimeException("Could not create DocumentBuilder or XPath", ex);
            }
        }
    }
 
    // (5)
    public static Sensor forUrl(final String url, final Function<Builder, BuilderStep3> cfg) {
        return cfg.andThen(Sensor::new).apply(new Builder(url));
    }
 
    public static void main(String... a) {
        // (6)
        final Sensor sensor = Sensor.forUrl("http://wetter-aachen-brand.de/mwlive.xml", cfg -> cfg
                .withDateTimePattern("dd.MM.yyyy")
                .withLocale(Locale.GERMAN)
                .withPath("/wx/temperature/current")
        );
    }
}
  1. The sensor now takes a BuilderStep3 argument. Also take note that I have moved the construction of complex objects into the builders as well
  2. The first builder returns a BuilderStep2 as the context changes from an url to datetime stuff
  3. Context changes again from creating the actual DateTimeFormatter to XML and XPath stuff
  4. BuilderStep3 is the last step and returns no other builder (and also has no build method!)
  5. Here is the “fun”: The creational function now takes a Function from Builder to a BuilderStep3 as argument and no simple consumer. This way I am in control over creating the first builder and then I can guide the user of my builders through the right order of configuring stuff. The final usage in (6) doesn’t look much different but it’s now the only way to use that set of builders
    Also take note how easily you can chain function calls in Java 8
  6. Final usage: Configuration can only be done in the correct order

I think my last suggestion can be very nice integrated into the Step builder pattern as described by Marco.

| Comments (2) »

06-Jul-16


On sourcecode formatting

Without any comment on which style is right, you can use GNU util expand / unexpand to replace tabs with spaces and vice versa.

For example, you can use the following command to replace all tabs with spaces and the recommended 8 spaces width in all Java files through

find . -name '*.java' ! -type d -exec bash -c 'expand -t 8 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;

Expand takes care of spaces between tabs and should be the preferable solution to sed in this case.

While you’re at it, you can use sed however to trim trailing spaces:

find . -iname '*.java' -type f -exec sed -i '' 's/[[:space:]]\{1,\}$//' {} \+

For further reading, follow this discussion:

😉

| Comments (0) »

04-Jul-16