Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Sunday, February 10, 2013

How to: scan interfaces in a custom Spring namespace

This article does not aim to address how to build a custom Spring namespace, to do so, Spring documentation integrates Extensible XML authoring. But a way to create a proxy based on a interface.
My first idea was to use Spring component-scan to find my annotated interfaces, and to proxy it via a BeanPostProcessor or something similar, but it cannot works because component-scan can only be used to load implementations and BeanPostProcessor as well.
As I'm using a custom namespace, so a parser, I made some research through Spring namespace elements and I found the attribute: base-package. And one of its associated class: ClassPathScanningCandidateComponentProvider. By extending this class, my annotated interfaces can be found, and the parser will be in charge to create the proxy around these interfaces.
The scanner implementation is quiet simple:

static class MyAnnotComponentProvider extends ClassPathScanningCandidateComponentProvider {

        public MyAnnotComponentProvider() {
            super(false);

            addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class, false));
        }

        @Override
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return beanDefinition.getMetadata().isInterface();
        }
    }

  1. The constructor defines a scanner without any filter by calling the super constructor with false
  2. Add a filter on the annotation to found in the classpath by using AnnotationTypeFilter. The second argument specifies only the search must include meta annotation or not.
  3. Based on the BeanDefinition, isCandidateComponent must must check if the found bean is elligible
Next, use it as follow:

ClassPathScanningCandidateComponentProvider componentProvider = new MyAnnotComponentProvider();
componentProvider.setResourceLoader(parserContext.getReaderContext().getResourceLoader());

final String basePackage = element.getAttribute("base-package");
Set < BeanDefinition > beans = componentProvider.findCandidateComponents(basePackage);
  1. Instanciate the scanner, and give it a ResourceLoader. In a Spring XML parser, it can be reached by ParserContext
  2. Get the package to parse by, for example, get the value of the base-package attribute
  3. Call the method findCandidateComponents to get a Set of BeanDefinition.

Tuesday, May 17, 2011

Annotation scanner with Spring

Spring framework, from version 2.5, can retrieve bean based on an annotation set such as @Service, @Repository. This mechanism uses an annotation scanner to retrieve the annotated classes through the classpath.

As Spring is easily extendable, it is possible to work with an annotation scanner dedicated to our own annotations.

The annotation

The annotation we want to use as a class marker, is not a psecial Spring define one. The only requirement is the retention must be runtime and the target must be at least TYPE.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation { }

The scanner

Firstly, we need to create an application context:

GenericApplicationContect applicationContext = new GenericApplicationContext();

And now, the annotation scanner:

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext, false);

An annotation scanner needs an application context to store retrieved classes. The second parameter is used to avoid this scanner search after Spring framework defined annotations. Now, we must configure the scanner to retrieve only our annotation:

scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnotation.class));

Several filters are available to include or exclude classes from the search, such as RegexPatternTypeFilter.

To trigger the scanning, we must call scan method with a package list as string array:

scanner.scan(packageNames);

Now, just refresh the context and get the annotated instance:

applicationContext.refresh();
Map<String, Object> result = applicationContext.getBeansWithAnnotation(MyAnnotation.class);

The map key is the bean Spring id, and the value is an instance. By default, the id is the simple class name.

Thursday, November 18, 2010

Devoxx 2010 daily notes: day three

Java SE Keynote

Java platform is now targeting:

  • productivity
  • performance
  • universality
  • modularity
  • integration

Java language evolution will be:

  • for generics: declarations like: HashMap<String, List<String>> map = new HashMap<String, List<String>>(); will become: HashMap<String, List<String>> map = new HashMap<>();
  • lambada expressions will be added (JDK 8)
  • type reification: primitive type will be used as generics
  • module will be added: based on descriptor (module-info.java) and manage by JMOD (integration with maven and its repositories)
  • module will be able to be package as RPM, JAR or DEB or directly managed by JMOD

Java evolution has been planned until 2030.

For the roadmap:

  • Java 7: end of july 2011 (project coin, fork/join framework)
  • Java 8: end of 2012

Java Persistence 2.0

JPA 2.0 brings some news:

  • Criteria API
  • pessimistic lock
  • metamodel API
  • standardize configuration
  • collections of basic types

Basic types collections:

  • @ElementCollection: this collection must be stored as an elmeent collection
  • @CollectionTable(...): specify the table name
  • @Colcumn(...): specify the collection column name

