facebook
Swapna Sagi
Support Engineer at Genuitec for MyEclipse and Webclipse products. I have been part of the Genuitec team for over 6 years.
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:

spring4blog01

spring4blog02

comparator

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.

spring4blog04

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.

spring4blog05

Examples of Spring Framework functional interfaces:

spring4blog06

spring4blog07

@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.

spring4blog08

spring4blog09

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
ComparableT -> 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:
spring4blog10

// With lambda expression
spring4blog11


Example 2:
spring4blog12

// With lambda expression
spring4blog13

 

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
spring4blog14

 

We can also pass input arguments for year, month and day to create a LocalDate instance.

//2016-04-01
spring4blog15

 

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
spring4blog16

// 18:30:30
spring4blog17

 

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)
spring4blog18

 

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
spring4blog19

// 2016-04-01 13:30
spring4blog20

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
spring4blog21

// Current time using system clock for a specific time-zone
spring4blog22

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.

spring4blog23

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:

spring4blog24

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:

spring4blog25

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:

spring4blog26

Step 2: Declare container annotation type.

spring4blog27

The full implementation would look like:

spring4blog28

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!