HTTP Cache

Caching is a powerful mechanism to increase application performance and to improve user-experience. There exist caches at each level of the application, i.e. at the database, in the application server and at the client. It generally applies, the closer the data can be kept at the client, the better the performance. However, not all caches are equally well known. The http cache is a browser cache  with which data is directly kept at the client and is probably the fewest known cache. The following shows how to configure this cache with a simple Restful service with Spring Boot. See Increasing Application Performance with HTTP Cache Headers for a more detailled description of the http cache.

The following code snippet shows a simple RestController which returns „Hello World!“ two seconds later after the service has been called. Furthermore, the Cache-Control in the http header is set to max-age =5. This tells the web browser that this response can be kept for 5 seconds in the cache before it is discarded.


@RestController
public class HelloController {
@RequestMapping("/hello")
public String sayHello(HttpServletResponse response) throws InterruptedException {
response.setHeader("Cache-Control", "max-age=5");
TimeUnit.SECONDS.sleep(2);
return "Hello World!";
}
}

view raw

HelloController

hosted with ❤ by GitHub

That’s all. If you start the application and call http://localhost:8080/hello you will see „Hello World!“ after a delay of two seconds. If you call the service again, the reponse appears immediately as it is was cached this time. This works quite well with IE. However, Chrome automatically sets Cache-control: max-age=0 on the request’s header if you’re refrehsing the page. This obviously prevents the data from being cached. To test the correct caching behavior in Chrome anyway, one can create a dummy HTML page with a link to the service and then calling the service via this link. If you are opening the dev tools in your browser and inspect the response headers, you should see that the Cache-Control is correctly set:

httpcache
Response header

If Spring Security is enabled and you are experiencing problems with the cache, try to disable the cache-control header in the security configuration:


@Configuration
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/hello").permitAll()
.anyRequest().authenticated();
http.headers().cacheControl().disable();
}
}

view raw

SecurityConfig

hosted with ❤ by GitHub

The whole project can be found here: http-cache-demo

Implementing Serializable?

When does it makes sense to implement Serializable? Should we implement it for all domain classes or only in certain cases? This is a question that has popped up repeatedly in my previous projects and I would like to answer it in this article. But first, let’s have a look at what Serializable actually does and what it is meant for without going into the details.

Serialization is the conversion of an object into a sequence of bytes. This enables to store data on disk or to transmit it across the network from one running JVM to another. Deserialization is the reverse conversion, i.e. the reconstructing objects from  a series of bytes. In Java, the serialization mechanism is built into the platform, but you need to implement the Serializable interface to make an object serializable. By implementing this interface, it marks the class to be serializable.

But why are not all java classes Serializable by default? Making a class serializable comes with certain costs:

  • Assume you implemented Serializable for a class in your application in production. Clients are working with this class version and are storing some objects to disk. After a certain time, your class is changed and released again. What happens if the customer is trying to deserialize an object of the old class version? Yes, clients will experiences program failures. Implementing Serializable restricts the future flexibility. Once you released a serializable class, you are required to support the serialized form forever.
  • Serialization can also lead to security problems. By being able to serialize any object it has a reference to, a class can access data it would not normally be able to (by parsing the resultant byte data).
  • Serialization also increases the testing burden as you must ensure the proper functioning of the application with all your class versions.

There are other issues, such as the serialized form of inner classes not being well defined. Making all classes serializable would exacerbate these problems. Although it is very easy to make a class serializable, it should be well thought out, when this should be done. In today’s business applications, mostly a web- or restful-service is used for remote communication. Thus, there is mostly no need to implement Serializable.

Assertion Frameworks

In a recent project, although some JUnit tests were available, but the readability of these tests was rather bad. In my view, there were two reasons that caused this poor readability: Firstly, the tests were far too long. The tests were neither short nor precise. Too many things have been attempted to test in a single test. Secondly, one has no assertion framework used as Hamcrest or AssertJ. It has been limited to the usual JUnit assertions, which has not contributed to the readability and finally maintainability of the tests.

Assertion frameworks have different objectives. Generally, they increase the readability of tests. Assertions of these frameworks are more expressive. This means more conditions can be checked in less code.  Therefore tests are easier to understand. Moreover, these frameworks provide better error messages. In case of a test failure, it is not only said that the test is failed, but a precise error message is issued saying why the test was not successful. In addition, such frameworks provide a lot of flexiblilty. It is possible to create your own matcher allowing to write precise assertions for your own classes. Last but not least, these frameworks provide common patterns of assertions, which leads to an easy usage.

Hamcrest and AssertJ are both assertion frameworks that help to check conditions in tests. Both frameworks have the objective to make tests as readable as possible. Currently, Hamcrest is still more widespread and well-known, not least because this framework exists longer and is bundled with JUnit. However, AssertJ is evolving rapidly and is catching up with Hamcrest. Since Spring Boot’s version  1.4.0.M2 it is packed within the spring-boot-starter-test dependency.

Let me give you an example how to use these frameworks. Given is the String „Developer“ on which we want to perform several assertions. Let’s start how to do this with JUnit:


public class JUnitStringAssert {
private static final String DEV = "Developer";
@Test
public void testString() {
assertNotNull(DEV);
assertFalse("".equals(DEV));
assertTrue(DEV.startsWith("Dev"));
assertTrue(DEV.contains("elo"));
assertEquals(9, DEV.length());
}
}

That is the way with JUnit most developers are familiar with. However, the assertions of JUnit are quite limited and mostly not really readable. This often means that you longer have to think about what is actually tested.

A better way offers Hamcrest whose assertions are more expressive:


public class HamcrestStringAssert {
private static final String DEV = "Developer";
@Test
public void testString() {
assertThat(DEV, is(notNullValue()));
assertThat(DEV, not(isEmptyString()));
assertThat(DEV, startsWith("Dev"));
assertThat(DEV.length(), equalTo(9));
}
}

Hamcrest provides more powerful assertions and make them easier to read and understand. However, personally I didn’t find it that easy to get started with Hamcrest. Note that in Hamcrest, the expected and actual values are reversed compared to JUnit. While JUnit expects the expected value always as the first argument, Hamcrest expects it as the second argument.

An even better alternative and in my opinion the most elegant and easiest way to perform assertions provides AssertJ:


public class AssertJStringAssert {
private static final String DEV = "Developer";
@Test
public void testStrings_WithAssertJ() {
assertThat(DEV).isNotNull().isNotEmpty().startsWith("Dev").contains("elo").hasSize(9);
}
}

The assertions of AssertJ are even more readable and are the most extensive. The framework provides a fluent api which makes it really simple and intuitive to use. Assertions can be read from left to right like a normal sentence. Furhermore, AssertJ provides the most meaningful failure messages, is actively developed and community driven, has strong Java 8 support and lots of examples makes it simple to get started.

First Post

This is my first blog post.

I’ve often thought about to create an own blog. Today is finally the day when I put this idea into action.

The content will focus on my experiences in Software Engineering from my projects. Firstly, I would like to share my thoughts and ideas about technologies, tools, problems and their solutions. Secondly, I’ll try  to write some general posts concerning the social aspects of a project, as this should not be less interesting in the life of a software engineer.

I look forward to go this way and I hope that I will find enough time in the future to publish some posts here. Stay tuned.