Tuesday, May 2, 2017

How to Develop Microservices with Spring Boot

Spring Boot is a good framework/platform for Java to develop microservices. Other programming languages also have frameworks that enable writing microservices with easy: Python with Flask, PHP with Laravel Lumen. With Java platform you also have many options: Spring Boot is one, but there is also Dropwizard, Vert.x, and Play framework (nice if you like Scala).

It is also possible to develop a microservice application from scratch using a plain Maven project, since you can add POM dependencies easily. However, you will soon be busy wiring and configuring several low-level infrastructural things like logging, HTTP client library, security, and so on that it may distract you from the core issue: application functionality.

Advantages of Spring Boot for Microservices

There are a number of advantages of using Spring Boot for developing microservices. This is not all but you get the idea.

  • You get necessary infrastructural "services" like logging, application configuration, REST API support (both client and server), JSON parsing and generation, data access, mostly out-of-the-box or with minimal configuration.
  • Spring Boot application is directly runnable. Once the app is built with Maven, it can be run using "java -jar" standard technique, and it can be deployed on any server (just by installing a JRE or JDK) or cloud platforms such as Cloud Foundry, Red Hat OpenShift, Heroku, and so on.
  • Lightweight footprint. While the definition of "lightweight" can be ambiguous (a Spring Boot application isn't as light as a bare bones Java app without logging etc.), a minimal Spring Boot app has only a few dependencies. In practice it's just Spring Framework dependency injection, logging, Spring Boot thin wrapper, and some helper libraries that are useful for your app as well. You can add only Spring Boot modules that you need so there is no unnecessary bloat. It keeps memory usage minimum as well.
  • Fast. A simple Spring Boot app starts in a few seconds. Less startup time means it can get your app to do its job sooner.
  • Modular. There are various Spring Boot modules that provide additional functionality. Mostly minimal configuration and some doesn't even require any configuration. For example if you need a web server you can just add Spring Boot Web and you can access it at http://localhost:8080/ by default (using embedded Tomcat).
  • Flexible. Even though most modules require minimal or no configuration, it doesn't mean that you're restricted. It's still using the Spring programming model, which means pretty much everything is configure. I have to confess that I think sometimes it can get a bit difficult to locate where to find out how to do certain things. But fortunately, Spring Framework is not an unknown framework: it's a popular framework and I think millions of developers use it on a daily basis. There are already answers on StackOverflow and forums or blogs for most common cases.
  • Stable. Spring Boot is based on Spring Framework which is very stable and mature, yet still incorporates the latest advances and features in Java technology. However, Spring Boot is built on top of Spring, and has more moving parts, meaning that it's possible that it breaks considering that it has to integrate a lot of different modules. Yet it's even easier to break your own wiring of components in a "plain Spring" app because of component incompatibility or configuration. Each Spring Boot versions recommends a particular set of components, versions, and configurations, that are known to work together, so the chances of them breaking is fairly low. In a microservice app it is even better as there should be minimal dependencies, therefore Spring Boot is a good fit.
  • Support. Spring Boot uses popular open source components like Spring Framework, Hibernate, Tomcat, so there are free articles, StackOverflow answers, and books of these available. Paid support services are also available from Pivotal and Java consultants, including enterprise support for each of the open source components.
  • Secure. By adding Spring Security module, you get default security consisting of a "user" username and automatically generated password (viewable from the app console logs). After that you can configure specific security features like JDBC user/credentials store, HTTP security, etc.
  • Easy to deploy. As mentioned above, since Spring Boot app is just a Java JAR it can be deployed on any ordinary server (via file transfer such as SSH, FTP, SFTP) and then run using "java -jar". For managed services, it is recommended to deploy it on a PaaS cloud offering such as Pivotal Cloud Foundry, Red Hat OpenShift, Heroku, and so on. There is no lock-in as Spring Boot does not require a specific platform (other than Java). You can also build Spring Boot apps as WAR and deploy them on Tomcat servlet container.
  • It's "just Spring" underneath. While there are advantages/disadvantages of using non-Java platforms like Python, NodeJS, Go, etc., when you consider Java you also consider that a lot of server-side Java programmers know Spring. There are good reasons to use Vert.x and Play framework, but Spring programmers using Spring Boot will usually have better experience resolving issues.


How to Create a Microservices App with Spring Boot

1. First you need to create a Spring Boot web app

Make sure to include the Spring Web module, as you'll need it to serve your REST API endpoints. It is recommended to include Spring Security, as most microservice will require OAuth access token, JWS token, or some other form of authentication.

2. Add a @RestController class.

Here's a simple @RestController implementation that simply returns a POJO object.

package demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    public static class Order {
        private String name;
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
    }

    @GetMapping("/order")
    public Order getOrder() {
        Order order = new Order();
        order.setName("Happy meal");

        return order;
    }
}

A @RestController may contain several service methods. Each method usually for a single HTTP method mapping (@GetMapping, @PostMapping), and for a specific path (probably with path parameters).

3. Run the app and test your service method.

Run the app. You can test your service method by visiting the service URL using web browser, for example http://localhost:8080/order in the simple example above.

I prefer using Postman to test my service APIs, which has a convenient UI. You can experiment with different parameters, save HTTP requests into a collection, and display/edit HTTP request bodies and responses with pretty syntax highlight. You'll notice with HTTP requests that accept JSON (set header Accept: application/json), Spring Boot Web automatically converts the returned object to JSON representation.