Embadable objects:

  • multi level (@AttributeOverride)
  • relationship (@AssociationOverride, @JoinTable)

Persistence order:

  • implemented by provider as an additional column (@OrderColumn)
  • in case of legacy use @OrderBy to use existing schema

Maps usage:

  • key: basic type, embeddable, entity
  • value: basic type, embeddable, entity

JPQL:

  • conditional expression: CASE ... THEN .. (usefull with map)
  • restriction on type TYPE(e) IN (...) (usefull for inheritance)

Criteria API: support object and strinf literals

  • CriteriaQuery: query description
  • CriteriaBuilder: criteria query objects factory
  • How to express: select c from Customer
    CriteriaQuery cq = criteriaBuilder.createQuery(Customer.Class);
    Root root = cq.from(Customer.class);
    cq.select(root);

Metamodel: abstract schema model.

Pessemistic lock: specify mode as properties.

Second level cache API: use of @Cacheable on properties

Standardized configuration by providing a set of default properties.

Validation: automatic validation for PrePersist, PreUpdate and PreRemove.

The Next Big JVM Language

Actually, languages challenge Java by providing more features and different expression ways (have a look to Stephen Colebourn).

What Java has done right:

  • simplify C++ migration
  • take old ideas but JVM make them popular (garbage collector for example)

What Java has done wrong:

  • Checked exception: how to ignored them?
  • primitives: split type system
  • arrays: split type system and expose JVM future
  • monitors: unsafe effects, difficult to optimize
  • static: cannot be override, hurt concurrency
  • method overloading: complexity for compiler and for programmer
  • generics: too complex, background compatibility result in erasure

The New Big JVM Language should be:

  • like C syntax
  • multi paradigm: object oriented and functional
  • type system: static typing
  • easy reflection
  • have properties
  • have closure in language core
  • a better null handling (avoiding NullPointerException and long and borring debugging)
  • thread not exposed
  • have modules
  • good tooling (make tooling esay to build)
  • extensible (combination of language feature)
  • not verbose

No JVM languages fullfil these criteria, so, perhaps it is time for a none backward compatible version of Java: Java 9?

Project Lambda: To Multicore and Beyond

The based of Lambda project is SAM types: interfaces or abstract classes with a single abstract method.

Closure take the following syntax:

#{Person.getLastName()}

Collection framework will be adapted to provides facilities based on closure, such as filtering, sorting, etc...

New key words will be added to define immutable classes and their properties:

value class ImmutableClass {  
properties String lastname;
}

Actually, modifying an interface results to breaking API compatibility. With Lambda, it will be possible to add method with default behavior.

Spring 3.1 - Themes and Trends

Spring 3.0 brings:

  • annotated component model
  • expression language
  • REST support
  • Portlet 2.0
  • support Java EE 6 (JPA 2)
  • custom annotation
  • include JavaConfig (configuration classes)
  • @Value (use of value express with EL)
  • model validation @Valid on parameters
  • type conversion @DateTimeFormat(iso=ISO.DATE)
  • annotation scheduling: @Scheduled

Spring 3.1 will provide:

  • environment profiles
    • activated in command line by: -DspringProfile=env
    • provides environment abstraction as an API
    • custom placeholder resolution
  • java based configuration: @Configuration on class
  • cache abstraction
    • EhCache support (important for cloud)
    • support for Gemfire, Coherence
    • annotation @Cacheable
    • cache could be conditional
    • @CacheEvict to avoid caching
    • new namespace declaration
  • conversation management:
    • HttpSession ++
    • association with browser and tabs
    • foundation for WebFlow 3
  • Groovy will be used as template engine
  • c: namespace for constructor arguments
  • Roadmap:
    • M1 in december
    • 3.1 GA march/april 2011

HTML 5 Websockets: A New World of Limitless, Live, and Wickedly Cool Web Applications

Actually, HTTP is not full duplex, so, Websockets brings full duplex to web.

It is implemented as a Javascript API that uses IETF protocol, but is still compatible with HTTP. The idea is not to replace HTTP.

Websocket allowed cross origin, secured and unsecured communication in standard.

It is supported by browsers:

  • Chrome 4.0+
  • Safari 5.0, iOS 4
  • Firefox 4 beta
  • to check compatibility, go to Websocket web site

