Cette présentation, réalisée dans le cadre de Devoxx France 2012, propose une exploration pratique des fonctionnalités de CDI et de quelques extensions Seam 3 à travers le module Seam Social (solution d'interconnexion aux réseaux sociaux).
Cassandra Java Driver : vers Cassandra 1.2 et au-delà
CDI par la pratique
1. CDI mis en pratique avec Seam
Social et Weld OSGI
par Mathieu Ancelin @TrevorReznik
et Antoine Sabot-Durand @antoine_sd
1
2. Antoine Sabot-Durand
Expert Java EE
16 ans d’expérience
Java & OSS :
Leader sur Seam Social
Commiter Apache Deltaspike
Membre de l’EG CDI 1.1(JSR 346)
@antoine_sd
2
3. Ippon technologies
SSII parisienne spécialisée en Java
Domaines de compétence
Java EE
Portail
SOA
RIA
e-commerce
Mobilité
Partenaire Devoxx.Venez sur notre Stand !
3
4. Mathieu ANCELIN
Développeur @SERLI
Java & OSS
JOnAS, GlassFish, Weld, etc ...
Membre de l’équipe du Poitou-Charentes
JUG
Membre de l’expert group CDI 1.1
(JSR-346)
@TrevorReznik
4
5. SERLI
Société de conseil et d’ingénierie du système d’information
65 employés
80% de business Java
Contribution à des projets open-source
10% de la force de travail
Membre de l’EG JSR-346
www.serli.com @SerliFr
5
6. SERLI
Société de conseil et d’ingénierie du système d’information
65 employés
80% de business Java
Contribution à des projets open-source
10% de la force de travail
Membre de l’EG JSR-346
www.serli.com @SerliFr
5
8. Abstract
La plupart des présentations CDI restent théoriques
Nous allons vous montrer comment CDI a été mis en pratique à travers le
fonctionnement du module Seam Social
Vous verrez également comment CDI peut être modularisé grâce à Weld
OSGI
Nous profiterons également de ces 3 heures pour monter une petite
application sociale en CDI et JSF / Primefaces et la même utilisant Twitter
Bootstrap
7
11. Messaging Application
Client
Container
CDI dans Java EE
Web Browser
SOA
Client Tier
JSF 2.0 CDI est une technologie d’intégration qui enrichi
aussi bien des POJO que des EJB
JAX-WS
JAX-RS
JMS
Servlet 3.0
Web Tier
Il a vocation à servir de «glue» entre les
différentes parties de la stack Java EE
EJB Container Managed Bean (POJO) C’est la première technologie qui permet
d’étendre Java EE de manière portable et
naturelle
Service Tier CDI
JTA JPA JAAS JAXB JCA
Serveur Java EE 6
10
12. Seam Social
Seam Social est un module CDI pour faciliter l’utilisation des réseaux
sociaux
Inspiré par Spring Social, il propose un noyau très différent tirant parti des
spécificités CDI
Les binding des API des réseaux sociaux, en revanche sont pour l’instant des
forks de ceux de Spring Social
Connecteurs out of the box
11
13. Inside Seam Social
Seam Social repose sur des bibliothèques tierces
comme :
Scribe-java pour le client Rest et OAuth
Jackson pour le mapping JSON
JBoss Solder, helpers CDI
12
14. Jackson
@JsonIgnoreProperties(ignoreUnknown = true)
@SuppressWarnings("unused")
abstract class TwitterProfileMixin {
@JsonCreator L’un des frameworks les plus performants pour
TwitterProfileMixin(@JsonProperty("id") String id, @JsonProperty("screen_name")
String screenName, parser du JSON
@JsonProperty("name") String name, @JsonProperty("url") String url,
@JsonProperty("profile_image_url") String profileImageUrl,
@JsonProperty("description") String description,
Jackson permet également de mapper du JSON
@JsonProperty("location") String location,
@JsonProperty("created_at") @JsonDeserialize(using =
sur des classes java
TimelineDateDeserializer.class) Date createdDate) {
} Pour ça il peut utiliser des annotations JAXB ou
@JsonProperty("notifications") ses propres annotations
private boolean notificationsEnabled;
@JsonProperty("lang") En plus Jackson propose la notion de Mixin qui
private String language;
permet de déporter les annotations sur une
@JsonProperty("statuses_count")
private int statusesCount; classe dédiée et de laisser la classe d’origine
...
propre.
13
15. Jackson : Utilisation d’un Mixin
Pojo PojoMixin
Texte Pour le Pojo que l’ont veut binder, il faut créer
une classe abstraite : un Mixin
Ce mixin comporte les annotations Jackson qui
seront utilisées pour associé le JSON au pojo
Module Un module Jackson est nécessaire pour créer
l’association
Jackson
14
17. La big picture
Tous les réseaux sociaux reposent sur REST comme protocole d’échange
Les données transmises sont au format JSON et certains proposent XML en
option
Enfin, la sécurisation (encryption et authentification) passe par le protocole
OAuth.
16
18. OAuth
OAuth est un protocole pour déléguer une autorisation à l’utilisation d’un
service donné (autoriser sans partager ses données d’accès avec l’entité à qui
on délègue l’accès au service)
Développé par Twitter, Magnolia puis Google, il est normalisé par l’IETF en avril
2010 via la RFC 5849
La version 2.0 plus simple d’utilisation est en cours de standardisation mais déjà
utilisée par certains acteurs (Facebook, Google, Microsoft)
Tous les Réseaux Sociaux s’appuient sur Oauth 1.0a ou 2.0
Pour utiliser OAuth on doit commencer par déclarer une application sur le
service concerné. Celui-ci vous délivrera une Consumer_Key (clé asymétrique)
17
19. Le cycle OAuth 1.0a
Service tiers (OAuth)
Client
Serveur de l’application
18
20. Le cycle OAuth 1.0a
Service tiers (OAuth)
Client
1
Le client demande
une ressource sur le
service tiers
Serveur de l’application
18
21. Le cycle OAuth 1.0a
Service tiers (OAuth)
Client
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le
service tiers
Serveur de l’application
18
22. Le cycle OAuth 1.0a
Service tiers (OAuth)
Le service retourne le token
Client 3
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le
service tiers
Serveur de l’application
18
23. Le cycle OAuth 1.0a
Service tiers (OAuth)
L’application
4
redirige le
client sur la
page de login Le service retourne le token
du service
Client 3
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le
service tiers
Serveur de l’application
18
24. Le cycle OAuth 1.0a
Une fois connecté le service
Service tiers (OAuth)
redirige le client vers l’URL de
callback avec un code de vérification
L’application
4
redirige le 5
client sur la
page de login Le service retourne le token
du service
Client 3
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le
service tiers
Serveur de l’application
18
25. Le cycle OAuth 1.0a
Une fois connecté le service
Service tiers (OAuth)
redirige le client vers l’URL de
callback avec un code de vérification
L’application
4
redirige le 5
client sur la
page de login Le service retourne le token
du service
Client 3
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
6 service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le A l’aide du code et du Token, le
service tiers service demande un Access Token
Serveur de l’application
18
26. Le cycle OAuth 1.0a
Une fois connecté le service
Service tiers (OAuth)
redirige le client vers l’URL de
callback avec un code de vérification
Le service retourne l’access token
L’application
4
redirige le 5
client sur la
page de login 7
Le service retourne le token
du service
Client 3
L’application demande un
1
request Token (relatif à
2 l’application déclarée) au
6 service et envoie une url de
callback à associer au token
Le client demande
une ressource sur le A l’aide du code et du Token, le
service tiers service demande un Access Token
Serveur de l’application
18
27. JSON
1: {
2: "firstName": "John",
3: "lastName" : "Smith",
4: "age" : 25,
5: "address" :
6: {
7: "streetAddress": "21 2nd Street", Javascript Object Notation : format de
8:
9:
"city"
"state"
: "New York",
: "NY", structuration de données provenant de
10: "postalCode" : "10021" Javascript et adopté comme standard d’échange
11: },
12: "phoneNumber": dans la quasi totalités des services en ligne
13: [
14: { Comparable à XML mais sans XSD
15: "type" : "home",
16: "number": "212 555-1234" Tous les langages disposent de bibliothèques
17:
18:
},
{
pour exploiter / générer du JSon
19: "type" : "fax",
20: "number": "646 555-4567"
21: }
22: ]
23: }
19
29. Objectifs de Seam Social
Fournir un socle générique pour construire des
API d’accès aux réseaux sociaux
La connexion et l’identification sont génériques
pour fournir un moyen standard de
s’authentifier
Découverte dynamique de nouveaux modules
(le socle reconnait automatiquement un nouveau
connecteur)
Fourniture de services haut niveau (bindings et
appels) vers les services en ligne
21
31. Bootstraping Social
@Twitter
@ApplicationScoped
Grace à une extension CDI incluse
dans Solder, on créé 4 beans portant
@OAuthApplication(apiKey = "FQzlQC49UhvbMZoxUIvHTQ",
apiSecret = "VQ5CZHG4qUoAkUUmckPn4iN4yyjBKcORTW0wnok4r1k",
callback = "http://localhost:8080/social-web-client/callback.jsf")
@Produces
public TwitterServicesHub twitterProducer(TwitterServicesHub service) { le même qualifier et le scope de son
return service;
} choix lié à celui du producer
@Twitter @ApplicationScoped
«interface» @Twitter @SessionScoped
OAuthService «interface»
OAuthSession @Twitter @ApplicationScoped
+getAccessToken()
«interface»
+getAuthorizationUrl()
+getRequestToken() OAuthProvider
+getVerifier()
+setRequestToken(OAuthToken)
+initAccessToken()
+getAccessToken()
+sendSignedRequest(RestVerb, String) +getRequestToken()
+setAccessToken(OAuthToken)
+sendSignedRequest(RestVerb, String, Map) +getAccessToken(OAuthToken, String)
+getVerifier()
+sendSignedRequest(RestVerb, String, String, Object) +signRequest(OAuthToken, OAuthRequest)
+setVerifier(String)
+setVerifier(String) +getVersion()
+setUserProfile(UserProfile)
+setAccessToken(String, String) +getAuthorizationUrl(OAuthToken)
+getUserProfile()
+setAccessToken(OAuthToken) +requestFactory(RestVerb, String)
+getServiceQualifier()
+sendSignedXmlRequest(RestVerb, String, String) +tokenFactory(String, String)
+isConnected()
+getSession()
+getName()
+requireAuthorization()
+sendSignedRequest(OAuthRequest)
23
32. Etendre Seam Social
Pour créer un nouveau module (supporter un nouveau réseau social) il faut :
S’assurer que Scribe-Java propose un connecteur vers ce service ou créer
ce connecteur (une classe)
Etendre AbstractSocialNetworkService pour fournir le socle aux API du
service
Créer un Qualifier (annotation) portant la meta annotation
@ServiceRelated
Implementer SocialNetworkService Hub pour les services génériques.
Il ne reste plus qu’à coder les bindings JSON et API.
24
35. CDI
La meilleur spec. de Java EE 6 (la plus cool)
#annotationsEverywhere #noXml
Typesafe
Aucune limite à ce que vous pouvez faire avec CDI
Si vous pouvez l’imaginer, vous pouvez le faire
Extensions portables standard :-)
JBoss Weld en est l’implémentation de référence
plutôt mature, très bonne communauté
Deux autres implémentations :
Apache Open WebBeans
Caucho Candi
Limité à Java EE 6 ?
et bien, pas forcément ...
27
36. Environnements for CDI/Weld
Il est possible de bootstraper Weld très simplement en dehors de Java
EE 6
à priori, vous pouvez le bootstraper n’importe où :-)
Weld-Servlet
Jetty
Tomcat 6/7
Weld-SE
Bonne vieilles applications desktop
28
39. Le Bean
En Java EE 6 tout est Managed Bean
le managed bean est le composant de base
il a un cycle de vie
il est interceptable
il est injectable
accessible via JNDI
31
42. Injection de dépendance
public class MyBean extends Application {
private HelloService service;
@Inject
public MyBean(HelloService service) {
this.service = service;
}
public void displayHello() {
display( service.hello();
}
}
34
43. Injection de dépendance
public class MyBean extends Application {
private HelloService service;
@Inject
public void setService(HelloService service) {
this.service = service;
}
public void displayHello() {
display( service.hello();
}
}
35
44. Injection de dépendance
public class MyBean extends Application {
@Inject HelloService service;
public void displayHello() {
display( service.hello();
}
}
36
45. Injection de dépendance
public interface HelloService {
public String hello();
}
public class FrenchHelloService implements HelloService {
public String hello() {
return "Bonjour tout le monde!";
}
}
public class EnglishHelloService implements HelloService {
public String hello() {
return "Hello World!";
}
} 37
46. Les qualifiers
public class MyBean extends Application {
@Inject @French HelloService service;
public void displayHello() {
display( service.hello();
}
}
public class MyBean extends Application {
@Inject @English HelloService service;
public void displayHello() {
display( service.hello();
}
}
38
49. Les qualifiers
@French
public class FrenchHelloService implements HelloService {
public String hello() {
return "Bonjour tout le monde!";
}
}
@English
public class EnglishHelloService implements HelloService{
public String hello() {
return "Hello World!";
}
}
41
51. Les qualifiers
@Language(FRENCH)
public class FrenchHelloService implements HelloService {
public String hello() {
return "Bonjour tout le monde!";
}
}
@Language(ENGLISH)
public class EnglishHelloService implements HelloService {
public String hello() {
return "Hello World!";
}
}
43
52. Les qualifiers
public class MyBean extends Application {
@Inject @Language(ENGLISH) HelloService service;
public void displayHello() {
display( service.hello();
}
}
public class MyBean extends Application {
@Inject @Language(FRENCH) HelloService service;
public void displayHello() {
display( service.hello();
}
}
44
53. Les qualifiers
public class MyBean extends Application {
@Inject @French
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements
HelloService {
}
45
54. Les qualifiers
public class MyBean extends Application {
@Inject @French @Console
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements
HelloService {
}
46
55. Les qualifiers
public class MyBean extends Application {
@Inject @French @Console @Secured
HelloService service;
}
@French @Console @Secured
public class FrenchHelloService implements
HelloService {
}
47
56. Les qualifiers
public class MyBean extends Application {
@Inject @French @Console @Secured
HelloService service;
}
@French @Secured
public class FrenchHelloService implements
HelloService {
}
48
57. Les qualifiers
public class MyBean extends Application {
@Inject @French @Console @Secured
HelloService service;
}
@French @Secured
public class FrenchHelloService implements
HelloService {
}
48
58. Injection programmatique
public class MyBean extends Application {
@Inject Instance<HelloService> service;
public void displayHello() {
display( service.get().hello() );
}
}
49
59. Injection programmatique
public class MyBean extends Application {
@Inject Instance<HelloService> service;
public void displayHello() {
if (!service.isUnsatisfied()) {
display( service.get().hello() );
}
}
}
50
60. Injection programmatique
public class MyBean extends Application {
@Any @Inject Instance<HelloService> services;
public void displayHello() {
display(
service.select(
new AnnotationLiteral()<French> {})
.get() );
}
}
51
61. Les contextes
Gestion du cycle de vie des beans
choix du moment de la création et de la destruction des beans
‘un singleton pour un contexte donné’
Contexte requête, session, conversation, application, singleton
Possibilité de créer des scopes personnalisés
via les extensions
52
78. Extensions CDI pourquoi faire ?
Une extension CDI permet :
De créer des Beans (fichier de
configuration) ou des points d’injection
modifier des beans ou des points d’injection
Annuler la création de beans
D’une manière générale inventorier
l’ensembles de l'écosystème CDI de
l’application, le modifier ou l’enrichir.
68
79. Pour comprendre les extensions
Une fois l’application lancée le BeanManager
est en lecture seule (pas de création de Bean
au runtime)
Ne pas confondre Bean (définition) avec
Instance de Bean
Nos extensions seront donc exécutées au
démarrage de l’application et devront influer
sur le contenu du BeanManager et des futurs
beans
Les extensions peuvent aussi devenir des
Beans (avec quelques restrictions)
69
80. Cycle de vie CDI
Deploy Process Process Before Undeploy
Application Beans Producers Shutdown Application
Process
Before Bean Process Application
Observer
Discovery Injection Taget Running
Methods
After
Scan Process After Bean
Deployment
Archive Anotated Types Discovery
Validation
70
81. Pour Faire une Extension CDI
Créer une classe qui implémente Extension avec un
constructeur sans paramètres
Y placer une ou plusieurs méthodes avec un observer sur
les événements du cycle de vie CDI pour intervenir sur le
contenu du bean manager
Ajouter dans le classpath le fichier
META-INF/services/javax.enterprise.inject.spi.Extension
dans lequel on ajoutera le nom qualifié de la classe
d’extension
71
82. Exemple simple : @Veto
<X> void processAnnotatedType(@Observes final ProcessAnnotatedType<X> pat, BeanManager beanManager) {
final AnnotatedType<X> annotatedType = pat.getAnnotatedType();
final Class<X> javaClass = annotatedType.getJavaClass();
final Package pkg = javaClass.getPackage();
// Support for @Veto
if (annotatedType.isAnnotationPresent(Veto.class) || (pkg != null &&
pkg.isAnnotationPresent(Veto.class))) {
pat.veto();
log.info("Preventing " + javaClass + " from being installed as bean due to @Veto annotation");
return;
}
}
72
83. Exemple simple : @Veto
<X> void processAnnotatedType(@Observes final ProcessAnnotatedType<X> pat, BeanManager beanManager) {
final AnnotatedType<X> annotatedType = pat.getAnnotatedType();
final Class<X> javaClass = annotatedType.getJavaClass();
final Package pkg = javaClass.getPackage();
// Support for @Veto
if (annotatedType.isAnnotationPresent(Veto.class) || (pkg != null &&
pkg.isAnnotationPresent(Veto.class))) {
pat.veto();
log.info("Preventing " + javaClass + " from being installed as bean due to @Veto annotation");
return;
}
}
72
85. Et OSGi ?
Seam Social est un projet open source
Et nous comptons sur vous pour créer des modules
Seulement ajouter un module nécessite de redéployer l’application
Comment faire pour charger un module à chaud ?
OSGi arrive à la rescousse pour résoudre ce problème
74
87. OSGi
Plateforme modulaire et dynamique pour Java
Très stable et puissante mais APIs vieillottes ...
Plateforme Java
76
88. OSGi
Plateforme modulaire et dynamique pour Java
Très stable et puissante mais APIs vieillottes ...
Module
Plateforme Java
76
89. OSGi
Plateforme modulaire et dynamique pour Java
Très stable et puissante mais APIs vieillottes ...
Lifecycle
Module
Plateforme Java
76
90. OSGi
Plateforme modulaire et dynamique pour Java
Très stable et puissante mais APIs vieillottes ...
Service
Lifecycle
Module
Plateforme Java
76
91. OSGi
Plateforme modulaire et dynamique pour Java
Très stable et puissante mais APIs vieillottes ...
Bundles
Service
Lifecycle
Module
Plateforme Java
76
118. Weld-OSGi
(Essaye d’être) le meilleur des deux mondes
dynamique, typesafe, utilisation d’annotations, etc ...
Extension CDI permettant d’utiliser le modèle de programmation CDI dans OSGi
Pas besoin de connaître OSGi
faire disparaitre le modèle de programmation OSGi en faveur de celui de CDI
modèle de programmation standard
... mais reste compatible
81
119. Weld-OSGi
Un projet JBoss Weld
besoin de démarrer Weld dans un environnement OSGi
expérimentations à faire sur la compatibilité des modèles de programmation
Développé par l’équipe R&D SERLI
Mathieu ANCELIN & Matthieu CLOCHARD
82
142. Modulariser ‘Socializer’
module-twitter
Registre
social-api module-linkedin Socializer.war
OSGi
le O SGi
module-facebook
B und
88
143. Modulariser ‘Socializer’
module-twitter
le O SGi Registre
social-api module-linkedin
B und Socializer.war
OSGi
le O SGi
module-facebook
B und
88
144. Modulariser ‘Socializer’
le O SGi
module-twitter
B und
le O SGi Registre
social-api module-linkedin
B und Socializer.war
OSGi
le O SGi
module-facebook
B und
88
145. Modulariser ‘Socializer’
le O SGi
SGi module-twitter
B und
und le O
B
le O SGi Registre
social-api module-linkedin
B und Socializer.war
OSGi
le O SGi
module-facebook
B und
88
146. Modulariser ‘Socializer’
le O SGi
SGi module-twitter
B und EB
und le O p pli. W
B A
le O SGi Registre
social-api module-linkedin
B und Socializer.war
OSGi
le O SGi
module-facebook
B und
88
147. API commune
public interface SocialProvider {
String getName();
UserProfile getUserProfile();
OAuthService getOAuthService();
List<Post> getTimeline();
void post(Post post);
}
89
149. Construire les modules sociaux
Module OSGi pour wrapper la librairie cible (twitter, facebook, etc ...)
ajout de quelques classes pour permettre l’intégration via Weld-OSGi
aucun export de package nécessaire
nous allons exposer un service via un type de l’API commune
import des packages des librairies utilisées ainsi que de l’API commune
91
150. Exposer les modules
Chaque module ‘Social’ va se charger d’exposer un Service type
‘SocialProvider’
à travers le registre de services OSGi
à disposition des autres bundles Weld-OSGi
à disposition des autres bundles OSGi
utilisable par d’autres applications
92
151. Publication des SocialProviders
• Publication par déclaration
@Publish
@ApplicationScoped
public class TwitterSocialProvider implements SocialProvider {
...
}
93
152. Publication des SocialProviders
• Publication par déclaration
@Publish
@ApplicationScoped
public class TwitterSocialProvider implements SocialProvider {
...
}
• Publication dynamique
@Inject Instance<SocialProvider> instance;
@Inject ServiceRegistry registry;
SocialProvider service = instance.get();
Registration< SocialProvider > reg = registry.register(service);
...
reg.unregister();
94
153. Récupération des Posts depuis
‘Socializer’
Chaque module ‘Social’ expose un service OSGi permettant d’accéder au
Posts qu’il manipule
‘Socializer’ doit consommer ces Posts pour les afficher dans son interface
différentes méthodes possibles
privilégions une approche générique
95
154. Injection de services
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
96
155. Le rôle de l’extension
Vraisemblablement, le bean correspondant à ‘@OSGiService SocialProvider
provider’ n’existe pas dans l’application cliente
Au démarrage de l’extension CDI, Weld-OSGi va scanner tous les points
d’injection
recherche tous les PI utilisant @OSGiService et créé des beans
correspondant
cependant n’écrase pas les beans existant pour que l’application continue à
fonctionner comme doit, tout n’est pas censé être OSGi-ifié
97
156. Le rôle de l’extension
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
@Inject @OSGiService
MyService service;
98
157. Le rôle de l’extension
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
@Inject @OSGiService
InjectionPoint
MyService service;
98
158. Le rôle de l’extension
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
create()
@Inject @OSGiService
MyService service; Provider InjectionPoint
98
159. Le rôle de l’extension
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
P
get() create()
R
@Inject @OSGiService
MyService service; O Provider InjectionPoint
X
Y
98
160. Le rôle de l’extension
Injection de service dynamique
@Inject @OSGiService SocialProvider provider;
provider.getTimeline(); // échoue si aucun service disponible
Extension
CDI
P
get() create()
R
@Inject @OSGiService
MyService service; O Provider InjectionPoint
X
Y
98
161. Le rôle de l’extension
provider.getTimeline()
P
R
O registre de
X services
Y OSGI
99
162. Le rôle de l’extension
provider.getTimeline()
P
R
O registre de
X services
Y OSGI
99
163. Le rôle de l’extension
provider.getTimeline() get()
P
R
O registre de
X services
Y OSGI
99
164. Le rôle de l’extension
provider.getTimeline() get()
P
R
O registre de
service
X réel services
Y OSGI
99
165. Le rôle de l’extension
provider.getTimeline() get()
P
R
O getTimeline() registre de
service
X réel services
Y OSGI
99
166. Le rôle de l’extension
provider.getTimeline() get()
P
R
O getTimeline() registre de
service
X réel services
Y OSGI
unget()
99
167. Injection de services
Injection programmatique - whiteboard pattern (comme Instance<T>)
@Inject Service<SocialProvider> providers;
for (SocialProvider provider : providers.first()) {
provider.getTimeline(); // appel sur 0-1 service
}
for (SocialProvider provider : providers) {
provider.getTimeline(); // appel sur 0-n service(s)
}
providers.get().getTimeline(); // peut échoué car non dynamique
providers.size();
providers.isUnsatisfied();
providers.isAmbiguous();
100
168. Injection de services
@Inject Service<SocialProvider> providers;
public List<Post> getTimeline() {
List<Post> timeline = new ArrayList<Post>();
for (SocialProvider provider : providers) {
timeline.addAll(provider.getTimeline());
}
Collections.sort(timeline, new Comparator<Post>() {
public int compare(Post post1, Post post2) {
return post1.timestamp().compare(post2.timestamp());
}
});
return timeline;
}
101
169. Et si on souhaite un service en
particuliers ?
@Publish
@Twitter
public class TwitterSocialProvider implements SocialProvider {
...
}
102
170. Et si on souhaite un service en
particuliers ?
@Publish
@Twitter
public class TwitterSocialProvider implements SocialProvider {
...
}
@Inject @OSGiService
@Filter("(twitter=true)") SocialProvider service;
103
171. Et si on souhaite un service en
particuliers ?
@Publish
@Twitter
public class TwitterSocialProvider implements SocialProvider {
...
}
@Inject @Filter("(twitter=true)")
Service<SocialProvider> service;
104
172. Et si on souhaite un service en
particuliers ?
@Publish
@Twitter
public class TwitterSocialProvider implements SocialProvider {
...
}
@Inject @Filter("(twitter=true)")
Service<SocialProvider> service;
@Inject @OSGiService @Twitter SocialProvider service;
105
173. Et si on souhaite un service en
particuliers ?
@Publish
@Twitter
public class TwitterSocialProvider implements SocialProvider {
...
}
@Inject @Filter("(twitter=true)")
Service<SocialProvider> service;
@Inject @Twitter Service<SocialProvider> service;
106
174. Des services requis ...
Avoir une application dynamique est intéressant, mais parfois il est
absolument nécessaire d’avoir un certain service pour que tout fonctionne
Weld-OSGi vous prévient lorsque des services requis sont disponibles
peut fonctionner de manière globale pour tous les services requis du
bundle
peut cibler des services requis en particulier
107
175. Des services requis ...
Bean A
Bean B
service validation
de dépendances
Weld-OSGi
registre de
services OSGi
108
176. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis
service validation
de dépendances
Weld-OSGi
registre de
services OSGi
108
177. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis
service validation
Extension
CDI
de dépendances
Weld-OSGi
registre de
services OSGi
108
178. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis
service validation
Extension
CDI
de dépendances enregistrements/
Weld-OSGi désenregistrements
registre de de services
services OSGi
108
179. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis
service validation
Extension
CDI
de dépendances notifications enregistrements/
Weld-OSGi désenregistrements
registre de de services
services OSGi
108
180. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis évènements de validation
des dépendances
service validation
Extension
CDI
de dépendances notifications enregistrements/
Weld-OSGi désenregistrements
registre de de services
services OSGi
108
181. Des services requis ...
Bean A
Bean B
enregistrement d’un
service requis évènements de validation
des dépendances
service validation
Extension
CDI
de dépendances notifications enregistrements/
Weld-OSGi désenregistrements
registre de de services
services OSGi
108
182. Des services requis ...
@Inject @OSGiService @Required @Twitter SocialProvider twitter;
@Inject @OSGiService @Required @Facebook SocialProvider facebook;
public void start(@Observes Valid evt) {
System.out.println("Les SocialProviders sont disponibles");
twitter.getOAuthService().connect();
facebook.getOAuthService().connect();
}
public void stop(@Observes Invalid evt) {
twitter.getOAuthService().disconnect();
facebook.getOAuthService().disconnect();
System.out.println("Les SocialProviders sont indisponibles");
}
109
183. Des services requis ...
@Inject @Required @Twitter Service<SocialProvider> twitter;
@Inject @Required @Facebook Service<SocialProvider> facebook;
public void start(@Observes Valid evt) {
System.out.println("Les SocialProviders sont disponibles");
twitter.get().getOAuthService().connect();
facebook.get().getOAuthService().connect();
}
public void stop(@Observes Invalid evt) {
twitter.get().getOAuthService().disconnect();
facebook.get().getOAuthService().disconnect();
System.out.println("Les SocialProviders sont indisponibles");
}
110
184. Des services requis ...
let
@Inject @Required @Twitter Service<SocialProvider> twitter;
p
@Inject @Required @Facebook Service<SocialProvider> facebook;
o m
public void start(@Observes Valid evt) {
System.out.println("Les SocialProviders sont disponibles");
c
twitter.get().getOAuthService().connect();
e
facebook.get().getOAuthService().connect();
l
}
nd
public void stop(@Observes Invalid evt) {
u
twitter.get().getOAuthService().disconnect();
b
facebook.get().getOAuthService().disconnect();
System.out.println("Les SocialProviders sont indisponibles");
}
111
185. Des services requis ...
@Inject @OSGiService @Required SocialProvider provider;
public void start(@Observes @Specification(SocialProvider.class)
ServiceAvailable evt) {
System.out.println("Au moins un SocialProvider est disponible");
provider.getOAuthService().connect();
}
public void stop(@Observes @Specification(SocialProvider.class)
ServiceUnavailable evt) {
System.out.println("Aucun SocialProvider disponible");
}
112
186. Des services requis ...
@Inject @OSGiService @Required Service<SocialProvider> provider;
public void start(@Observes @Specification(SocialProvider.class)
ServiceAvailable evt) {
System.out.println("Au moins un SocialProvider est disponible");
provider.get().getOAuthService().connect();
}
public void stop(@Observes @Specification(SocialProvider.class)
ServiceUnavailable evt) {
System.out.println("Aucun SocialProvider disponible");
}
113
187. Les notifications OSGi
OSGi génère de nombreuse évènements pour pouvoir interagir avec les
couches bundle et services
meilleur moyen de gérer le côté dynamique du framework
Evènements disponibles :
bundle events
service events
114
188. Les notifications OSGi
Va permettre à notre application de savoir lorsqu’un nouveau service
est disponible
géré de manière asynchrone, pas besoin de vérifier ‘à la main’
permet d’afficher une notification à l’utilisateur lui demandant de se
connecter
utilisation des servlets asynchrones ?
115
202. Inter-bundles events
Synchronisation des timelines de manière planifiée
Appelé depuis un EJB avec @Schedule
Récupération des timelines de manière asynchrone
Mise en cache pour des raisons de performances
Envoi des nouveaux ‘Post’ vers l’application cliente pour une mise à jour en
temps réel
127
211. Le futur de Weld-OSGi
Intégration dans Weld core (en cours)
Plugin Forge
CDI Extension pour les serveurs Java EE hybrides
utiliser Weld-OSGi dans une application Java EE
en cours ;-)
Intégration avec les spécifications entreprise
une future spécification OSGi entreprise ?
135
212. Informations sur le projet
Code du projet
https://github.com/mathieuancelin/core/tree/weld-osgi/environments/osgi
Documentation du projet
http://mathieuancelin.github.com/weld-osgi/
136
213. Seam Social et son futur
Seam Social est forkable sur github :
http://github.com/seam/social
Si vous êtes intéressés par Socializer (branche ‘Twitter Bootstrap’ incluse) :
https://github.com/antoinesd/Socializer
Seam Social dépasse le simple cadre d’un module CDI
Une tentative de JSR a été conduite mais rejetée
Un projet « Java Social » est en cours de constitution
Une communauté s’est constituée. Pour ceux que ça intéresse suivez
@antoine_sd ou @Java_social
137
214. Le mot de la fin
CDI c’est bien mangez-en
OSGi est beaucoup plus sympathique que vous ne le pensez
Surtout avec Weld-OSGi
Seam Social c’est cool mais le sera encore plus avec vous comme
contributeur.
138