The JSON support is provided by Jackson, which is automatically configured by Spring Boot for sane defaults. You can also configure Jackson to your liking, for example to pretty print JSON (not recommended for bandwidth), add Jackson support modules such as Joda time and so on.

Next Steps

There are several functionality that is needed in a microservice app, such as connecting to SQL databases, communicating via RESTful HTTP API with other (micro)services, and executing background operations. But I hope this short tutorial can get you started on microservices development using Spring Boot. Let me know if there are specific cases I can help you with.

To learn more about Spring Boot, I highly recommend Spring Boot in Action:



Spring Boot 1.5 Tutorial: How to Create A Simple Web App

Spring Boot is a comprehensive Java application development framework. This tutorial will show you how to create a simple Java web app using Spring Boot. Spring Boot allows you to develop:
  • web applications: all from traditional, dynamic AJAX with HTML5 and JavaScript, and also server-side push
  • REST API services: you can access these servers and transfer data using JavaScript HTTP clients, AngularJS, Postman, REST API clients, and also other web servers
  • microservices: self-contained small applications that can be deployed using Docker or to Platform-as-a-Service infrastructure such as Pivotal CloudFoundry, IBM Bluemix, Red Hat OpenShift, or your own custom servers
Spring Boot 1.5 is the latest version and comes with features that make it easier to develop Java web apps compared to previous versions and especially when compared to configuring and wiring Spring applications manually.

Why Spring Boot?

The advantage of using Spring Boot is it's easy and fast to get started. Spring Boot provides most of the necessary components/dependencies and wiring them all together so you can create your app faster and deploy it in less time.

Spring Boot Modules

Spring provides many ready-to-use modules "out-of-the-box". What I mean by out-of-the-box here is not that your application will be bloated! In fact, your application will be very lean by default. However, you can add more modules as you see fit, and these modules will usually just work with your app with very little configuration. Let's see some modules that you can integrate with your app. I try to be as comprehensive as possible so let me know if I miss anything.

Core Spring Boot Modules

  • Spring Security. It allows you to secure your application via username and password credentials. This secures your web application, REST API endpoints, as well as JMX / Spring Boot Actuator endpoints. By default Spring Boot will autoconfigure a username called "user" and a random password that will be displayed on your application's console log. After that you can configure further by integrating with RDBMS database via JDBC, OAuth, or other means.
  • AOP. This provides aspect-oriented programming support via spring-aop or AspectJ. I don't really use AspectJ often but some of you may like it due to its flexibility for cross-cutting code injection support.
  • Transactions / JTA. A lot of you will be happy with built-in database Entity Manager transactional support provided by your JPA provider (default is Hibernate in Spring Boot). However if you need more, you can use Atomikos, Bitronix, or Narayana, that can provide JTA distributed transactions. This happens without the use of a Java EE app server. So you can still deploy using the self-contained Spring Boot app or to a plain "lightweight" web servlet container such as Tomcat.
  • Cache. I would avoid caching in the first stages of app development, but later on when you have many requests and you need caching support, Spring Boot allows you to integrate this functionality quickly. It can support in-memory Spring Caching and you can also configure other cache such as EHCache and JCache-compliant providers such as Apache Ignite and Hazelcast. It's possible to use Redis and memcached with some work.
  • DevTools. Some tools to make development work easy, debugging, diagnostics.
  • Configuration Processor. This module allows you to generate metadata for the configuration keys that you define yourself, other than the configuration keys already built-in from Spring Boot.
  • Validation. JSR-303 validation support using annotations. You'll need this either for JPA/document entities or for JSON REST API processing, or both. Note that by adding Web support you'll get this module too.
  • Session. Provides the API and implementations for storing and manipulating user sessions in the servlet container or better: the database. You can use standard RDBMS database but it's recommended to store session data in a fast in-memory storage such as Redis or memcached. Spring provides easy way to support Redis, which is expected as Redis has tight development relationship with Pivotal Software (although now it's somehow independent with Redis Labs).
  • Retry. Allows you to retry failed database transactions and other operations in a graceful manner.
  • Lombok. In my opinion it's a futuristic Java annotation library which allows you to perform several useful operations and structure code in a more compact and easy-to-understand way than plain Java, through constructs that feel like language extensions. I feel it's a bit risky for now but your development team may think its usefulness outweight the risks, so there's an option for you.

