Engineering
Releases
News and Events

Project Sagan: Upgrading to JDK 8

As I’m sure most readers are aware, Java SE 8 was released last month. In conjunction with the recent release of STS 3.5.0 and its complete support for JDK 8, we thought now would be an ideal time to upgrade Sagan to take advantage of the new language features and APIs.

Note: Not yet familiar with the Sagan project? It’s the Spring reference application that powers this blog and everything else at spring.io. Check out the first three posts in this series for more details.

Cloud Foundry’s Java buildpack has provided support for JDK 8 since the day it was released. To begin using it, we’ve created our own fork of the buildpack, bumped the JDK version from 1.7.0 to 1.8.0, and configured our Gradle build to use our fork when deploying Sagan to production.

Note: At some point in the near future, 1.8.0 will become the default version for the Cloud Foundry build pack, and the forking described will no longer be necessary.

As you may have noticed, Sagan uses Travis CI for continuous integration and deployment, and updating our Travis configuration to use JDK 8 was extremely simple.

Of course the most interesting aspect of the upgrade is the changes to the code inself. Take a look through the commits in pull request #348, where you’ll see changes broken up into several categories, including refactoring to use lambda expressions and taking advantage of JDK 8’s powerful new Stream API.

For one very simple example, it’s great to go from code like this:
java List<String> projectVersions = new ArrayList<>(); for (ProjectRelease projectRelease : project.getProjectReleases()) { projectVersions.add(projectRelease.getVersion()); }

to this:
java List<String> projectVersions = project.getProjectReleases().stream() .map(ProjectRelease::getVersion) .collect(Collectors.toList());

Or, in unit tests, from the ceremony-laden:
java mockMvc.perform(createPostRequest) .andExpect(new ResultMatcher() { @Override public void match(MvcResult result) { String redirectedUrl = result.getResponse().getRedirectedUrl(); assertThat(redirectedUrl, startsWith("/admin/blog")); } });

to the tight and readable:
java mockMvc.perform(createPostRequest) .andExpect(result -> { String redirectedUrl = result.getResponse().getRedirectedUrl(); assertThat(redirectedUrl, startsWith("/admin/blog")); });

Of course, what you see above only scratches the surface of what’s possible with streams, lambda expressions and method references in JDK 8. There are a few new concepts to learn, but you’ll be glad you did! To do so, we recommend reading Venkat Subramanian’s excellent Functional Programming in Java.

There are additional changes we can make to take full advantage of what JDK 8 has to offer, and among them is converting our uses of java.util.Date, java.util.Calendar and java.util.TimeZone to JDK 8’s new Date and Time API. We’ve created issue #360 to do just that, and if you’re interested in helping make it happen, we’d love to work with you on a pull request. Just take a look at the contributor guidelines, and let us know you’re interested in a comment on that issue.

In any case, if you’ve been curious to check out and play with the new features and APIs in JDK 8, we hope you’ll find these changes to the Sagan app a useful reference.

Note: if you already have the Sagan repository checked out locally, you’ll need to re-generate your IDE project metadata to ensure you’re working properly against 1.8-level language features. The project wiki has been updated to reflect the correct requirements and steps for doing this.

Also, for a more general overview of what’s available at both the language and API level in JDK 8, be sure to check Benjamin Winterberg’s excellent Java 8 Tutorial and Java SE 8 API Explorer.


SpringOne 2GX 2014 is around the corner

This year’s SpringOne will be in Dallas, TX on September 8-11 and super early bird registration is now open. We hope to see you there!

comments powered by Disqus