• Aucun résultat trouvé

Une introduction à la technologie EJB (3/3)

N/A
N/A
Protected

Academic year: 2022

Partager "Une introduction à la technologie EJB (3/3)"

Copied!
5
0
0

Texte intégral

(1)

Une introduction ` a la technologie EJB (3/3)

1 Pr´ ealables

Il faut appliquer ces modifications1.

Conseil : Reprenez votre TP sur les EJB bas´e sur TomEE. Nous allons l’´etendre en ajoutant de nouveaux EJB et de nouveaux tests.

Pr´eparez les packages suivants :

• Cr´eez le package myapp3.services : d´efinition des services logiciels.

• Cr´eez le package myapp3.test dans le r´epertoire test.

2 Les appels asynchrones

Afin d’´eviter que des clients ne soient bloqu´es en attendant la fin d’un appel `a un EJB, nous pouvons maintenant, grace `a l’annotation @Asynchronous 2, indiquer qu’une m´ethode ou toutes les m´ethodes d’un EJB doivent ˆetre trait´ees de mani`ere asynchrone :

package myapp3.services;

import javax.ejb.Asynchronous;

import javax.ejb.Stateless;

@Stateless

public class LongWorks {

@Asynchronous

public void aLongWork() {

for (int i = 0; (i < 10); i++) { sleep(1000);

} }

private void sleep(int ms) { try {

Thread.sleep(ms);

} catch (InterruptedException e) { }

} }

Travail `a faire : Cr´eez un test unitaire afin d’appeler la m´ethode aLongWork. V´erifiez que le client n’est pas bloqu´e en testant le temps d’ex´ecution avec assertTimeout :

assertTimeout(Duration.ofMillis(20), () -> { work.aLongWork();

});

1. modifications.html

2. https ://javaee.github.io/javaee-spec/javadocs/ ?javax/ejb/Asynchronous.html

(2)

2.1 Appels asynchrones avec r´esultats

L’exemple pr´ec´edent est tr`es simple car la m´ethode ne renvoie aucun r´esultat. Dans le cas contraire, nous allons utiliser l’interface java.util.concurrent.Future 3 pour transmettre le r´esultat et permettre au client de questionner l’´etat d’avancement de l’appel asynchrone :

@Asynchronous

public Future<String> aLongWorkWithResult(String value) { sleep(5000);

return new AsyncResult<String>(value);

}

Travail `a faire :

• Utilisez la m´ethode get de l’interface Future pour r´ecup´erer, chez le client, le r´esultat de plusieurs appels `a la m´ethode aLongWorkWithResult.

• Testez, par attente active, la fin de l’appel (m´ethode isDone de l’interface Future), puis r´ecup´erez le r´esultat (m´ethode get).

2.2 Contrˆoler un appel asynchrone

Un client est ´egalement capable de demander l’arrˆet d’un traitement asynchrone (m´ethode cancel de l’inter- face java.util.concurrent.Future 4). La m´ethode m´etier va devoir, p´eriodiquement, tester cette demande comme le montre l’exemple ci-dessous :

@Resource

private SessionContext context;

@Asynchronous

public Future<String> aLongBreakableWorkWithResult(String value) { for (int i = 0; (i < 10); i++) {

sleep(500);

if (context.wasCancelCalled()) { return null;

} }

return new AsyncResult<String>(value);

}

Travail `a faire :

• Pr´evoyez un test unitaire qui va lancer un traitement asynchrone, attendre (un peu) son d´eroulement et finalement demander son interruption.

• Explorez les capacit´es de la classe @SessionContext 5.

3 S´ ecuriser les acc` es aux EJB

Il est possible de limiter l’acc`es aux m´ethodes d’un EJB `a des utilisateurs qui auraient certains profils. En voici un exemple (librement inspir´e des exemples pr´esents sur le site d’OpenEJB6) :

3. https ://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html 4. https ://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html 5. https ://javaee.github.io/javaee-spec/javadocs/ ?javax/ejb/SessionContext.html

6. http://openejb.apache.org/examples-trunk/index.html

(3)

package myapp3.services;

import java.util.LinkedList;

import java.util.List;

import java.util.Set;

import javax.annotation.security.PermitAll;

import javax.annotation.security.RolesAllowed;

import javax.ejb.Stateful;

@Stateful

public class Names {

Set<String> names = new java.util.HashSet<>();

@RolesAllowed({ "Employee", "Manager" })

public void addName(String name) throws Exception { names.add(name);

}

@RolesAllowed({ "Manager" })

public void deleteName(String name) { names.remove(name);

}

@PermitAll

public List<String> getNames() { return new LinkedList<>(names);

} }

Travail `a faire :

• V´erifiez avec un test unitaire que la m´ethode getNames est accessible.

• V´erifiez ensuite que la m´ethode addName n’est pas accessible (utilisez assertThrows de JUnit).

3.1 Authentification par un proxy EJB

Pour acc´eder aux m´ethodes prot´eg´ees nous devons nous authentifier. La premi`ere solution consiste `a passer par un EJB public qui va servir de porte d’entr´ee vers les services authentifi´es. En voila un exemple :

package myapp3.services;

import javax.annotation.security.RunAs;

import javax.ejb.Stateless;

@Stateless

@RunAs("Manager")

public class AsManager {

public void deleteName(Names names, String name) { names.deleteName(name);

} }

Travail `a faire: V´erifiez avec un test unitaire que la m´ethode deleteName de l’EJB AsManager est accessible