Web

  • Spring Web. Gives you the powerful Spring Web MVC web framework and Tomcat web server by default. You can also switch to Jetty or JBoss Undertow if you want.
  • Reactive Web. This is a future development for Spring Boot 2.0 that supports reactive web development, using Netty and Spring WebFlux. Very interesting, but if you want stability I suggest you to wait.
  • Websocket. Adds support for asynchronous server-side push interactions using Websocket technology which can also fallback to older mechanism with SockJS. STOMP via Websocket is supported as messaging protocol.
  • Web Services. SOAP is used in some enterprise environments so you can build contract-first (WSDL) SOAP web services with Spring. You can also create XML/SOAP Web Service clients with Spring (usually using proxies).
  • JAX-RS (RESTful API). JAX-RS is the Java API to write RESTful API servers and clients. Spring provides you the choice to use either Jersey or Apache CXF implementation. Note that you don't have to use JAX-RS to work with REST APIs. Spring Web already contains features that allow you to implement REST API servers and clients and you can use it as an alternative to JAX-RS. Or use both if you like (not common, but possible).
  • Ratpack. While I haven't used it but Spring Boot provides support for Ratpack framework: Lean and powerful HTTP apps for the JVM.
  • Vaadin. Vaadin is a Java web application framework that allows you to write and design web UIs similar to how you build Swing GUI apps. It abstracts the low-level details of JavaScript, AJAX, etc. so you just focus on the functionality of the app via Java code. Spring Boot provides good Vaadin integration.
  • REST Repositories. With Spring Data you can expose database entities easily from SQL DBMS databases or document databases, but still programmatically. With Spring REST Repositories support you can access these entities via REST API with minimal code. You definitely need to add Spring Security module as well, otherwise your database entities won't be secured.
  • HATEOAS. Allows you to build RESTful API services that adhere to HATEOAS principle (Hypermedia As The Engine Of Application State).
  • REST Repositories HAL Browser. Optional module that embeds a HAL Browser in your app, so you can inspect RESTful API endpoints just by using a browser. I don't really use this much as I prefer specialized tools like Postman for testing.
  • Spring Mobile. It makes development of mobile web applications simpler by providing device detection, and so on.
  • REST Docs. I have to admit I'm lousy at REST API documentation. Spring REST Docs is a tool for generating REST API documentation by combining manually written documentation and those generated automatically from API structure.
  • Stormpath. It integrates Stormpath authentication functionality with Spring Security, and provides Thymeleaf templates.

Template Engines

There are several template engines that Spring Boot supports. Thymeleaf is the one Pivotal promotes most, but you can use another template engine according to your preference.
  • Thymeleaf is the XML-based template engine with the best support with Spring MVC components.
  • Apache Freemarker. Very popular general purpose template engine that can be used well with Spring MVC.
  • Apache Velocity. Very mature general purpose template engine that also can be used with Spring MVC, though I personally prefer Freemarker.
  • Groovy Templates. You can use Groovy programming language to develop Spring Boot apps, and if so then using Groovy as the template engine may be natural to you.
  • Mustache. Template engine that is popular in the JavaScript world. In my opinion its template code looks good and with less clutter. However Mustache was not designed originally with Java in mind, so be prepared if there's lack of integration in some cases.
My favorite Java "template engine" is actually Apache Wicket, however it is not integrated by Spring Boot. However it is still possible to use Apache Wicket in Spring Boot with some configuration.

SQL Databases

Spring has excellent support for all kinds of RDBMS databases. And even those databases (and any exotic connector) not directly listed are can be supported as long as you have the proper JDBC driver.
  • JPA (Java Persistence API). This is mandatory for pretty much all web applications if you want to access the database. Spring Boot chooses Hibernate as default implementation but you can switch to EclipseLink.
  • JOOQ. JOOQ allows you to query database entities using fluent APIs.
  • MyBatis. You can also use MyBatis persistence library instead of Hibernate.
  • JDBC. JdbcTemplate support for accessing any SQL database with lower-level API.
  • JDBC Drivers: Spring Boot supports H2, HSQLDB, Apache Derby, MySQL, PostgreSQL, Microsoft SQL Server, and others.
  • Database migrations library. If you prefer a rigidly structured database migrations scheme that can potentially work across RDBMS implementations, choose Liquibase. Otherwise, Flyway will give you the most flexibility by writing RDBMS-specific SQL DDL/DML statements.

NoSQL

Spring Boot provides support for easy NoSQL database access through Spring Data project. This allows you to access NoSQL documents/entities using JPA-like object mapping and API. It makes it very quick to get started but there are also downsides to this approach: less flexibility and in some cases worse performance. That said, using Spring Data is not mandatory, you can always use the native driver/API, but this will forfeit conveniences provided by Spring Boot, like Spring Data REST Repositories support.

NoSQL databases readily supported by Spring Boot include:
  • MongoDB: You can use the standard MongoDB, or the Reactive MongoDB driver, and also use embedded MongoDB which is useful for testing.
  • Cassandra: Horizontally scalable columnar database.
  • Couchbase. Horizontally scalable database that stores documents using JSON structure and accessible via REST API as well.
  • Neo4j. Native Java graph database with good performance, indexing features, and optimized Cypher query language.
  • Redis. Fast key-value data store that works in-memory.
  • GemFire. Distributed data store supported well by Pivotal.
  • Full text search: Solr and Elasticsearch. Both search engines use Apache Lucene underneath, but the similarity end there. Both Solr and Elasticsearch are capable search engines that you can use, and Spring Boot makes it easy to integrate.

Cloud Modules

These modules allow you to connect, configure, and discover services in cloud environments such as Cloud Foundry and Amazon Web Services.

Social

Spring Boot provides integration with 3 social networks by way of Spring Social: Facebook, LinkedIn, and Twitter. With these modules, you can read posts and users from social media, and also post to Facebook wall and tweet. Before using any of these modules, you need to specify OAuth credentials and access token via application.properties configuration file.

I/O

