Bonjour,
Est il possible d'injecter un EJB dans une classe Java avec CDI ?
Si oui comment ?
Version imprimable
Bonjour,
Est il possible d'injecter un EJB dans une classe Java avec CDI ?
Si oui comment ?
Salut,
Je pense que tu peux, mais fait gaffe à ne pas mixer les annotations de déclaration et d'injection CDI/EJB (ps: par le passé j'avais déjà essayé de mixer CDI avec des annotations d'injection propres au framework JSF et j'avais eu des problèmes).
Si tu veux tu peux toujours essayer de voir ce que ça donne :
- Pour injecter un composant CDI (annoté avec @Named + Scope CDI), utilise l'annotation @Inject dans la classe où tu injectes ta dépendance.
- Pour injecter un composant EJB (annoté avec @Stateless, @Stateful ou @Singleton en fonction de ton scope), utilise l'annotation @EJB dans la classe où tu injectes ta dépendance.
Cordialement,
oui, dans le dernière spec javaEE, les annotations d'injection EJB présentent dans les Beans CDI sont respectées, et inversément. Tu peux donc aussi injecter du CDI dans un EJB. J'ai du code ici où c'est l'orgie et tout le monde y trouve son compte :mouarf:
Tu peux aussi injecter tout ça dans les Beans JSF, mais pas l'inverse il me semble.
Merci pour vos réponses,
Je suis novice avec CDI et c'est par hasard que je me suis rendu compte que je pouvais en avoir l'utilité.
J'utilise Apache Shyro pour ma Sécurité et je dois implémenter mon propre Realm qui est une classe Java, j'utilise ensuite dans cette classe une méthode provenant de mon EJB me permettant de récupérer des valeurs depuis ma DB (via JPA) mais celui ci est null.
C'est à ce moment que j'ai vu que les injection d'EJB ne fonctionnait que dans des servlet ejbs .. mais pas dans des classes java
J'avais le choix en utilisant lookup ou CDI et je trouve que CDI est beaucoup plus pratique..
J'ai cru voir que je pouvais utiliser l'annotation Produce avec un ManagerBean mais je ne sais pas si c'est vraiment adapté à mon besoin et s'il y a d'autres moyens plus simple pour faire ça.
Je ne comprend pas pourquoi d'ailleurs l'injection d'EJB ne fonctionne pas dans une classe Java ?
Fait quand même attention si tu es dans un Realm. Je ne connais pas apache Shyro, mais en général le realm se déclenche avant de rentrer dans la partie sécurisée où on trouve les EJB / Beans CDI. Du coup ton injection pourrait foirer parce qu'il n'y a pas encore de contexte accessible quand tu es dans le Realm. Ca dépend surtout de ta sécurité comment elle travaille. Si elle fonctionne au dessus du conteneur J2EE ou en dessous.
Oui je comprend, je ferais attention à ça.
Mais je suis dans l'impasse mon Realm est appelé implicitement par les méthodes des lib Shiro je ne peux pas faire autrement que d'appeler la méthode de mon EJB à moins de créer une classe DAO exprès pour cette méthode..
Je ne vois vraiment pas comment injecter mon EJB dans ma java class avez vous d'autres idées ?
Mais pourquoi ne pas utiliser la solution ultra simple de lookup JNDI ?
Pour avoir essayé Apache Shiro, je comprend Tom1x, car j'avais moi même essayé toutes les injections et les lookup possibles mais sans succès.
J'avais dû abandonner l'idée de vouloir localiser mes EJB dans le Realm de Apache Shiro. J'avais contourné cela en utilisant mon managed bean de la page d'authentification pour récupérer tout ce dont j'ai besoin dans Apache Shiro.
La présentation ci-dessous suppose l'utilisation des pages JSF pour la partie web.
Ci-dessous ma page de login (avec PrimeFaces, m'est c'est pas ça le plus important)
Le contrôleur (Managed Bean) de ma pageCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui"> <ui:composition template="/templateLogin.xhtml"> <ui:define name="body"> <p:panel class="background"> <div id="container"> <h:form> <h:panelGroup id="display" style="position:fixed;top:35%;left:40%;"> <p:panelGrid columns="1"> <p:messages globalOnly="true"/> <h:panelGrid columns="3"> <p:outputLabel for="username" value="Login :" /> <p:inputText id="username" value="#{userLoginViewController.username}" placeholder="User name" required="true" label="Username" requiredMessage="Enter the login" onkeyup="this.value = this.value.toUpperCase();"/> <h:message for="username" /> <p:outputLabel for="password" value="Password :" /> <p:password id="password" value="#{userLoginViewController.password}" placeholder="Password" required="true" requiredMessage="Enter the password"/> <h:message for="password" /> <p:outputLabel for="rememberMe" value="Remember Me:" /> <p:selectBooleanCheckbox id="rememberMe" value="{userLoginViewController.rememberMe}" /> </h:panelGrid> <p:commandButton action="#{userLoginViewController.authenticate()}" update="display" value="Login"/> </p:panelGrid> </h:panelGroup> </h:form> </div> </p:panel> </ui:define> </ui:composition> </html>
Remarque surtout l'injection de mon EJB UserFacade et la méthode getUser (Bref des choses que tu aimerais faire dans ton Realm de Apache Shiro)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 @ManagedBean @SessionScoped public class UserLoginViewController implements Serializable{ @EJB private UserFacade userFacade; /** * Creates a new instance of UserLoginViewController */ public UserLoginViewController() { } private String username; private String password; private boolean rememberMe = false; private static final Logger log = Logger.getLogger(UserLoginViewController.class.getName()); public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isRememberMe() { return rememberMe; } public void setRememberMe(boolean rememberMe) { this.rememberMe = rememberMe; } public String authenticate() { // Example using most common scenario of username/password pair: UsernamePasswordToken token = new UsernamePasswordToken(username, password); // "Remember Me" built-in: token.setRememberMe(rememberMe); Subject currentUser = SecurityUtils.getSubject(); try { currentUser.login(token); } catch (AuthenticationException e) { password = null; // Could catch a subclass of AuthenticationException if you like log.warning(e.getMessage()); FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login Failed (incorrect login or password, or user probably suspended )", e.toString())); return "/login"; } SecurityUtils.getSubject().getSession().setAttribute("username", username); return "/views/index?faces-redirect=true"; } public String logout() { Subject currentUser = SecurityUtils.getSubject(); try { currentUser.logout(); ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ec.redirect(((HttpServletRequest)ec.getRequest()).getRequestURI()); } catch (Exception e) { log.warning(e.toString()); } return null; } public User getUser(String login){ return userFacade.findUserByLogin(login); } }
Dans mon Realm Apache Shiro, j'ai la fonction ci-dessous
Je m'appui sur le contrôleur de ma page web, que je récupère dans le contexte de l'application pour utiliser les EJB que je n'arrive pas récupérer avec Apache Shiro. J'espère que tout ceci aidera..... Mon appli est en exploitation aujoud'hui quelque part :)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken; if (usernamePasswordToken.getUsername() == null || usernamePasswordToken.getUsername().isEmpty()) { throw new AuthenticationException("Authentication failed"); } FacesContext context = FacesContext.getCurrentInstance(); UserLoginViewController userLoginViewController = context.getApplication().evaluateExpressionGet(context, "#{userLoginViewController}", UserLoginViewController.class); User user = userLoginViewController.getUser(usernamePasswordToken.getUsername()); if (user == null || user.getStatutil()) { return null; } return new SimpleAccount(user.getNomUtil(), user.getMotdepas(), getName(), user.getRoles(), new HashSet()); }
le lookup jndi devrait marcher à tous les coup. C'est vrai que je ne comprend pas pourquoi tu préfère CDI. Oui tu peux injecter un EJB dans un bean CDI, mais si ton realm n'est pas un Bean CDI, tu rond, tu va devoir localiser le bean CDI et c'est un peu chiant à faire.