`

a un client non authentifi´e.

(4)

3.2 Authentification par identifiant

La deuxi`eme solution consiste `a donner un identifiant et un mot de passe. Commencez par cr´eer les deux fichiers users.properties accessible `a partir du CLASSPATH (donc dans le r´epertoire src) :

Fichiersrc/users.properties pierre=mot-de-passe-de-pierre paul=mot-de-passe-de-paul

et groups.properties :

Fichier

src/groups.properties Manager=pierre

Employee=pierre,paul

Le code du client va maintenant int´egrer la fourniture du couple identifiant/mot de passe :

@Test

public void testUserGroup() throws Exception { Properties p = new Properties();

p.put(Context.INITIAL_CONTEXT_FACTORY,

"org.apache.openejb.core.LocalInitialContextFactory");

p.put(Context.SECURITY_PRINCIPAL, "paul");

p.put(Context.SECURITY_CREDENTIALS, "mot-de-passe-de-paul");

InitialContext context = new InitialContext(p);

String name = "java:global/votre-application/votre-EJB";

final Names names = (Names) context.lookup(name);

names.addName("Votre nom");

context.close();

}

Travail `a faire :

• Testez l’acc`es authentifi´e aux m´ethodes. Faites un test pour le profil Employee et un autre pour le profil Manager.

• Dans votre EJB, interrogez l’instance de l’interface @SessionContext 7 pour connaitre l’utilisateur au- thentifi´e et testez son profil (m´ethode isCallerInRole).

4 Les timers

Je vous propose de suivre un petit exercice. Utilisation des Timers8: Cet exemple illustre le m´ecanisme destimers et l’injection de ressources.

5 Les intercepteurs

Remarque: Nous avons d´ej`a vu cette possibilit´e pour CDI. Nous pouvons ´egalement l’utiliser pour les EJB.

Il est souvent utile de pouvoir surveiller l’ex´ecution d’une m´ethode en effectuant un traitement avant et apr`es l’ex´ecution. C’est l’une des bases de la programmation orient´ee Aspect9. Nous retrouvons cette possibilit´e dans

7. https ://javaee.github.io/javaee-spec/javadocs/ ?javax/ejb/SessionContext.html 8. http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html

(5)

la norme EJB3 en d´efinissant des m´ethodes particuli`eres qui vont intercepter les appels aux m´ethodes m´etier via l’annotation javax.interceptor.AroundInvoke 10. C’est l’occasion desimplifierles m´ethodes m´etiers en d´elocalisant le code technique (trace, v´erification, sauvegarde) dans des classes de surveillance.

import javax.interceptor.AroundInvoke;

import javax.interceptor.InvocationContext;

...

@AroundInvoke

public Object interceptor(InvocationContext context) throws Exception { String methodName = context.getMethod().getName();

System.err.println("appel de " + methodName);

for (Object param : context.getParameters()) {

System.err.println("param = " + param.toString());

}

return context.proceed();

}

Ces m´ethodes sont plac´ees dans la classe `a surveiller ou dans une classe annexe (ou les deux). Dans le cas d’une classe d’interception, vous devez donner son nom avec l’annotation javax.interceptor.Interceptors 11 (il peut y en avoir plusieurs) :

package myapp3.services;

import javax.interceptor.AroundInvoke;

import javax.interceptor.InvocationContext;

public class Interceptor {

@AroundInvoke

public Object interceptor(InvocationContext context) throws Exception { ...

} }

Classe m´etier `a surveiller :

package myapp3.services;

import javax.interceptor.Interceptors;

@Interceptors({Interceptor.class}) public class LaClasseASurveiller {

...

}

Pour finir, une m´ethode pour d´econnecter la surveillance effectu´ee par une autre classe en utilisant l’annotation

@ExcludeClassInterceptors.

Mise en oeuvre: Cr´eez un intercepteur qui va calculer la temps pris par les appels aux m´ethodes m´etiers (utilisez System.currentTimeMillis()).

Références

Documents relatifs

(R.1.1) Principe d’induction math´ ematique faible.. Etant donn´ ´ e un pr´

Pour terminer, observer les variables présentes dans votre environnement (commande ls()) et supprimer l’une d’entre elles, en vérifiant le

Ecrire le processus it´ eratif de Newton pour cette ´ equation.. quel est dans ce cas l’ordre de convergence de la

Le syst` eme admet un d´ eterminant diff´ erent de 0 (il vaut − 34), il admet donc une unique solution qui est la solution nulle (et on n’a pas besoin des formules de Cramer

Dans le contexte d’enquˆ ete sur la pˆ eche sportive, la s´ election par la m´ ethode du cube semble ˆ etre une excellente alternative d’´ echantillonnage... R´

[r]

´evaluations en deux temps : (1) on r´esout d’abord le probl`eme elliptique (par la m´ethode des ´el´ements finis) pour un nombre relativement modeste de valeurs du param`etre,

L’avantage de cette deuxi`eme fa¸con de pr´esenter les choses (mais qui est bien sˆ ur ´equivalente `a la premi`ere) et qu’elle se rapproche plus de la m´ethode bien connue du