Modules which provide enterprise integration and messaging functionality.
  • Mail (javax.mail). You'll use it in most of your apps to send email notifications to users, and you can also access POP3/IMAP inbox.
  • Message routing: Apache Camel and Spring Integration. Either of these modules allow you to integrate message routing with modular components. Spring Integration is more integrated with the Spring ecosystem, but Apache Camel is more flexible and also work very well with Spring. An advantage of Camel routes is that they can also work outside of Spring app, via a dedicated ESB such as JBoss Fuse. Camel also has Fuse IDE which allow you to design message routes visually.
  • JMS message broker. Spring Boot can support Apache ActiveMQ, Apache Artemis, and HornetQ as your preferred JMS message broker.
  • Spring Batch. Batch processing capability with an API that is also Java EE JSR-352.
  • Activiti. With this, you can integrate with BPMN workflow engine. Activiti is the BPMN engine used by Alfresco Enterprise Content Management System. Curious that Spring Boot doesn't provide built-in support for jBPM from JBoss.
  • RabbitMQ / AMQP 0.9.1. Spring Boot supports AMQP 0.9.1 message protocol that is used by RabbitMQ. Note that you also still use Apache Qpid AMQP message broker, although not so integrated.
  • Apache Kafka. Spring Kafka provides helpers to use Kafka messaging in more straightforward way.
  • LDAP. LDAP directory service protocol support. Spring Data LDAP allows you to access LDAP directory like accessing JPA entities.

Ops

  • Actuator. Actuator enables you to manage your Spring Boot application using JMX and REST APIs. Useful built-in endpoints are provided, and you're free to add custom Actuator endpoints. In addition, you can add Actuator Docs module to your Spring Boot project, to provide API documentation for these endpoints.
  • CRaSH Remote Shell (deprecated). This used to be a pretty useful functionality: you can SSH to your web application and perform maintenance tasks. Unfortunately, CRaSH project is no longer actively maintained so Spring developers decided to remove its support from Spring Boot 2.0 onwards.

Creating A Starter Web App

Now that we've known what Spring Boot modules are available, we're ready to start creating the app. Spring developers have provided Spring Initilizr, a scaffolding web app to generate a simple starter app project for you. Here's how to use it.

1. Go to http://start.spring.io and enter your project details

Go to http://start.spring.io.

Now you can enter some information about your project. These are optional but it's best that you get the names right from the first time. Renaming a project and all identifiers is not hard, but takes time and very boring.

2. Select the Spring Boot module dependencies

You can type in the autocomplete box or you can click "Switch to the full version" to get all choices so you can just tick checkboxes. I suggest you to pick: Security, Web.

I prefer to select as few dependencies as possible in the first step. Especially if you're new to Spring Boot, then a very simple first app is helpful. Adding more modules later is not complex, it's a simple matter of adding dependencies to the Maven pom.xml file. However, some modules (such as JPA for SQL database support) require application.properties configuration before you can use it. Configuring it takes simple steps, but you still have to know where to look. Unless you already know some Spring Boot configuration, it's best to leave the other modules unselected.

3. Click "Generate Project" and download the archived project

Extract the archived project inside a folder on your computer.

4. Test Running the App from Maven Command Line (Optional if you already use an IDE)

Even if you already use an IDE (which I'm sure most of you do), it's useful to know that Spring Boot projects can be run directly from the command line using Maven (if you don't have it yet, please download and make it runnable from your computer).

Use the command line, go to the Spring Boot project folder and type:

mvn spring-boot:run

For the first time, it will take some time to download Maven dependencies from the Internet. Then the app will start.
The app will show its console logs, which shows the autogenerated password (the username is "user"). You can visit the app using the browser here: http://localhost:8080/

While nothing meaningful will show up, if at least there are no errors and the web server is working well then you're good to go.

5. Import The Spring Boot Project into Your Java IDE

For convenient app development, a good Java IDE is necessary. All Java IDEs can import a Maven project easily.

Pivotal provides the Eclipse-based Spring Tool Suite IDE. However, I prefer IntelliJ IDEA from Jetbrains, which I think is a good choice if you're not sure what to pick, and there's a free Community edition available that is sufficient for simple apps. It's not a debate, any Java IDE will get the job done, they're all good. Each have strengths and weaknesses and I suggest that you get to know better with your IDE and explore alternatives that you see fit. But let's get back to the more important thing and that is to get the Spring Boot application development started.

After importing the project to the IDE, it will automatically download Maven dependencies from the Internet. You will also need to configure the JDK installed on your computer. Make sure there are no compiler or project errors.

From the IDE, you can Launch or Run the application which will display logging messages on the Console view. The logs show the autogenerated password (the username is "user"). Then you can check http://localhost:8080/ using your web browser.

Next Steps

This is just the first step but it demonstrates some important points with Spring Boot apps in general:

  • A starter app can be generated quickly with Spring Boot Initializr.
  • You don't need a servlet container or Java EE app server to run a Spring Boot app. A web server (Tomcat) is already built-in and you can run the project sources from command line using Maven.
  • Spring Boot is compatible with all Java IDEs: Eclipse, NetBeans, IntelliJ IDEA, Spring Tool Suite, even JBoss Developer Studio.
  • Spring Boot comes with convenient and sane defaults such as formatted logging using Logback. It's using the tools you may already know, preconfigured in a good way, and you still can customize if you like. But the boring little details have already been handled.
The plain empty web app needs some things to make it functional. Some things that can be added:
  • SQL Database access via JPA API and Spring Data JPA. By adding JPA and appropriate SQL driver such as MySQL or PostgreSQL, you can create database tables, insert and update rows, query for data, etc.
  • REST API Repositories. By using Spring Data API, you have the convenience of Spring Data REST Repositories, making your database entities accessible via REST APIs. Since you added Spring Security module, they're also secure by default.
  • Serve dynamic web pages with Thymeleaf/Freemarker/Velocity template engine. If you use purely client-side UI such as AngularJS, you won't need it. Otherwise, you can add a template engine such as Thymeleaf and start designing web UI, or use a component-based Java web framework such as Vaadin or Wicket.
I hope to cover tutorials for how to do these in the next articles.

Learn More

To learn more about Spring Boot, I highly recommend Spring Boot in Action:

Monday, May 1, 2017

Spring Security Support for CORS (Cross Origin Resource Sharing)

Since Spring Security 4.2, this is the proper way to make Spring Security support CORS (also needed in Spring Boot 1.4/1.5):
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
    }
}
and:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.csrf().disable();
        http.cors();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        // setAllowCredentials(true) is important, otherwise:
        // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(true);
        // setAllowedHeaders is important! Without it, OPTIONS preflight request
        // will fail with 403 Invalid CORS request
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
Do not do any of below, which are the wrong way to attempt solving the problem:
  • http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
  • web.ignoring().antMatchers(HttpMethod.OPTIONS);

