Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

What is New in Spring Framework 4 for Java 8

In this article we will see whats new in the new version of Spring Framework 4, created based on Java 8 specification.

Java 8 brought new developments in language and library and many of them are already supported by Spring 4.x. Some of the new features of Java 8 has no impact in Spring and can be used as is, while others need a specific support Spring to be used. This article presents these new features of Java 8 that are supported by Spring 4.x.

Spring 4 supports Java 6, 7 and 8

The code compiled with Java 8 generates a class file that requires at least one virtual machine (VM) Java 8. Once Spring uses a lot of reflection and bytecode manipulation with libraries as ASM, CGLIB, it was important to ensure that these tools to be able to understand these new bytecode files. For this, Spring Framework now maintains embedded form ASM libraries, and other CGLIB using jarjar (https://code.google.com/p/jarjar/), so that the distribution Spring always have a set predictable libraries that work with Java bytecode in versions 6, 7 and 8, ensuring that errors will not happen at runtime.

Spring Framework is built with Java 8 with the command-line option to produce bytecode Java 6. So, you can compile and run applications using Spring 4.x with Java 6, 7 and 8.

Spring and Lambda Expressions in Java 8

The designers of Java 8 ensured backward compatibility, so that lambda expressions Java 8 can be used with code compiled with previous versions. This compatibility was achieved through the concept of functional interfaces.

Basically, the designers analyzed several existing Java code snippets and realized that most Java developers used interfaces with a single method representing the idea of a function. For example, the following lists of JDK Spring interfaces and that only use a single method - also known as "functional interface".

Listing 1. Functional JDK interfaces

 public interface Runnable {
    public abstract void run();
}
 
public interface Comparable {
    public int compareTo(T o);
}

Listing 2. Functional interfaces of Spring framework

 public interface ConnectionCallback {
  T doInConnection(Connection con) throws SQLException, DataAccessException;
}
 
public interface RowMapper
{
  T mapRow(ResultSet rs, int rowNum) throws SQLException;
}

Lambda expressions can be used in Java 8 anywhere that a functional interface is passed as a parameter or returned by a method. For example, Spring JdbcTemplate class contains a method with the following signature:

 public  List query(String sql, RowMapper rowMapper)
  throws DataAccessException

Note that the second argument of the method is a type RowMapper interface. With Java 8 may be used a lambda expression as a value for this argument.

Instead of writing such a code:

Listing 3. Long and bad way to code.

 jdbcTemplate.query(“SELECT * from products”, new RowMapper(){
  @Override
  public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
    Integer id = rs.getInt(“id”);
    String description = rs.getString(“description”);
    Integer quantity = rs.getInt(“quantity”);
    BigDecimal price = rs.getBigDecimal(“price”);
    Date availability = rs.getDate(“available_date”);
 
    Product product = new Product();
    product.setId(id);
    product.setDescription(description);
    product.setQuantity(quantity);
    product.setPrice(price);
    product.setAvailability(availability);
 
    return product;
  }
});

It can be written the following code:

Listing 4. Faster and better way to code.

 jdbcTemplate.query("SELECT * from queries.products", (rs, rowNum) -> {
    Integer id = rs.getInt("id");
    String description = rs.getString("description");
    Integer quantity = rs.getInt("quantity");
    BigDecimal price = rs.getBigDecimal("price");
    Date availability = rs.getDate("available_date");
 
    Product product = new Product();
    product.setId(id);
    product.setDescription(description);
    product.setQuantity(quantity);
    product.setPrice(price);
    product.setAvailability(availability);
 
    return product;
});

This second version of the code using lambda expressions is much more compact and lighter than the first version using anonymous classes.

Present all the details of functional interfaces of Java 8 is beyond this article and it is highly recommended that the reader understands the details of functional interfaces in a more appropriate reference. The key point is that lambda expressions Java 8 can be passed to methods compiled with Java 7 or earlier if the methods accept a functional interface.

Spring code contains several functional interfaces and thus lambda expressions can be easily used with Spring. Even though Spring is compiled with Java 6 class format it is still possible to write applications using lambda expressions Java 8, compile them with Java 8 and run it in a VM Java 8 that everything will work.

Finaly, since Spring Framework uses functional interfaces before Java 8 formalize this concept is easy to use lambda expressions with Spring.

Spring 4 and the Date and Time API of Java 8

The Java developers lament long deficiencies in class java.util.Date and finally with Java 8 there is a new date and time API that solves these problems. This new API by itself would already have its own article, so it will not be covered in detail here.

Spring brings a conversion framework is able to convert strings to dates. Spring 4 updates the conversion framework to support classes that are part of the new Date and Time API Java 8. Therefore, it is possible to write the following code:

Listing 5. ExampleController class.

@RestController
public class ExampleController {
 
  @RequestMapping("/date/{localDate}")
  public String get(@DateTimeFormat(iso = ISO.DATE) LocalDate localDate)
  {
    return localDate.toString();
  }
}

Note that in the above example the get method parameter is the type LocalDate Java 8 and Spring 4 is able to pick up a string as 2014-02-01 and convert it to an appropriate instance. It is important to mention that Spring is often used with other libraries like Hibernate to persist data and Jackson to convert objects to JSON.

While Spring 4 supports date library of objects and time of Java 8, it does not mean that third-party frameworks are also able to do this treatment.

Spring 4 and the repeated annotations

Java 8 added support for repeated annotations and Spring 4 also recognizes this functionality. In particular, Spring 4 accepts the repeated annotations @Scheduled and @PropertySource. See an example of use of @PropertySource in the code below:

