Devoxx France 2015 Jour 2 : Spring 4.1 et Java 8

devoxx_france_280px


Dans cet article, je me concentrerai sur quelques nouveautés évoquées par Juergen, celles qui m’ont semblées être les plus intéressantes ou représentatives de ce qu’apporte la dernière version de Java.

Certaines de ces nouveautés n’en sont pas vraiment, puisque Spring 4.0 est sorti il y a plus d’un an, mais une petite piqure de rappel ne fait jamais de mal.

Beans génériques

En plus de l’annotation @Qualifier, Spring traite désormais les types génériques comme une sorte de qualifier.

    @Bean
    public GenericService<Customer> myCustomerService() {...}
    
    @Bean
    public GenericService<Basket> myBasketService() {...}
    
    @Service
    public class BookStoreService {
    
    	@Autowired
        public BookStoreService(GenericService<Customer> customerService) {...}
    }

Dans cet exemple, Spring injectera le bon bean. Avant, on aurait eu droit à la fameuse exception NoSuchBeanDefinitionException: No unique bean of type ....

Injection de java.util.Optional

Java 8 a apporté une version directement intégrée à la VM du pattern “Optional” popularisé par Guava.

Spring injectera désormais le bean de type demandé si il existe, Optional.absent() sinon.

    @Autowired
    public MyBeanConstructor(Optional<GenericService<Customer>> customerService) {
        if(customerService.isPresent()) { ... }
        ...
    }

On est ici très proche du fonctionnement de @Autowired(required="false"), si ce n’est qu’avec ce dernier le champ injecté aurait été null.

Annotations

Méta annotations et surcharge d’attributs

Pour rappel, depuis la version 3, Spring permet de combiner plusieurs annotations Spring en une méta annotation :

    @Service
    @Scope("session")
    @Transactional(rollbackFor=Exception.class)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyService {}

Dans notre exemple, un bean annoté @MyService sera équivalent à un bean annoté @Service, @Scope("session") et @Transactional(rollbackFor=Exception.class).

Spring 4 permet désormais d’exposer les attributs des annotations sous-jacentes via la méta annotation :

    @Transactional
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyService {
        boolean readOnly() default "false";
    }

Ici l’annotation @MyService expose l’attribut readOnly de @Transactional. Si aucune valeur par défaut n’est précisée dans la méta annotation, l’attribut devient obligatoire.

Evidemment, cela ne fonctionne pas pour value().

Annotations multiples

Avec les annotations répétables de Java 8, il est désormais possible d’annoter plusieurs fois une méthode, une classe ou un attribut avec la même annotation :

    @Scheduled(cron="0 0 12 * * ?")
    @Scheduled(cron="0 0 18 * * ?")
    public void performCleanup() {...}

JdbcTemplate et les Lambdas

Je pense que les classes *Template étaient les plus à même de bénéficier de l’ajout des expressions lambdas à Java. Un exemple vaut mieux que mille mots, et le voici :

    JdbcTemplate jt = new JdbcTemplate(dataSource);
    jt.query("SELECT name, age FROM emp WHERE dep = ?",
       ps -> ps.setString(1, "Sales"),
       (rs, rowNum) -> new Person(rs.getString(1), rs.getInt(2))
    );

La syntaxe perd un peu de son intérèt si on a besoin de plusieurs lignes pour instancier notre objet métier, mais profite du sucre syntaxique apporté par les lambdas.

Un peu plus près des… standards !

Pour finir, Spring prends désormais en charge les annotations de la JSR 107 (mise en cache) en plus des JSR 250 et 330 sans surplus de configuration.

Un mot sur Spring 4.2

Juergen a aussi évoqué la première release candidate de Spring 4.2, attendue pour la fin du mois de mai, et celle-ci apportera les nouveautés suivantes :

  • Support d’évenements émis par le serveur en Spring MVC
  • Support CORS (Cross-origin resource sharing)
  • Support des annotations sur les méthodes par défaut des interfaces Java 8
  • Formattage et binding pour la JSR-354 (“Money & currency”)
  • Support Hibernate 5.0 (API native et JPA)
Tweet about this on TwitterShare on FacebookGoogle+Share on LinkedIn