To learn more about Spring Boot, I highly recommend Spring Boot in Action:



Saturday, December 27, 2014

Trying Thymeleaf for one day: Why is it so hard?

In a project that uses fully stateless server-side frontend, I tried to use Spring MVC with Thymeleaf, using Spring Boot conventions. I've been using Apache Wicket for 2-3 years already so I'm definitely new with Thymeleaf ways, but I have some experience with Spring MVC. The reason why I wanted to use Spring MVC instead of Wicket is because if the app is entirely stateless, I won't be using like 90% of what Wicket is good for (statefulness and component-based framework).

My feelings? Since it's just one day there are definitely lots of things I might be missing out... but at this point I'm somewhat demotivated by Thymeleaf. Let me explain why.

Thymeleaf is a view layer with the goals of having great HTML5 support and local previews (without server). Note that I won't be describing Thymeleaf in detail, there's introduction tutorial to Thymeleaf if you like.

Basics

The first hours are good, there's good support for string manipulation, SpEL expressions, URI manipulations, and dynamic lists are easy:

<ul>
   <li th:each="place : ${places}">
       <a th:href="|/${localePrefId}/${placeSlugs[place.id]}|" th:text="${place.name}">Baso Enggal Malang</a>
   </li>
</ul>

The ${} @{} #{} and |...| (in some cases nested) syntax looks a bit arcane to me, but I can live with them, since I can't think of a better syntax anyway.

Layouts

This is my first uneasyness: layouts aren't built-in. However, you can either integrate with Apache Tiles 2 (why Tiles 2, not Tiles 3?) or use the Layout Dialect.

I'm not familiar with Tiles, although it looks great but I went with Layout Dialect, with the gut feeling that it's more "Thymeleaf native" than the Tiles integration. Sample templates for Gigastic:

The layout - layout.html

<div layout:fragment="content">
    Hello world!
</div>

The content - city.html


<div layout:fragment="content" class="about">
    <nav>
        <ol class="breadcrumb">
...
</div>

Ok, that's great! I'm happy. :)

Amazing Surprise: Automatic <head> elements

I was trying to find out how to propagate the HTML metadata tags (<title>, <meta name="description">, etc.) from the main template through the layout so they appear on the final rendered page. Imagine my delight when it's automatic! I haven't read anything about this feature on the Thymeleaf guide, but it works out of the box and I'm excited about it!

In Wicket you'd typically do something like:

<title wicket:id="title">Gigastic: Exciting Times Together!</title>
<meta wicket:id="metaDescription" name="description" content="Wow"/>

then back it in the superclass WebPage with:

add(new Label("title", getTitleModel()));
add(new MetaTag("metaDescription", getMetaDescriptionModel()));
...
protected abstract IModel<String> getTitleModel();
protected abstract IModel<String> getMetaDescriptionModel();

Nothing hard, but in Thymeleaf I can just do:

<title>Bandung, Jawa Barat, Indonesia</title>
<meta name="description" content="Informasi daftar tempat wisata di Bandung"/>

And they'll automatically replace the values from the layout. Neat!

Note that Wicket also has <wicket:head> but it only works for adding stuff into head, not for overriding them.

The Bad: Pagination

After that it goes downwards, at least in my opinion. For pagination, Spring MVC is nice, which can resolve the pagination URI parameters (page=, size= and sort=) as Pageable object which is directly usable:

@RequestMapping(Array("id/bandung"))
def bandung(model: ModelMap, pageable: Pageable) = {
  model.put("localePrefId", "id")
  model.put("pageable", pageable)
  val places = placeRepo.findAll(pageable)
  val placeSlugs = mapAsJavaMap(places.asScala
    .map { it: Place => it.getId() -> SlugUtils.generateSegment(it.getName()) }.toMap)
  model.put("places", places)
  model.put("placeSlugs", placeSlugs)
  log.debug("placeSlugs={}", placeSlugs)
  "city"
}