Beyond the scene, Websocket allows:

  • connection reuse
  • extends client server protocol (available in JS API)
From the tests, Websocket, compared to pure HTTP, reduce latency from 150 ms to 50 ms.

Visage Android Workshop

Visage is a dynamic UI language inspired by Flex and JavaFX for different target, and especially, for Android.It is declarative, brings data binding, provides closure to implements triggers and brings null safety.

Compilation is divided in two phases:

  • Visage to Java bytecode
  • Bytecode to Dalvik

Friday, July 16, 2010

Spring 3 et Rest

C'est seulement depuis la version 3.0 de Spring que le MVC supporte les services Rest. Biensur, le framework intègre les principales implémentations tel Jersey ou Restlet, mais dans la partie concernant les web services. La décision d'ajouter une implémentation Rest dans Spring MVC vient de l'orientation prise par le framework:

  • les méthodes des contrôleurs fournissent des vues en résultat
  • des annotations trés similaires à celles de Rest permettent:
    • le binding d'une URL vers un contrôleur
    • le binding des paramétres vers les arguments des méthodes d'un contrôleur

Configurer l'application web

Pour commencer, il faut déclarer le DispatcherServlet dans le fichier de configuration de l'application web: web.xml.

<web-app>

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/app-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>

</web-app>

En lui spécifiant le paramètre contextConfigLocation, la servlet va charger le context Spring a sa création. Le fichier de context se trouve: /WEB-INF/spring. La servlet doit mapper toutes les URLs du type:

