• 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]

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.1.1) Principe d’induction math´ ematique faible.. Etant donn´ ´ e un pr´

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

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

´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