The Thymeleaf template, umm... I'm quite disappointed. First I wanted to know if there's already Thymeleaf-Bootstrap library project out there, which provides ready-to-use components like Bootstrap pagination. Nope, the first hit for "thymeleaf bootstrap pagination" is Yuan Ji's March 2013 article, which feels quite recent to me, and made me sad. Because at that time Wicket-Bootstrap would already be running circles around Thymeleaf (oh, with AJAX support too)! Even Wicket's built-in PagingNavigator is way ahead of this. But here it goes:

<div class="pagination">
    <ul>
        <li>
            <span th:if="${!places.hasPrevious()}" class="disabled">Prev</span>
            <a th:if="${places.hasPrevious()}" th:href="@{${#httpServletRequest.requestURI}(page=${places.number-1})}">Prev</a>
        </li>
        <li><span th:text="${places.number+1}">1</span></li>
        <li>
            <span th:if="${!places.hasNext()}" class="disabled">Next</span>
            <a th:if="${places.hasNext()}" th:href="@{${#httpServletRequest.requestURI}(page=${places.number+1})}">Next</a>
        </li>
    </ul>
</div>

As you can see I'm too lazy to implement all of Yuan Ji's code. Also, you can see some "logic" up there in th:if, but since it's simple boolean evaluation it's a simple logic that shouldn't be a problem in a template. In AngularJS I'd have done it the same way.

One thing not in my taste is the verbosity in getting the current page URI: ${#httpServletRequest.requestURI}. But again I can live with it, since it's easy to make my own variable anyway, but I wonder why they don't make this commonly used variable use shorter alias.

Now if I'm going to write that much code just for pagination, I'd better find a way to keep a library of them and reuse it in many pages, in various ways...

Custom Reusable Components/Tag Libraries? How about Extensibility?


You wish.

Good programmers know what to write. Great ones know what to rewrite (and reuse).  - Eric S. Raymond
Please, PLEASE, PLEASE prove me wrong, but I've come to the hypothesis that in practice it's not feasible.

The Thymeleaf way of reusability/extensibility is via dialects and processors.

The terms may sound foreign, but wait until you see how to dynamically change a tag's CSS class by using a Thymeleaf processor: (I try to be nice and reduce the lines of code visually, so I remove the comments)

public class ClassForPositionAttrProcessor
        extends AbstractAttributeModifierAttrProcessor {

    public ClassForPositionAttrProcessor() {
        super("classforposition");
    }

    public int getPrecedence() {
        return 12000;
    }

    @Override
    protected Map<String, String> getModifiedAttributeValues(
            final Arguments arguments, final Element element, final String attributeName) {
        final Configuration configuration = arguments.getConfiguration();
        final String attributeValue = element.getAttributeValue(attributeName);
        final IStandardExpressionParser parser =
                StandardExpressions.getExpressionParser(configuration);
        final IStandardExpression expression =
                parser.parseExpression(configuration, arguments, attributeValue);
        final Integer position =
                (Integer) expression.execute(configuration, arguments);
        final Remark remark = RemarkUtil.getRemarkForPosition(position);
        final Map<String,String> values = new HashMap<String, String>();
        if (remark != null) {
            switch (remark) {
                case WORLD_CHAMPIONS_LEAGUE:
                    values.put("class", "wcl");
                    break;
                case CONTINENTAL_PLAYOFFS:
                    values.put("class", "cpo");
                    break;
                case RELEGATION:
                    values.put("class", "rel");
                    break;
            }
        }
        return values;
    }

    @Override
    protected ModificationType getModificationType(final Arguments arguments, 
            final Element element, final String attributeName, 
            final String newAttributeName) {
        return ModificationType.APPEND_WITH_SPACE;
    }

    @Override
    protected boolean removeAttributeIfEmpty(final Arguments arguments,
            final Element element, final String attributeName, 
            final String newAttributeName) {
        return true;
    }

    @Override
    protected boolean recomputeProcessorsAfterExecution(final Arguments arguments,
            final Element element, final String attributeName) {
        return false;
    }
}

That's not including the dialect code, and the code needed to register the dialect into SpringTemplateEngine. (which isn't much, but I'll explain later why it could be problematic)

That seems way too much ceremony and low-level just to dynamically change the CSS class. Thymeleaf definitely could use a major improvement in this area. Compare this with how we do it Wicket style: (oh yeah, baby!)

final Remark remark = RemarkUtil.getRemarkForPosition(position);
final Map<String,String> values = new HashMap<String, String>();
if (remark != null) {
    String cssClass = null;
    switch (remark) {
        case WORLD_CHAMPIONS_LEAGUE:
            cssClass = "wcl";
            break;
        case CONTINENTAL_PLAYOFFS:
            cssClass = "cpo";
            break;
        case RELEGATION:
            cssClass = "rel";
            break;
    }
    
item.add(new CssClassNameAppender(cssClass));
}

The Wicket code is just one line, unobtrusive and doesn't distract you from the main logic (which form the bulk of the code). Oh and Wicket Behaviors are crazily reusable and extensible, too!

Also of note is that Thymeleaf processors doesn't seem to support Spring dependency injection but only @Resource injection, so you have to call appCtx.getBean(...) thing. Not a dealbreaker, but it's quite inconvenient (Wicket supports Spring dependency injection in many places, and pretty much anywhere with Injector.get.inject()).

The important thing is that by using dialects/processors, you lose what Thymeleaf prides in the first place: local previewability. Not that I care about this particular feature. In Bippo, after the initial mockup phase our designers always work with the development server (since 95% things that can look wrong only happens when you put in dynamic data and behavior anyway) and close to 0% of our templates are locally previewable, even though you can make Wicket templates locally previewable if you want to. But hey, if you boast so much about local previewability but then it's gone when you try to reuse stuff (which should be common use in software development), then the feature is as good as gone in the first place.

It was scary to me at this point, then I wondered if this really how it's done in the real-world... and the horror: it is. An evidence is from popular open e-commerce software Broadleaf Commerce's ContentProcessor.java. Broadleaf uses Thymeleaf templating and they write their own dialect using "blc" prefix, and lots of processors.

In Wicket-speak this is akin to having only onComponentTag() and no behaviors, no (Generic)Panels, and no subclassing of components. Sounds cumbersome to me.

But consider that I can make a custom dialect and all the processors I want, and assuming they're quite reusable to be put in a separate library to reuse across projects... are they extensible? By this I mean is possible to subclass a processor, override a method to change its behavior, and use it easily on a few pages?

It seems not. The whole processor architecture isn't designed to be re-extensible, by that I mean it's designed to extend Thymeleaf, but not to extend a processor further. Even if you try to extend it, the primitives are too low-level to make extensibility practical. This is apparent in the "flatness" of Broadleaf Commerce's processor hierarchy: it doesn't have a class hierarchy of processor, what it has are a few base processor classes and many separate processors.

A Thymeleaf processor is so primitive it has no concept of a model (the M in MVC), let alone a typesafe version of it. Also there's no way to easily extend a processor from an imported dialect and then use it. You have to create a custom dialect which lists the extended processor and then use it. Again, such ceremony on top of ceremony. And that's still HTML, it'd be even harder to add in AJAX behaviors in a reusable and extensible way with Thymeleaf.

Wicket has Behaviors, which are way ahead than this. And it's easy to have AJAX functionality as well, extensible, and pretty much the only ceremony is .add() and new SomethingBehavior() normal Java instantiation. Behaviors aren't the only way to have reusability, the primary reusability mechanism of Wicket is its entire fleet of component hierarchy, infinitely subclassable/extensible, with probably the most common (but in no way limited to) superclass is (Generic)Panel. And you can put them in a reusable and extensible library such as Soluvas Web.

Dandelion DataTables's Thymeleaf integration is another evidence:


Not only that the Thymeleaf version still forces the developer to add required HTML markup (which probably will be duplicated in many pages), but it's actually more verbose than the older JSP taglib-based technology it's supposed to supersede. Where's the DRY?

This is the most painful revelation for me against Thymeleaf, and it's the primary reason why then I'm looking to find an alternative to Thymeleaf, but before that there are some other things.

Bootstrap (and Bootswatch, and Font-Awesome, and...) Integration... and Taglibs

Formerly I tried to find any kind of Bootstrap-Thymeleaf integration, including the usual companions like Bootswatch, Font-Awesome, and the likes. I didn't find any worth including, for reasons that was unknown to me until I found out the reusability issue (I wanted to call it design flaw but it's probably by design) above.

