Get session-scoped bean from GenericFacesPortlet - java

Is it somehow possible to accesse a sesssion-scoped bean in a class extending the GenericFacesPortlet?
Is a portlet even aware of the FacesContext?
What do I want to achieve?
I want to serve a file through the serveResource() method. The file's content should be retrieved from a bean implementing the method getResourceContent().
But unfortunately, I'm getting null when calling FacesContext.getCurrentInstance().
For your information: I'm using the JBoss Portlet Bridge in Version 2.1.0.FINAL.

The FacesContext will always be null in the GenericFacesPortlet. The GenericFacesPortlet creates the bridge and initializes it. The Bridge is actually creating the FacesContext and executing the JSF life cycle. From your GenericFacesPortlet point of view the FacesContext is not yet created (null).
In order to achieve what you want, you can grab the bean from the session. In order to do that you must use:
YourBean yourBean = (YourBean) request.getPortletSession().getAttribute("yourBeanName");
where "yourBeanName" is the name you used in the faces-config.xml when you defined YourBean.
Cheers!

Related

Two spring applications, both use a certain jar and application context - how do i control from which appl i get a bean from the context?

I have two Spring applications, applA and applB, running in Tomcat - both use jarX.jar and applicationContext-x.xml.
So there's going to be one instance of a certain bean, defined in the above context, for each application.
I'm exposing the bean and some of its methods via JMX by using annotations.
now i want to write a test client which calls method of the bean, but sometimes i want to call the methods of the bean in applA and sometimes of the bean in applB.
How do i do that?
i also have a bean called jmxServerConfiguration in each application, each using a different port though.
currently in my JMX client i'm getting the bean by using
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(applicationContextName);
theBean = beanFactory.getBean(BEAN_NAME);
but i always get the bean of applA. how do i tell it whether i want the bean of applB or applA?
Should i perhaps, (how?), use
MBeanServerConnection connection = JmxUtils.getMBeanServerConnection(url);
and specify a different port in the url, depending on the appl from which i want to get the bean?
Set the default-domain on the MBean exporter to a different value for each application and use the appropriate ObjectName to access the bean(s) over JMX.

Using global scope in spring mvc