<app_context>/services/*

Configuration Spring

La configuration Spring se fait en deux fichiers différents:

  • le context principal, le fichier app-config.xml, qui contient la configuration du backend: DAO, services et mappers.
  • le context MVC, dans le fichier mvc-config.xml, qui contient la configuration... du MVC.
<beans xmlns="<a class="external free" title="http://www.springframework.org/schema/beans" rel="nofollow" href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>"
xmlns:xsi="<a class="external free" title="http://www.w3.org/2001/XMLSchema-instance" rel="nofollow" href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>"
xmlns:mvc="<a class="external free" title="http://www.springframework.org/schema/mvc" rel="nofollow" href="http://www.springframework.org/schema/mvc">http://www.springframework.org/schema/mvc</a>"
xsi:schemaLocation="
<a class="external free" title="http://www.springframework.org/schema/beans" rel="nofollow" href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a>
<a class="external free" title="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" rel="nofollow" href="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">http://www.springframework.org/schema/beans/spring-beans-3.0.xsd</a>
<a class="external free" title="http://www.springframework.org/schema/mvc" rel="nofollow" href="http://www.springframework.org/schema/mvc">http://www.springframework.org/schema/mvc</a>
<a class="external free" title="http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" rel="nofollow" href="http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd</a>">

<mvc:annotation-driven />

</beans>

Cette configuration permet d'utiliser l'annotation @Controller pour déclarer les beans gérés par Spring MVC.

Implémentation d'un contrôleur

L'exemple suivant se base sur la gestion d'objets SampleBean:

public class SampleBean {

private String name;
private long id;
}

Et utilise le SampleController pour effectuer une recherche par id sur les SampleBean.

@Controller
@RequestMapping("/sample")
public class SampleController {

@RequestMapping(value="{id}", method=RequestMethod.GET)
public @ResponseBody SampleBean get(@PathVariable long id) {
return persistence.get(id);
}
}
  1. L'annotation @RequestMapping("/sample") sur la classe permet de mapper toutes les requêtes du type /services/sample sur ce contrôleur. /services étant l'URL sur lequel le DispatcherServlet est mappé.
  2. L'annotation @RequestMapping(value="{id}", method=RequestMethod.GET) sur la méthode get spécifie cette méthode sera appelé pour toutes les URL pouvant mapper avec /services/sample/4 pour les requêtes dont la méthode est GET.
  3. L'annotation @PathVariable permet de spécifier que l'une des valeurs ente {} de l'URL doit être mapper sur cette variable.
  4. @ResponseBody permet de déclarer que la valeur de retour de la méthode sera renvoyer dans le corps de la réponse. Reste à le convertir dans un format quelconque.

Mapper le résultat vers un format spécifique

Pour mettre en place la convertion, il faut configurer un bean de type ContentNegotiatingViewResolver. En Rest, l'opération de mapping des valeurs de retour et des paramètres vers des objets s'appel: négociation. La négociation se fait en ce basant sur la valeur du header Accept de la requête. Pour cet exemple, le mapping se fera vers du JSon. le header Accept aura donc pour valeur: application/json. Spring fournit parmis ces dépendances, le parseur Jackson, qui est utiliser dans ce qui suit:

 <bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>

La configuration se fait en spécifiant les formats supportés avec l'attribut mediaTypes et les implémentations des mappers ave la propriété defaultViews. La propriété mediaTypes correspond au contenu du header Accept de la requête reçu par le DispatcherServvlet.

Intégration Spring Flex

Spring Source a présenté l'année dernière à SpringOne, son projet d'intégration Spring et Flex, Spring Flex. Ce projet veut simplifier la mise en place d'un backend Spring derrière BlazeDS, le message broker free de Adobe. L'exemple suivant décrit les fichiers de nécessaires pour une configuration standard avec des Remote Object.

Fichier Maven

Le plugin utilisé pour compiler Flex est FlexMojos.
Sans passer par l'intégration de Spring Flex, il faut déclarer chaque jar BlazeDS comme dépendance, ce qui fait une demi douzaine de dépendances au total, Adobe n'ayant pas géré les dépendances entre les modules de BlazeDS.
Le fichier Maven de Spring Flex référence tous les modules nécessaires de BlazeDS.

<dependency>
<groupid>org.springframework.flex</groupid>
<artifactid>spring-flex</artifactid>
<version>1.0.3.RELEASE</version>
<type>jar</type>
<scope>runtime</scope>
</dependency>

Cette version de Spring Flex est dépendante de la version 2.5.6 de Spring.

Structure du WAR

L'application est configurée pour utiliser les répertoires suivant sous le répertoire WEB-INF:
  • conf: configuration SpringFlex
  • flex: configuration BlazeDS
  • spring: configuration vers le backend

Déclaration dans le fichier web.xml

La configuration de Spring se fait en utilisant les fonctionnalités de Spring MVC. Le chargement du context Spring se fait en déclarant les contextes du backend a charger et le listener de chargement.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*-context.xml
</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Ensuite, le DispatcherServlet est déclarer pour matcher toutes les requêtes vers le message broker. Il doit être initialisé avec un fichier de contexte Spring configurant l'intégration SpringFlex.

<servlet>
<servlet-name>flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/web-application-config.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

Configuration de BlazeDS

La configuration de BlazeDS passe par le fichier de contexte Spring utilisé par le DispatcherServlet: /WEB-INF/config/web-application-config.xml. Il ne fait que déclarer la configuration du message broker. Dans notre cas, la configuration par défaut est suffisante.
Le message broker est configurer pour charger le fichier de configuration des services BlazeDS
dans: WEB-INF/flex/services-config.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">

<flex:message-broker/>

</beans>

C'est dans ce fichier que l'on pourra déclarer les Remote Object.

Le fichier des services BlazeDS est réduit au minimal pour une configuration standard. Dans notre cas, il n'est pas nécessaire d'avoir d'autres fichiers de configuration.
Il suffit de déclarer le channel par défaut et de le configurer.

<services-config>

<services>
<default-channels>
<channel ref="my-amf">
</default-channels>
</services>

<channels>
<channel-definition id="my-amf"
class="mx.messaging.channels.AMFChannel">
<endpoint
url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint" />
</channel-definition>
</channels>
</services-config>

Déclaration des Remote Object

SpringFlex offre deux façons de déclarer des Remote Object:
  • Par configuration
  • Par annotation

Par configuration

Le namespace flex apporte l'élément remoting-destination qui permet de référencer un bean Spring et de l'exposer comme Remote Object. L'attribut ref permet de référencer un bean par son id. Et l'attribut destination-id permet de déclarer le nom du Remote Object coté Flex. Par défaut, destination-id est égale à l'id du bean.

<flex:remoting-destination id="userService" ref="userService"/>

Par annotation

L'annotation RemotingDestination de SpringFlex permet de déclarer au niveau de la classe d'un bean, qu'il doit être exposé à Flex via le message broker. Elle permet également de déclarer la destination, mais par défaut, il s'agira du nom du bean avec la première lettre en minuscule.
Cet approche couple directement les beans du backend à la technologie du frontend, ce qui, dans le cas d'un changement de technologie web, obligera les développeurs à garder des dépendances inutiles.