Posted on Nov 15th 2016
Spring Framework 4 supports Java 8 language and API features. In this article, we will focus on the new Java 8 features which are supported in Spring 4. The most important ones are lambda expressions, method references, JSR-310 Date and Time, and Repeatable annotations.
Lambda Expressions
Spring code base uses a lot of functional interfaces and with Java 8, lambda expressions can be used to write cleaner and compact code. We can supply a lambda expression whenever an object of a functional interface is expected. Let us first learn about functional interfaces before proceeding further.
Functional Interfaces
An interface which has a single abstract method can be called a functional interface. Here are some examples of JDK functional interfaces:
Comparator is functional as it has only one abstract non-Object method. Although it declares two abstract methods, the ‘equals’ is a method corresponding to the public method in Object so excluded from the count. Interfaces which have an Object class method and no non-Object method are not Functional interfaces.
The interface is functional if it has an abstract non-Object class method and extends a non-Functional interface which has only object class methods.
Examples of Spring Framework functional interfaces:
@FunctionalInterface
annotation can be used at the top of the interface declaration but it is not mandatory. This annotation is used by the compiler to detect if the interface is a valid functional interface or not. If we try to define more than one single abstract method into the interface, the compiler will throw an error.
Function Descriptors
A function descriptor of an interface is the method type of the single abstract method of the interface. The method type includes argument types, return type and the throws clause.
Examples:
Interface | Descriptor |
Runnable | () -> void |
Comparable | T -> int |
Comparator | (T, T) -> int |
interface A { void foo() throws IOException; }
interface B { void foo() throws EOFException; }
interface AB extends A, B {} | Descriptor for AB is:
() -> void throws EOFException |
interface X {
List<String> bar(List<String> arg) throws IOException, SQLTransientException;
}
interface Y {
List bar(List<String> arg) throws EOFException, SQLException;
}
interface Z extends X, Y {} | Descriptor for Z is:
(List<String>)->List<String> throws EOFException, SQLTransientException // EOFException extends IOException, and SQLTransientException extends SQLException. |
How to Write Lambda Expressions
Lambda expression syntax can be divided in three parts:
- An Arrow (–>)
- Argument list:
A lambda expression can contain zero or more arguments
Ex: () → { System.out.println(“ No arguments”); }
(String arg) → { System.out.println(“ One argument : ”+arg); }
(String arg1, Integer arg2) → { System.out.println(“Two arguments : ”+arg1+” and ”+arg2); }
- Body of the expression:
It can be a single expression or a block of code. Single expressions will be simply evaluated and returned.
Ex: (String arg) → { System.out.println(“ One argument : ”+arg); }
If the body has a statement block, then it will be evaluated as a method body and a hidden return statement will return control to the caller after the block executes.
Let’s now look at how to use a lambda expression:
Example 1:
// With lambda expression
Example 2:
// With lambda expression
You can make use of lambda expressions with Spring’s callback functions. For example, retrieving the catalog of a given JDBC connection with a ConnectionCallback can be written as follows:
jdbcTemplate.execute(connection -> connection.getCatalog())
Method References
Functional interfaces can also be implemented using method references which refer to methods or constructors without invoking them. Method references and lambda expressions are similar but method references refer to methods of existing classes whereas lambda defines an anonymous method and treats them as instances of functional interfaces.
A new package in Java 8 is added that contains functional interfaces that are commonly used for lambda expression and method reference: java.util.function.
Date Time API
There have been several problems with the existing date and time classes in Java. One of the biggest problems with the Date and Calendar classes is they are not thread safe. Developers have to take care of the concurrency problems when dealing with the date-handling code. The Date class also does not support Internationalization and hence no support for time zones. Developers have to write lot of code to support various time zones.
The Date and Time classes also exhibit poor API design. Months in java.util.Date start with 0, days with 1 and years with 1900. There is no uniformity. These and several other issues with Date and Time classes are now solved with the new Date and Time API in Java 8.
The important classes in the new Date and Time API under java.time package are LocalDate
, LocalTime
and `ZonedDateTime`.
LocalDate and LocalTime
LocalDate
represents Date with default format of yyyy-MM-dd without time. It is an immutable class. We can get the current date using the now()
method.
Examples for creating new LocalDate
instances:
//Get the current date
We can also pass input arguments for year, month and day to create a LocalDate
instance.
//2016-04-01
LocalTime
is an immutable which represents a time without the date. The default format of time is hh:mm:ss.zzz.
Examples for creating new LocalTime
instances:
//Get current time
// 18:30:30
By default the LocalDate
and LocalTime
classes use the system clock in the default time zone. These classes also provide support for timezone through the overloaded now()
method. We can pass ZoneId
to get a date in a specific time zone.
Examples:
// Current local date in Kolkata(India)
Additionally, there is one more class, LocalDateTime
which combines date as well as time with default format as yyyy-MM-ddTHH:mm:ss.zzz.
// Current date and time
// 2016-04-01 13:30
ZonedDateTime
This is an immutable class which represents date and time including time zone information. We can use an instance of this class to represent specific events like a conference in some part of the World.
// Current time using the system time and default zone
// Current time using system clock for a specific time-zone
Spring 4 ships with a conversion framework which supports all the classes that are part of the Java 8 Date and Time API. Spring 4 can take a string in the format 2016-09-10 and convert it to an instance of Java 8 LocalDate. Spring 4 also supports formatting Java 8 Date-Time fields annotated with the @DateTimeFormat
. @DateTimeFormat
declares that a field should be formatted as a date time.
Repeating Annotations
Prior to Java 8, attaching more than one annotation of the same type to a declaration or type (e.g. a class or a method) was not allowed. As a workaround, the developers had to group them together into single container annotation.
Example:
The Repeating annotations allows us to rewrite the same code without explicitly using the container annotation. Though the container annotation was not used here, the Java compiler is responsible for wrapping the two annotations into a container:
Example:
Defining Repeating Annotations
To define a repeating annotation, mark the annotation which can be repeated with @Repeatable
annotation and create an annotation which has an attribute which is an array of the repeating annotation type.
Step 1: Declare the Repeatable annotation type:
Step 2: Declare container annotation type.
The full implementation would look like:
To get the annotation information at runtime, annotate Roles with @Retention(RetentionPolicy.RUNTIME)
.
Retrieving Annotations
The getAnnotationsByType()
or getDeclaredAnnotationsByType()
are new methods in the Reflection API used to access the annotations.
The annotations can also be accessed via their container annotation using getAnnotation()
or getDeclaredAnnotation()
.
Conclusion
Spring 4 still runs with Java 6 and Java 7. Since Spring uses a lot of functional interfaces, with Java 8 and Spring 4 you will be able to use lambda expressions where there is a functional interface and write cleaner and compact code.
The new Date and Time API solves the long standing issues with the java.Util.Date class and introduces many new classes like LocalDate, LocalTime which will make date and time programming more enjoyable. Have you already adopted Java 8 with Spring 4? Please share your feedback with us on twitter at @MyEclipseIDE or on the MyEclipse forum. And, if you’re not already subscribing to our blogs, sign up today!