Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreAs 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:
List<String> projectVersions = new ArrayList<>();
for (ProjectRelease projectRelease : project.getProjectReleases()) {
projectVersions.add(projectRelease.getVersion());
}
to this:
List<String> projectVersions = project.getProjectReleases().stream()
.map(ProjectRelease::getVersion)
.collect(Collectors.toList());
Or, in unit tests, from the ceremony-laden:
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:
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.
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!