As far as I know that JSF keeps all the session scoped bean in some kind of Map (correct me if I am wrong.).
In my application I have session scoped (managed by Spring and injected into the backing bean) bean named "userDetailsBean".
Is it possible to get all the instances of the bean created for different user in some sort of collection by the help of JSF API?
Add and remove them to/from some applicationwide collection/mapping yourself during #PostConstruct and #PreDestroy.
#PostConstruct
public void init() {
allSessionScopedBeans.add(this);
}
#PreDestroy
public void destroy() {
allSessionScopedBeans.remove(this);
}
Related
Would it be technically a good and acceptable practice to inject required dependencies using an Interceptor type. For example:
public #interface Inject {
public Class thisType();
}
public class InjectionInterceptor implements HandlerInterceptor {
#Override
public bool preHandle(HttpServletRequest hsr, HttpServletResponse hsr1, Object o) {
HandlerMethod handlerMethod = (HandlerMethod) o;
Class type = handlerMethod.getBeanType();
Annotation[] annotations = type.getAnnotationsByType(Inject.class);
for(Annotation annotation: annotations){
Inject inject = (inject) annotation;
for(Field field :type.getDeclaredFields()){
if(field.getType().equals(inject.thisType())){
field.setAccessible(true);
field.set(handlerMethod.getBean(), Services.find(inject.thisType()));
}
}
....
return true;
}
...
}
A bean can have 4 scopes.
Singleton
Only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
It is default scope of a bean.
Prototype
New instance is returned by the container when bean with the specified id is requested.
Ex: If you have a bean with id as "employee" in your spring container, then everytime you do a
Employee emp = context.getBean("employee");
A new instance will be returned.
request, session, and global session are for use only in web-based applications
Request
A new instance is created for every single HTTP request.
Ex : Login needs different instance everytime.
Session
A new instance will be created of the bean using the bean definition for the lifetime of a single HTTP Session.
global
The global session scope is similar to the standard HTTP Session scope and really only makes sense in the context of portlet-based web applications
You can specify the scope of a bean in two ways
Using XML:
<bean id="employee" class="com.company.Employee" scope="singleton"/>
Using annotation.
mark the class with #Scope("prototype")
you can read more about scopes here
sample code for reference is available here
I want to initialize a bean or an ArrayList like a list of key value pairs for all the drop downs in the application that can be used across sessions application wide. And Want to happen during the application start-up. I tried implementing the ServletContextListener and added the beans to the context, but it didn't work.
Any suggestions as to how I can achieve this. Thanks.
Ravi
Define a regular (singleton) Spring bean and initialize your values either in constructor, or #PostConstruct method:
import javax.annotation.PostConstruct;
#Component
public class AppBean {
#PostConstruct
protected void init() {
// executed after dependencies have been injected. initialize values here
}
}
See http://www.mkyong.com/spring/spring-postconstruct-and-predestroy-example/ for more detailed example
In SessionListener I want to set some values of #ManagedBean with Session scope that I want to show in JSF.
You'd need to create the managed bean instance yourself.
Bean bean = new Bean();
bean.setSomething(something);
event.getSession().setAttribute("bean", bean); // "bean" is managed bean name.
JSF will just reuse it if it already exist in the session scope (you see, the JSF "session scope" is under the covers represented by attributes of HttpSession). Note that this way any #PostConstruct won't be invoked and any dependencies which needs to be injected by #ManagedProperty, #EJB, etc, won't be injected at all. You'd need to do it yourself as well.
Designtechnically, much better is to perform the job just in the constructor or #PostConstruct method of the backing bean class itself.
#ManagedBean
#SessionScoped
public class Bean {
#PostConstruct
public void init() {
// Here.
}
}
The context is the following :
An client application uses a stateless session bean in order to login on an EJB server application. If the login is successful, the client should get a stateful session bean in order to perform some transactions on his personal data. However, I would want that the login method returns a new instance of this stateful session bean such that a client should not be able to manually call this session bean and perform transactions without being authenticated. Is it possible ?
In my stateless bean I have the following code :
#Resource
private SessionContext context;
...
public StatefulBeanRemote login(username, password) {
if (ok) {
StatefulBeanRemote bean = (StatefulBeanRemote) context.lookup("StatefulBeanRemote");
return bean;
}
The lookup always fail. I don't know what I am doing wrong...
The lookup you're performing is the same as:
new InitialContext().lookup("java:comp/env/StatefulBeanRemote");
Have you defined an EJB reference to StatefulBeanRemote? Perhaps that is all you need:
#EJB(name="StatefulBeanRemote", beanInterface=StatefulBeanRemote.class)
public class MyClass {
#Resource
private SessionContext context;
...
}
guys i'm using jsf 2.0 with spring.
I have annotated a method in a managed bean with #PostConstruc, but if in the bean there aren't field connected to the jsf page the #PostConstruct method isn't called even if in the jsf page there is an action method connected to the Bean.
Thank you in advance.
Added code for explaination:
this si my BackingManagedBean
#ManagedBean(name="utenteBean")
#ViewScoped
public class UtenteBean extends SupportBean implements Serializable
While this is my ControllerManagedBean
#ManagedBean(name="gestisciUtentiController")
#ViewScoped
public class GestisciUtentiController extends MessageSupportBean implements Serializable {
#ManagedProperty(value="#{utenteBean}")
private UtenteBean utenteBean;
public void setUtenteBean(UtenteBean utenteBean) {
this.utenteBean = utenteBean;
}
#PostConstruct
public void loadBean()
{
try
{
utenteBean.setUtentis(getFacadeFactory().getUtenteFacade().readAllOrdered(Utente.class, "username"));
}
catch (ApplicationException e)
{
setExceptionMessage(e.getLocalizedMessage(), e.getLocalizedMessageDetail());
}
}
http://blog.icefaces.org/blojsom/blog/default/2009/04/23/Making-distinctions-between-different-kinds-of-JSF-managed-beans/ i'm trying to use this approch. You think that that approch isn't correct? –
I'm not sure. That article mentions that the model is typically to be placed in the session scope. This is actually a poor approach. Injecting a session scoped bean in a request scoped bean makes sense if the session scoped one is for example the logged-in user and the request scoped one is bound to the form.
In your case you should just make the model bean a property of the controller bean and use #{gestisciUtentiController.utenteBean.someProperty} instead of #{utenteBean.someProperty}.
I've some "JSF design" questions before, you may find them useful as well:
JSF MVC design question
JSF / Java Design Question
What components are MVC in JSF MVC framework?