Listing 6. Example of use of @PropertySource

 @Configuration
@ComponentScan
@EnableAutoConfiguration
@PropertySource("classpath:/example1.properties")
@PropertySource("classpath:/example2.properties")
public class Application {
 
            @Autowired
            private Environment env;
 
            @Bean
            public JdbcTemplate template(DataSource datasource) {
                        System.out.println(env.getProperty("test.prop1"));
                        System.out.println(env.getProperty("test.prop2"));
                        return new JdbcTemplate(datasource);
            }
 
            public static void main(String[] args) {
                        SpringApplication.run(Application.class, args);
            }
}

Java 8 Optional<> and Spring 4.1

Failure to check null references is a common problem in application code. One way to eliminate the NullPointException is to ensure that the methods always give back a non-null value. For example, consider the following interface definition:

Listing 7. CustomerRepository interface.

 public interface CustomerRepository extends CrudRepository {
   /**
    * Returns the customer to a specific id or
    * Null if the value is not found
   */
   public Customer findCustomerById(String id);
}

A developer can implement CustomerRepository with a possible failure by the following code:

Customer customer = customerRepository.findCustomerById(“123”);
customer.getName(); // cause NullPointerException

instead of writing the following more secure code:

Customer customer = customerRepository.findCustomerById(“123”);
if(customer != null) {
  customer.getName(); // prevents NullPointerException
} 

The ideal here is that the compiler can report the problem if we can not verify that a value can be null. The java.util.Optional class makes it possible to write the interface follows:

 public interface CustomerRepository extends CrudRepository {
  public Optional findCustomerById(String id);
} 
Therefore, the version of the code containing possible failures will not compile and the developer must explicitly determine whether an Optional contains a value or not as follows: Listing 8. Checking wether Optional is valuable.
Optional optional = customerRepository.findCustomerById(“123”);
if(optional.isPresent()) {
   Customer customer = optional.get();
   customer.getName();
}

The main idea of the Optional is to ensure that the developers know that a method can return a null value, or they can pass a null value for a method without having to read the Javadoc. The method signature and the compiler will help make it clear that a value is Optional. A more detailed description of the Optional class idea can be found here.

Spring allows the use of 4.1 Option two ways. The @Autowired annotation contains an attribute 'required' that can be used as follows:

Listing 9. MyService class.

@Service
public class MyService {
 
    @Autowired(required=false)
    OtherService otherService;
 
    public doSomething() {
      if(otherService != null) {
        // use another service
      }
   }
}

and it can be replaced by:

Listing 10. New MyService class.

 public class MyService {
 
    @Autowired
    Optional otherService;
 
    public doSomething() {
      otherService.ifPresent( s ->  {
        // use "s" to do something
      });
    }
}

Other Optional point where it can be used with Spring MVC in which it may indicate that a parameter of a method that handles requests is optional. For example:

 @RequestMapping(“/accounts/{accountId}”,requestMethod=RequestMethod.POST)
void update(Optional accountId, @RequestBody Account account)

inform the Spring that accountId is optional.

In short, the Optional class Java 8 makes it easy to write code with fewer NullPointException and Spring works perfectly with this class.

Parameter name discovery

Java 8 introduces support for keeping at runtime the name of the method arguments. This means that Spring 4 can extract the names of methods, making it the most compact SpringMVC code. For example:

@RequestMapping ("/ Accounts / {id}")
Public Account getAccount (@PathVariable ("id") String id)

It can be written as:

@RequestMapping ("/ Accounts / {id}")
Public Account getAccount (@PathVariable String id)

Note that the @PathVariable("id") annotation was replaced by @PathVariable because Spring 4 can get the name of the argument "id" from the compiled code. The Java compiler 8 saves the name of the arguments in the class files if it runs with the "-parameters". Before Java 8, Spring was able to extract the parameter names of the compiled code if the code was compiled with the "-debug".

Even the Java 7 the "-debug" does not preserve the parameters names in abstract methods. So for a project like Spring Data that automatically generates repositories implementations based interfaces that caused problems. Consider the following interface:

Listing 11. CustomerRepository interface.

 interface CustomerRepository extends CrudRepository {
  @Query("select c from Customer c where c.lastname = :lastname")
  List findByLastname(@Param("lastname") String lastname);
} 

The need of the @Param("lastname") at the signing of findByLastname is needed even with the "-debug" to the Java 7 because the parameter names are not preserved because findByLastname is an abstract method. With Java 8 the "-parameters" allows Spring Date discover the parameter names in the abstract methods so that the interface can be rewritten as follows:

interface CustomerRepository extends CrudRepository {
  @Query("select c from Customer c where c.lastname = :lastname")
  List findByLastname(String lastname);
}

Note that it is not the most necessary @Param("lastname") to make it less verbose code and easier to read. When using Java 8 is a good idea to compile your code with the "-parameters"

Conclusion

Spring 4 works with Java 6, 7 and 8 and as a developer you can write your application using any of these versions of Java. If you are using Java 8 may then make use of lambda expressions to write a cleaner and more compact code in places that there is a functional interface. Since Spring uses various functional interfaces then there are several opportunities to use lambda expressions.

Java 8 brings an improved version of some libraries, such as the new java.time package and the Optional class that Spring is able to use them to write a code easier to write and easier.

Finally, compile the code with Java 8 with "-parameters" preserves the name of the arguments in the methods and makes it possible to write a more compact code in methods that meet requests in Spring MVC and query methods Spring Data.

If you are ready to use Java 8 in your projects, you can find in Spring 4 a good option that makes use of the features of Java 8.



Web developer and passioned for web design, SEO and front end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login