How to call EJB in PhaseListener - jsf

I use JSF 2 and EJB 3.1, all of them are deployed on Glassfish 3.1.
When i setup a class named MyInterceptor which is implemented PhaseListener, i can not revoke remote EJB interface inside it.
It notice "NullPointerException ..."
public class MyInterceptor implements PhaseListener {
#EJB(name="AuthorizationEJB",
beanInterface=AuthorizationService.class,
mappedName="corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")
public AuthorizationService authorizationService;
....
}
When I call authorizationService.dosomestuff(), it raise error NullPointerException
How can i do to fix it?
Thank in advance

In JSF 2.1 and earlier, PhaseListeners are unfortunately no injection targets (meaning you can't use injection in them). You can do your lookup programmatically via JNDI instead though.
In JSF 2.2 all JSF artifacts (including PhaseListeners) will be injection targets, but this will probably not help you now.
Unrelated to your question, but I'm not sure what you're trying to achieve by specifying the beanInterface in your annotation. Most likely you'll also don't need the name attribute and if your bean is a local bean you'll also don't need mappedName.

Use a servlet filter instead of a JSF phase listener to do authorization. You can inject an #EJB in a #WebFilter.

Yeah in web filter you could have just used plain #EJB. Maximimum you needed to add beanName if you had two beans implement same AuthorizationService interface.
Servlet filter is per request, I don't think you need to do security stuff at a certain phase from JSF's lifecycle (which is a more granular level than the whole http request).
For normal lookup you can do:
AuthorizationService.class.cast(new InitialContext().lookup("corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")).dosomestuff();
in a try catch javax.naming.NamingException

Related

JSF 2.2 inject Deltaspike (CDI) windowId into Bean

I'm currently using JSF 2.2 with Deltaspike. We use the Multi-Window-Handling from Deltaspike to handle separate windows. It works great but in a specific case, we need the window ID.
I am able to read it with:
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("dswid");
Is there a more elegant way, maybe with injection into my bean?
Regards,
Sebastian
You can use Param from OmniFaces. I find it more elegant, but it is a third libary.
#Inject #Param
private String dswid;
If you don't want to add a library, you can also inject the external context.
#Inject
private ExternalContext externalContext;

Why does my FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal() code runs to NullPointer?

I have a stateless bean which has a method, where I want to get the current/logged user.
My code to get it:
Principal p1 = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
But I am getting nullpointer exception on this. Why is that?
Or is there any other way to get the logged user?
I am using weblogic.
You're not supposed to grab the FacesContext in an EJB. Even more, your EJBs should be completely free from any JSF dependencies. In other words, you should not have any code imported from javax.faces.* package inside your EJBs. Your EJBs should be designed that way that they are reusable across all different front-ends you can think of such as JSF, JAX-RS, Struts, Spring-MVC and even "plain vanilla" Servlets.
If you're using container managed security or a security framework like Apache Shiro, then you're supposed to use the API-provided facilities for that. In case of "plain vanilla" container managed security (JAAS via web.xml and so on), you're supposed to obtain it form SessionContext (which is rightfully from javax.ejb package) which can be injected as #Resource.
#Resource
private SessionContext context;
public void doSomething() {
Principal principal = context.getCallerPrincipal();
// ...
}
An alternative would be to pass the JPA entity representation of the logged-in user as method argument.
verify the import of the following library:
javax.faces.bean.SessionScoped;
Try again

does this JSF pattern break dependency injection?

I have a JSF2 project (Mojarra on GlassFish 3.1).
I have a ViewScoped bean that references services through a utility class like so:
#ManagedBean
#ApplicationScoped
public static class ServicesUtil {
#EJB
UserService userService;
#EJB
EmailService emailService;
/** getters/setters **/
}
and
#ManagedBean
#ViewScoped
public class UserHandler {
public String method() {
ServicesUtil.getUserService().doUserStuff();
return "newPage";
}
}
My question is, since the ServicesUtil is ApplicationScoped, does that mean there is only one instance of each service for the entire application? And is this bad practice? If done correctly, would the CDI in GlassFish actually create new instances as they are needed?
Similarly, if the Services were injected into the UserHandler instead would the application be more scalable?
The reason we added the ServicesUtil layer is one of my coworkers said that he occasionally had problems getting the injection to work in the Handler when it is ViewScope. Should there be any difficulty using #EJB in a ViewScoped bean?
Any help is greatly appreciated!
Rob
The pattern you're using doesn't seem to make a lot of sense. There should be no problem with injecting EJBs into a view scoped bean.
Depending on the type of EJB you are using (stateless, stateful or singleton) different things hold.
If the userService and emailService are stateless (they most likely should be), you gain nothing by using a bean that's injected into an application scoped bean first. Namely, what's injected is not the bean itself but a proxy and every request to that is routed to a different real bean instance anyway (see http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans).
If the userService and emailService are stateful, you do get a single instance here, but I highly doubt you need to share actual between every user in your application. But even if you would want that, only a single user (thread) can access the stateful bean at a time.
If those services are singleton, you can just inject them right away into the view scoped bean. There is absolutely no reason to go via an application scoped bean.
Furthermore, ServicesUtil.getUserService() is a static method, so using this to get an injected service is brittle. If you want to use this (you shouldn't, but suppose) ServicesUtil should be injected into UserHandler.
Then, it seems you are confusing CDI and JSF managed beans. I agree this is confusing, but it's currently the way it is. #ViewScoped does not work in combination met CDI beans. From your code it's not clear if #ManagedBean is the JSF variant or the Java EE/CDI one. In this case it should be javax.faces.bean.ManagedBean if you want to use the view scope.

Injecting EJB3.0 Beans into JSF2.0 Backing Beans... Impossible?

I'm working on a JSF project on Weblogic 11g, and our initial design is calling for JSF Backing Beans to invoke EJB3.0 beans to perform business logic and data access calls. The #EJB annotation doesn't seem to work in my project when I try to inject the EJB reference to the backing bean. Whenever I hit the class that I am testing, the constructor for my EJB is never called and I end up with a NPE. Is it possible to inject an EJB3.0 bean into a JSF backing bean? Is there another way I should be invoking an EJB through the JSF Backing bean? What is the best practice?
I googled somewhat and this indeed seems to be a known issue with Weblogic. Lot of similar topics are kept unanswered.
I found this blog which confirms that #EJB in Weblogic only works for resources definied by web.xml, not for JSF. The blog describes also in detail a workaround using ServletContextListener which is IMO not much better than using JNDI.
I also found this OTN topic which confirms that #EJB in Weblogic started to work when EJB modules are not included in subdirectories (see the answer posted at the bottom, Feb 15, 2011 5:44 PM).
It turns out that it is a Weblogic specific issue when deploying anything using JSF and EJB. I found this post on the Oracle forums that explains how to get the #EJB injection working in JSF Managed Beans using Weblogic 11g:
EJB3.0 Injection into JSF Managed beans
UPDATE:
After spinning my wheels for too long, I have to give up trying to inject an EJB into a JSF ManagedBean on Weblogic 11g. Seems to work fine in Tomcat. Maybe the EJB3 and JSF implementation will be better in 12G...
To make it work you need to follow two steps:
Deploy jsf-2.0.war as LIBRARY, you can find it /ORACLE_HOME/wlserver_10.3/common/deployable-libraries
In your web project, add the reference to the jsf-2.0.war library in WEB-INF/weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.3</wls:weblogic-version>
<wls:context-root>your_context_app</wls:context-root>
<wls:library-ref>
<wls:library-name>jsf</wls:library-name>
<wls:specification-version>2.0</wls:specification-version>
<wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
<wls:exact-match>true</wls:exact-match>
</wls:library-ref>
</wls:weblogic-web-app>
I have successfully tested this in weblogic 10.3.3 and 10.3.5. If somehow this does not work, try to deploy the application as part of EAR file.
So here is the beat! There is a simple way to fix this.
Open up jsf-2.0.war under ...wlserver_10.3\common\deployable-libraries
Navigate to WEB-INF/lib and save wls.jsf.di.jar JAR somewhere
Place wls.jsf.di.jar JAR under lib folder of your WAR application.
Deploy
all should work now just by adding #EJB to property in your #ManagedBean.
There is an alternative for the #EJB annotation in order to get your local EJB bean accessible in your JSF ManagedBean web application. Considering that you have your EJB classes and your WAR packaged in the same EAR file, do the following:
configure your ejb-jar.xml to tell the weblogic expose the EJB beans to the external components;
<enterprise-beans>
<session>
<ejb-name>MyEJBBean</ejb-name>
<business-local>com.app.MyEJBBeanLocalInterface</business-local>
<ejb-class>com.app.MyEJBBeanLocalImpl</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<local>com.app.MyEJBBeanLocalInterface</local>
</ejb-local-ref>
</session>
<enterprise-beans>
Insert in the web.xml of your web application a reference to the EJB throught the ejb-link name. The ejb-ref-name is name visible for the JSF managed beans.
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.app.MyEJBBeanLocalInterface</local>
<ejb-link>MyEJBBean</ejb-link>
</ejb-local-ref>
In your JSF Managed Bean call the EJB Bean through JNDI lookup as the following:
try {
Context context = new InitialContext();
MyEJBBeanLocalInterface myEJBBean =
context.lookup("java:comp/env/ejb/MyEJBBeanLocal");
} catch (NamingException e) {
e.printStackTrace();
}
In my case I was using the Weblogic 10.3.6 (11g), JSF 2.0 and EJB 3.0 with JPA (Eclipselink)

Inject EJBs into a Seam Component

guys. I have a Seam project running on Tomcat 6.0.20 (webapp.war) and an EJB project running on JBoss 4.2.3 (ejbapp.ear).
I can access my EJBs in my Seam components using JNDI lookup [initialContext.lookup(...)].
I'd like to have them injected in my Seam components instead.
My Seam components ARE NOT EJBs, so I can't use #EJB annotation. I'd like to have something like this in my Tomcat (Web) app.
#Name("customerAction")
public class CustomerAction {
#In // even with (autoCreate=true) or the EJB name if necessary
private CustomerEJB customerEJB;
...
}
And this in the JBoss (EJB) app.
#Stateless(name="customerEJB")
public class CustomerEJBImpl implements CustomerEJB {
...
}
#Remote
public interface CustomerEJB {
...
}
In my components.xml I have the jndiPattern=ejbapp/#jndiPattern/remote specified just like I currently use to lookup the EJBs (ex: ejbapp/CustomerEJB/remote).
I'm probably missing something in my configuration to make this work.
PS: I'd like NOT HAVE to annotate my EJBs as #Name (Seam) components.
Any suggestions? Thanks in advance.
Thanks for your reply, but it didn't work.
When I declared the EJBs in components.xml, it did inject the object in my Action (Seam component), but as a POJO. I mean, the EntityManager and other EJB injections I had in the injected object didn't work.
I also tried to define the EJB as a Seam component, but, once they are in the webproject inside a JAR file, it didn't load automatically, and trying the scenario above, I got the same error.
Just an FYI, I also declared the Seam interceptor in ejb-jar.xml file.
I have no idea why this is happening, BTW I thought it would be quite a simple thing for Seam to handle.
Anyway..., any other suggestions, guys?
Define your EJB as Seam components in your components.xml

Resources