Thymeleaf doesn't support JSP tag libraries (JSTL), since it breaks local previewability but in JSTL's place it has processors which can do some things JSTL can do plus some but in Thymeleaf-specific way and still breaks local previewability.

Having been spoiled by Wicket Bootstrap and Wicket Stuff, this is a huge letdown. :(

So I added a bunch of webjars to my build.gradle file and links to them in my Thymeleaf templates and that's when I get to the next point...

The CDN, URI References, Webjars, JavaScript and CSS Dependencies, <head> and </body> scripts, LESS, minification, aggregation...

How do I replace these <link rel="stylesheet"> and <script src=> URIs with CDN ones in production? To be fair, this isn't Thymeleaf's fault.

A StackOverflow answer recommends using a Properties file, which is okay I guess. I prefer Wicket Bootstrap's dedicated-class-per-JS-library and typesafe-way of doing this, but not a big deal.

The bigger deal is with dependencies. In Wicket, a Component/Behavior implements renderHead() which declares external JavaScript or CSS or custom inline JavaScript. These in turn may depend on other JavaScript/CSS files that will be merged in the rendered page. No JavaScript or CSS will be included twice. And the page doesn't need to care about them.

In Thymeleaf, these are just tags. Even if I implement Thymeleaf processors, I'm not sure whether it's possible to add JavaScript/CSS files automatically, let alone manage them. wro4spring-thymeleaf-dialect seems promising, but: it's a community project (Wicket's JavaScript/CSS management is built in core), the last commit was April 2013.

Also other things like LESS, minification, aggregation. To be fair, Wicket doesn't have these LESS and minification out of the box as well, but the foundation is there including resources bundles for aggregation and the rest are provided by Wicket Bootstrap which fortunately is presently well maintained.

Conclusion: Thymeleaf, FreeMarker, or...?

As I mentioned, after using Thymeleaf for one day and hitting a roadblock on reusability and extensibility I tried to find alternatives.

Struts 2: It's probably good, but I'm content with Spring MVC and Struts doesn't solve the view layer problem.

JSF / Tapestry / Vaadin: Having used JSF 2.1 in the past, I'm absolutely sure Wicket is superior. I've used Vaadin a bit, and heard good things about Tapestry. But the thing is, if I'm looking for a component-based framework I'd just use Wicket: I've invested there, both code and knowledge.