I came across below statement from Spring MVC documentation:
Upon initialization of a DispatcherServlet, Spring MVC looks for a
file named [servlet-name]-servlet.xml in the WEB-INF directory of
your web application and creates the beans defined there, overriding
the definitions of any beans defined with the same name in the global
scope.
Please help me in understanding this statement.
As global scope is used for portlet based applications, then why a developer wants to configure like this in normal Spring MVC applications?
I don't think the term "global scope" here means the global scope bean like singleton, prototype, request, session and global. I believe the global scope here means the scope of the bean context.
In Spring MVC, there are 2 scopes of bean can be defined. The first one is at servlet context level which I believe is what it meant by "global scope" in the above statement. The second one is at servlet level where the bean defined at this level will take priority when resolved by other bean in servlet level.
The beans in servlet level will be able to resolve beans in servlet context (global) level but not the other way round.
Spring MVC provides options to configure multiple Context based on number of DispacthServlet Configuration .
For example
Consider you have two modules with in your application and url pattern starts as module1/* and module2/* . And you want to keep two different context ( always declarations in *context.xml is private to the context ). So you would be creating two dispatchServlet and provide two different servletname and url pattern. Now you have two Spring context which has specific declartions and which is not visible to other. But still you may wanted to declare some application wide beans such as persistentManager / Logger instance and so. for those case you can keep seperate config as root-context.xml and keep the generic declartions in that root. Which is considered here as "GLOBAL SESSION" Now this Global Session beans scope can be different scope based on configuration. And the bean configured in Global Session ( root-context) can be overriden by specific-servlet for customization.
I like the answer provided here also Understanding contexts in Spring MVC
A typical Spring MVC application will have two contexts: the root context and the servlet context.
The root context is loaded by the ContextLoaderListener. The ContextLoaderListener loads the ApplicationContext and sets it as an attribute in the ServletContext. This makes it available to other Servlet, Filter, and XxxListener instances.
The servlet context is another ApplicationContext loaded by the DispatcherServlet when its init() method is called. Since the init() method of a Servlet is called after the contextInitialized() method of a ServletContextListener is called, the DispatcherServlet has access to the root context set as an attribute in the ContextLoaderListener and can therefore use the beans declared there.
[...] creates the beans defined there, overriding the definitions of any
beans defined with the same name in the global scope.
A bean definition is, for example,
<bean id="someBean" class="com.company.SomeBean">
<property name="someProp" value="some value" />
</bean>
Spring creates a BeanDefinition object for this and all other <bean> declarations (or #Bean annotation methods). When the ApplicationContext is refreshed, Spring generates actual instances from these bean definitions.
What the above quote from the documentation is saying is that if you have a <bean> declaration with the same name or id in both the root context and the servlet context, the servlet context one will overwrite the root context one.

Spring Injection & Globally initialized objects

I have a spring injected service
class A{
List l = new ArrayList();
public m1(){
//do some additions in list
}
public m2(){
//do some new additions in list
}
}
Now because creating of objects of A, is in the hands of spring the behavior of program is not what is expected. (I expect list to be available empty always but not initialized by methods for some wired reason)
Will Spring always create only one instance of A, so that list l will keep on growing, I have configured bean as singleton in application context.
If yes, naturally I must initialize the list inside the functions m1 & m2 or callee must past the reference, and in my case callee being struts2 actions they are not singleton so this issue can be solved?
Or
Does spring provide any support in configuration to initialize member variables at every call or something else?
More generally what are best practices to have in writing services injected by spring about using member variables/ local variables for performance & efficiency.
Trying to answer following :
Does spring provide any support in configuration to initialize member variables at every call or something else?
By default Spring beans are singleton. Initialized only once and use the same object again and again.
However, if requirement changes as you asked. You need to understand scope attribute provided by the Spring.
<bean id="id" class="com.test.TP" scope="prototype">
</bean>
Refer following for detail understanding.
Scope Description
singleton
Scopes a single bean definition to a single object instance per
Spring IoC container.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP
request; that is each and every HTTP request will have its own
instance of a bean created off the back of a single bean definition.
Only valid in the context of a web-aware Spring ApplicationContext.
session
Scopes a single bean definition to the lifecycle of a HTTP Session.
Only valid in the context of a web-aware Spring ApplicationContext.
global session
Scopes a single bean definition to the lifecycle of a global HTTP
Session. Typically only valid when used in a portlet context. Only
valid in the context of a web-aware Spring ApplicationContext.
http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch04s04.html
It is also possible to have user defined scope such as thread scope.
You can configure your bean as follows:-
<bean id = "serviceBeanA" class = "somepkg.A" scope="prototype">
<property name = "l">
<value>
<list>
<value>ABC</value>
.....
</list>
</value>
</property>
</bean>
I'm not sure if I understand the question but your sample class should work fine with spring. Spring will call the default constructor unless you pass in constructor args in the configuration file. As long as you have an id="..." in the bean then it will create a singleton of that class. Then, the first class that calls a.m1() will see l as being an empty list.
What may be happening is that you have multiple instances of A being created. See here about Spring singletons versus non. To quote:
Beans are defined to be deployed in one of two modes: singleton or non-singleton. (The latter is also called a prototype, although the term is used loosely as it doesn't quite fit). When a bean is a 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.
So if you don't have an id or name specified in your Spring configuration then you might get multiple instances of A created.
The non-singleton, prototype mode of a bean deployment results in the creation of a new bean instance every time a request for that specific bean is done. This is ideal for situations where for example each user needs an independent user object or something similar.

Spring set abstract bean property value

I need to chance spring bean property values on runtime. Currently I'm doing it this way
Object bean = context.getBean(beanName);
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean);
wrapper.setPropertyValue(propertyName, newValue);
But some beans are configured as abstract
<bean id="abstractFoo" abstract="true" class="com.Foo" />
<bean id="bar" class="com.Bar">
<constructor-arg><bean parent="abstractFoo" /></constructor-arg>
</bean>
and in that case context.getBean("abstractFoo") throws BeanIsAbstractException
This is really simplified example, but I hope you get the idea.
Any idea how to change property value of abstract bean (in this case 'abstractFoo')?
We're using spring 2.5.4
Edit
Changed a XML example to be more specific. abstractFoo is declared abstract because of security reasons.
Spring application context contains bean definitions, and Spring instantiates bean objects defined by these definitions.
Your current code obtains an object that was created from the named bean definition, and changes its property. However, abstract beans are never instantiated as objects, they exist only in the form of definitions which are inherited by definitions of concrete beans.
So, if you want to change properties of abstract beans, you need to change their definitions, that can be done using BeanFactoryPostProcessor. Note, however, that post-processors are applied during container startup, so if you want it to be actually "runtime", you this approach is not applicable.
Disclaimer: this is untested; off the top of my head. Not sure if it will work after the init phase.
You need to get in instance of a ConfigurableListableBeanFactory. Your appcontext probably is one, so you can probably cast it.
From there, get the bean definition and change the property.
ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory)context;
BeanDefinition fooDefinition = clbf.getBeanDefinition("abstractFoo");
MutablePropertyValues pv = fooDefinition.getPropertyValues();
pv.add(propertyName, newValue);
Maybe you need to re-register your beandefinition with the ConfigurableListableBeanFactory after that. I'm not 100% sure; you'll have to test that.
Keep in mind that if it works, it will only work for beans that are instantiated after the change.

Spring MVC 3.0 accessing Session Variable

I have the following problem, I have configured the following class which should be stored in session.
<bean id="Users" class="com.doolloop.DlUser" scope="session">
<aop:scoped-proxy/>
</bean>
Then I in my Dispatcher servlet I would like to access this class user and set
#RequestMapping(value="/authenticate.do",method = RequestMethod.POST)
public String sampleAuthentication(#Valid Person person, BindingResult result,
Map model,HttpServletRequest request){
...... /some code
HttpSession session = request.getSession();
DlUser user = (DlUser) session.getAttribute("Users");
/// some uses for user object
}
The problem is that I'm always getting null Value of user object.
What am I doing wrong?
Second problem, I read in articles that accessing HttpSession is not thread-safe, how can it be done safe way? Should be kind of Singleton? Why this is not Thread Safe operation?
Thank you in advance.
Danny.
That's a special case when you want to inject a bean with a shorter scope into a bean with a longer scope (i.e. a session-scoped bean into a singleton-scoped bean)
You can use a lookup-method:
<bean id="yourSingletonBean"
class="your.singleton.BeanClass">
<lookup-method name="getDLUser" bean="Users"/>
</bean>
You'll need to make your singleton bean abstract, and create an abstract method public DLUser getDLUser()
That, however, is not a perfect solution. The idea is to hold in the session as little as possible. If you don't need to store a bean in the session, but only the current user, you can easily call session.setAttribute(..) when the user logs in, and then access the current user with session.getAttribute(..), without the user being a bean at all.
A way that I chose for the current user in my application is to create a custom #SessionAttribute annotation. See this question on how to achieve that.
objects scoped "session" are not STORED in session, they are available to the session through the regular direct injection paradigm. It's just that they are session-tied. So, if you need to have this available, you need to inject this bean into your controller. Read here for more info.

Categories