I want to get my current loggin User in my EJB Container.
I built an CDI - EJB Webapplication with Shiro for Security.
My problem is now, in my EJB Class the sessionContext is everytime "anonymous"
#Resource
private SessionContext sessionContext;
String userEmail = sessionContext.getCallerPrincipal().getName();
I donĀ“t know, set Shiro this automaticly or should I set sessionContext?
Can anybody help me?
The problem is the connection from CDI ---> EJB or why is it "anonymous"
#Resource is not context-aware. You want to use #Inject instead.
Related
This question already has answers here:
Removing specific CDI managed beans from session
(2 answers)
Closed 1 year ago.
How I invalidate a specific bean in a session?
I have this example code.
I test with ExternalContext.invalidateSession(); but it destroy all beans in the session in the application since it destroys the full session.
#Named
#SessionScoped
class Managed implements Serializable {
public void invalidate (){
// lines //
externalContext.invalidateSession();
}
}
but, with invalidateSession all beans in the session are destroyed, I want to invalidate only the one specific "Managed" bean, how I do that?
Ignoring the fact that you're not clear on how you want to implement this solution, to start
Inject the BeanManager into wherever you plan to execute the logic. It has to be a managed component
#Inject
BeanManager beanManager;
The bean manager is the component that will grant you access to all the CDI beans (and other stuff) within your context.
You then use the BeanManager to get a contextual reference to the bean you're interested in
Bean<Managed> bean = (Bean<Managed>) beanManager.resolve(beanManager.getBeans(Managed.class));
Managed managedBean= (Managed) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)
managedBean = null; //or whatever you want to do with it
This solution should destroy the active instance of that session bean; if another attempt is made to use that same bean, CDI will most likely create a brand new instance on-demand
While the approach with BeanManager is viable, I would suggest slightly different approach.
You should be able to #Inject HttpSession into your managed #SessionScoped bean and then invoke invalidate() on that session.
Something along these lines:
#Named
#SessionScoped
class Managed implements Serializable {
#Inject
HttpSession session;
public void invalidate (){
session.invalidate(); //invalidates current session
}
}
Yet another way to achieve this is to make use of FacesContext. You were on the right track but you need to take one extra step:
((HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true)).invalidate();
I'm developing a real time application. I have websockets and application scoped managed bean. I'm trying to access the application scoped managed bean from a websocket but I can't. Is this possible?
This is my websocket and managed bean (application scoped):
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
#ManagedProperty(value = "#{aplicacion}")
private Aplicacion aplicacion;
...
And my "Aplicacion" managed bean:
#ManagedBean(eager = true)
#ApplicationScoped
public class Aplicacion implements Serializable {
...
If I try to access in Mediador class to de managed property "aplicacion" it's null so I get a NullPointerException.
Thanks
This is really not right.
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
WS (JSR-356 WebSocket) API and JSF API are completely independent from each other. They know nothing from each other and won't take mixed annotations from each other into account.
Effectively, you end up with two instances of the class. One as a WS managed server endpoint as available by ws://.../mediador, and one as a JSF managed bean as available by #{mediador}. The #ManagedProperty is only recognized by JSF managed bean facility and it'll work in the JSF managed bean instance only.
Use CDI instead. It works across the entire Java EE web application. Not only in WebSocket endpoints, but also in JSF managed beans, WebServlets, WebFilters, WebListeners, JAX-RS resources, JAX-WS resources, etcetera. Eventually, JSF managed bean facility will be deprecated in favor of CDI. This will happen in Java EE 9 or perhaps already 8.
#ServerEndpoint("/mediador")
public class Mediador { // Shouldn't be serializable!
#Inject
private Aplicacion aplicacion;
// ... (no getter+setter needed!)
}
#Named
#ApplicationScoped // javax.enterprise.context
public class Aplicacion { // Shouldn't be serializable!
// ...
}
Unrelated to the concrete problem: implementing websockets in JSF rightly is not exactly trivial, certainly not if you'd like to take into account JSF session and view scopes, and would like to be able to target a specific user during push. You'd better look at an existing push component. See also How can server push asynchronous changes to a HTML page created by JSF?
In my application there are 5 portlets accessing same bean class which is in session scope. My problem is, whenever I open a portlet, managed bean initializes. Managed bean should be initialize once in a session. In my case bean initializing 5 times. Can anyone tell me what is the root cause of that problem?
Here is my bean :
#ManagedBean(name="userManagementBean")
#SessionScoped
public class UserManagementBean {
public UserManagementBean() {
System.out.println("In getter setter bean");
sName=userManagementHelper.findScreenName();
directReport=new DualListModel<String>();
addUserToGroupDual=new DualListModel<String>();
addUserToGroupDual.getSource().clear();
addUserToGroupDual.getTarget().clear();
............
When you annotate your beans with #SessionScoped in Portlet application it is mapped to something as "Portlet Instance Session". This means that this bean will live in session of that portlet, and each portlet has its own session. There is something called "Global Session" which is session shared across all portlets, but as far as I know there is not such annotation in JSF.
JSR286 has user session based scope but it would depend on your portal server if it has the implementation for this as a Custom Scope for JSF.
I know for sure that Websphere portal 8.x supports this.
In Websphere portal 8.x you can specify your managed bean like,
#ManagedBean(name="userManagementBean")
#CustomScoped("#{portletApplicationSessionScope}")
public class UserManagementBean {
...
}
Have a look into your portal server documentation to see if it supports that.
You can use Apache JSF portlet bridge as you have updated that you are using liferay ,
It will expose Application Session Scope as EL,
Add it to application scope in portlet A
PortletSession session = request.getPortletSession();
session.setAttribute("name",name.getValue().toString(),PortletSession.APPLICATION_SCOPE);
and use in portlet B
PortletSession session = request.getPortletSession();
String value = session.getAttribute("name", PortletSession.APPLICATION_SCOPE).toString();
Your xhtml ,
<h:inputText id="itName"
required="true"
value="#{httpSessionScope.name}"/>
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.
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