FreeMarker / Velocity / JSP: I've heard good things about FreeMarker as a template language, and I'd love an opportunity to use it. We at Bippo have been using Mustache for hypertext templating and it's cool too. Now FreeMarker with JSP taglibs would be a step up in the reusability front compared to Thymeleaf, but I doubt it will solve the other peculiarities like resource management I mentioned above. In a way it also feels backwards because we're back to JSP-land, since actually I liked how Thymeleaf does most things (except dialects/processors), although I definitely prefer older-but-working-tech to newer-but-less-functionality any day.

The surprising (for me) conclusion is that I think Wicket is ideal for this "stateless web app" use case:
  1. I'm well-versed in Wicket
  2. Wicket and all its components and custom components are straightforward reusable, no ceremony required
  3. Extensible, again no ceremony just good old "class A extends B" + @Override elementary OO thing
  4. Has excellent out-of-the-box coverage of commonly needed functionality, such as JavaScript and CSS resource management
  5. This guy Martin Grigorov is awesome, I have 27 Wicket JIRA issues and 22 of them are resolved, usually within a few days. :)
  6. Excellent ecosystem for integration with Bootstrap, Bootswatch, Font-Awesome, LESS, and other various JavaScript libraries. And if I need to do it myself, it's easy and reusable.
  7. I'll leverage my existing knowledge and Wicket component libraries, both for stateful and stateless apps, without maintaining two separate projects with similar functionality, and two separate parts of my brain.
  8. In any case I need stateful stuff, it's there.
Note that this post is my findings plus opinions, it's not my intention to attack Thymeleaf in any way, in fact I quite liked it other than the major (and a few minor) weaknesses I outlined above. If anything isn't accurate due to my limited knowledge of Thymeleaf or you have solutions to my problems, please do let me know in the comments and I'll correct/update them. Thanks! :)

To learn more about Spring Boot, I highly recommend Spring Boot in Action:


Saturday, December 29, 2012

Setting Up logentries for OSGi Applications in Apache Karaf

What You'll Get

-->

How To

Get an account at logentries. For a start, you'll get free forever account for 1 GB of logs per month, which is cool. :-)
We need to patch leappender-1-1.5.jar by adding OSGi manifest headers and attach it as fragment to pax-logging-service. (in CentOS/Amazon Linux, jar requires java-1.7.0-openjdk-devel yum package)
wget 'https://github.com/downloads/logentries/le_java/leappender-1.1.5.jar'unzip -d leappender leappender-1.1.5.jarmkdir -vp leappender/META-INF
nano leappender/META-INF/MANIFEST.MF
Replace with:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.logentries.leappender
Bundle-SymbolicName: com.logentries.leappender
Bundle-Version: 1.1.5
Created-By: 1.7.0_09-icedtea (Oracle Corporation)
Export-Package: com.logentries.log4j;uses:="org.apache.log4j.spi";version="1.1.5"
Import-Package: org.apache.log4j,org.apache.log4j.spi
Fragment-Host: org.ops4j.pax.logging.pax-logging-service
rm -v leappender-1.1.5.bar; jar -cvfm leappender-1.1.5.bar leappender/META-INF/MANIFEST.MF -C leappender .
# Wrap it first using bnd
wget -O bnd.jar 'http://search.maven.org/remotecontent?filepath=biz/aQute/bnd/1.50.0/bnd-1.50.0.jar'
java -jar bnd.jar wrap leappender-1.1.5.jar


our appender bundle should be present in the system folder and defined in etc/startup.properties.
The system folder has a “Maven repo like” structure. So you have to copy with:

system/groupId/artifactId/version/artifactId-version.jar


In our example, it means:
mkdir -vp system/com/logentries/leappender/1.1.5/cp -v leappender-1.1.5.bar system/com/logentries/leappender/1.1.5/leappender-1.1.5.jar
and in etc/startup.properties, we define the appender bundle just before the pax-logging-service bundle:
...
org/ops4j/pax/logging/pax-logging-api/1.
7.0/pax-logging-api-1.7.0.jar=8com/logentries/leappender/1.1.5/leappender-1.1.5.jar=8 org/ops4j/pax/logging/pax-logging-service/1.7.0/pax-logging-service-1.7.0.jar=8
...
Edit Karaf's etc/org.ops4j.pax.logging.cfg :
log4j.rootLogger = INFO, out, le, osgi:*
...
# Logentries appender
log4j.appender.
le=com.logentries.log4j.LeAppender
log4j.appender.
le.Token=LOGENTRIES_TOKEN
log4j.appender.
le.Debug=true
log4j.appender.
le.layout=org.apache.log4j.PatternLayout
log4j.appender.
le.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
#
log4j.appender.le.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss ZZZ} %-5p: %F:%L %m
Note: The LOGENTRIES_TOKEN parameter can be found beside the logfile which we created earlier.
I can't get this to work automatically, so on first Karaf launch you'll get ClassNotFoundException, then you'll need to install it:
install mvn:com.logentries/leappender/1.1.5
bundle-level <id> 8
Now it should work.
At first launch you'll get a ClassNotFound exception. Shutdown Karaf and relaunch, it should work. (this was due to the leappender-1.1.5.jar in deploy/ folder, the system one still doesn't work automatically)
Happy logging! :-)
References: