I am using JSF+Spring project my spring maanged bean is ViewScoped
my saving state is client.
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Following is my bean i found that constructor of bean and postconstruct method got call only on tomcat startup when it is spring managed bean instead if it is JSF managed bean constructor and postconstruct got call on every page refresh.
Is it the real behavior if i want to call method on page refresh every time under spring managed bean what should id do ?
#Component
#ViewScoped
public class DataTableBean implements Serializable{
public DataTableBean() {
super();
}
#PostConstruct
private void loadDataData(){
System.out.println("Post constructing");
}
}
The #Component is a Spring specific annotation to manage beans by Spring. The #ViewScoped is a JSF specific annotation to specify the scope of a JSF managed bean #ManagedBean. JSF specific scope annotations does not work on a Spring managed bean at all. You should use the Spring specific #Scope annotation instead.
So, either just manage the bean by JSF:
#ManagedBean
#ViewScoped
Or homegrow a Spring "view" scope (this is namely not one of the default scopes available in Spring):
#Component
#Scope("view")
Related
I have a #RequestScoped bean with a List property.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.springframework.stereotype.Controller;
#Controller
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
private List list;
// getters and setters
}
This property is linked to a datatable:
<ice:dataTable value="#{myBean.list}" ..other stuff.. />
The List is dynamically filled with no problem, and the datatable is displayed with no problems. But if, I navigate to another page, and then go back to the initial page the datatable is still with the data of the initial request. It shouldn't be empty again? If the bean is request scoped it should be destroyed after the request, and I should get and empty datatable as the beginning.
Even more strange is that if I open the page in one browser (like Firefox), fill the datatable with a request, then I open another browser (like Chrome) and go to the datatable page, it is filled with the data from previous request from another browser! I think the bean is behaving like an application one.
Any ideas?
Update 1: The class is not static neither its variables. Also, I disable tomcat cache, but still not working.
Update 2: I think probably found the problem. My backing beans are annotated with #Controller from Spring. I use this annotation because then use #Autowired to bind services. Could be this is creating a singleton and that why is not being created and destroyed with every request? I think pretty sure the problem is in the mix of Spring and JSF2 annotations.
You shouldn't manage a single bean by multiple different bean management frameworks like JSF, CDI and Spring. Choose the one or the other. When managing the bean by for example Spring's #Controller, all bean management related annotations of other frameworks like JSF's #ManagedBean and CDI's #Named are ignored.
I don't do Spring and I have no idea why you're using it instead of the standard Java EE 6 API, but the symptoms and documentation indicates that the scope of such a Spring bean indeed defaults to the application scope. You need to specify the bean scope by Spring #Scope annotation. You would also like to remove the JSF bean management annotations since they have no value anymore anyway and would only confuse the developer/maintainer.
#Controller
#Scope("request")
public class MyBean implements Serializable {
// ...
}
Alternatively, you can also get rid of Spring #Controller annotation and stick to JSF #ManagedBean. You can use #ManagedProperty instead of #Autowired to inject another #ManagedBean instance or even a Spring managed bean (if you have Spring Faces EL resolver configured), or the Java EE standard #EJB to inject an #Stateless or #Stateful instance.
E.g.
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
#EJB
private SomeService service;
// ...
}
See also:
Spring JSF integration: how to inject a Spring component/service in JSF managed bean?
i am using jsf2.0 as MVC framework and Spring just for Dependency Injection. i made it work but there is little problem when Spring Creating bean. Means on My JSFBean (ManagedBean) i have to use #Component Annotation of Spring otherwise i am not able to make it work. and because of that when my ManagedBean have some code in Constructor Spring is throwing Exception. It is working Perfect without Constructor CODE. Please comment if you need anything else.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean' defined in file [C:\Documents and Settings\KshiS\My Documents\NetBeansProjects\Sp_Js_1\build\web\WEB-INF\classes\com\ksh\excel\MyBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ksh.excel.MyBean]: Constructor threw exception; nested exception is java.lang.NullPointerException
My JSF Bean code is
package com.ksh.excel;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* #author KshiS
*/
#ManagedBean
#ViewScoped
public class MyBean {
#Autowired
private Userdao userdao;
ArrayList<String> arrayList = new ArrayList<String>();
public MyBean()
{
Object object = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("Userid");
if(object != null)
{
arrayList.add("Session Value");
}
else
{
arrayList.add("Temp Value");
}
}
public void print()
{
System.out.println(userdao.print());
}
}
How to Resolve it. ? OR Is there any possibility to Make it work without #Component Annotation on ManagedBean. ?
One More Important Question that I dont want use Spring As DI rather then i want use J2EE6 Dependency Injection. But also there is One problem That i have to use pure j2EE server like glassFish or JBOSS. Is it possible to use it in Tomcat. ? i know tomcat is not pure j2ee Server But i just want to use DI.
You need to post your full stacktrace here.
While your bean won't be injected using #AutoWired because your managed bean is not a spring managed bean (you need #ManagedProperty), that is not your primary problem.
The root cause is a failure in your bean's constructor. My guess would be that the following line is responsible for the NPE.
Object object = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("Userid");
FacesContext.getCurrentInstance().getExternalContext().getSessionMap() will only return a non-null SessionMap if there's a valid HttpSession. Your chained method call assumes that this will always be the case, and it appears that's not true here.
After you fix that code, you can then use #ManagedProperty to inject the spring bean into your JSF bean (you don't need Spring MVC here.)
Related reading:
JSF 2 inject Spring bean/service with #ManagedProperty and no xml
#ManagedProperty in a Spring managed bean is null
For the first problem try adding an #Lazy annotation to your JSF bean. That will delay the creation of the object till it is required. That will resolve the problem with the exception on startup - but I think it will not fix the issue. When used with JSF the object created by spring will not be used.
Take a look at the example in this article to do it correctly - using a spring variable resolver.
http://www.mkyong.com/jsf2/jsf-2-0-spring-integration-example/
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
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/web-facesconfig_2_1.xsd"
version="2.1">
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
On the second question - you can loook at TomEE. This article also has some details on using CDI in tomcat directly.
I am trying to use spring to provide managed beans to jsf. I assume that #ManagedBean will be picked up by JSF container to link the EL in JSF to managed bean even when I use spring by configuring spring usage in faces-config.xml.
Spring shall provide the beans but now who manages scope of the beans?
I have tried following annotation on beans to have it become Request scope but they do not work.
#ManagedBean(name="helloBean") //meant for JSF
#RequestScoped //meant for JSF
#Scope(value="request") //meant for spring
#Controller //meant for spring
public class HelloBean implements Serializable {
Actually earlier I was using plain JSF and #ManagedBean and #RequestScoped were working well. Now as I tried to integrate using spring the scope are not working.
I have even tried setting bean scope in spring config but they work as expected in context of spring (singleton and prototype) but not web request context.
I was trying to avoid having to use above #Scope and #Controller annotation hoping that JSF will manage scope but do not seem like.
Below are my files snippet for spring config and MyHelloBean which probably will help communicate better.
<bean id="helloBean" class="com.mkyong.common.HelloBean" init-method="init" />
<bean id="myHelloBean" class="com.mkyong.common.MyHelloBean" init-method="init" >
<property name="helloBean" ref="helloBean"></property>
</bean>
#ManagedBean
#RequestScoped
#Scope(value="request")
#Controller
public class MyHelloBean implements Serializable {
private static final long serialVersionUID = 1L;
//#ManagedProperty(value = "#{helloBean}")
private HelloBean helloBean;
see in above MyHelloBean I am using spring DI to set helloBean which gets set by spring fine. I have commented out #ManagedBean which I think I can leave it in there as it will be ignored by spring any ways and JSF is not going to process it I guess but to be safe I commented it out for JSF to not process it.
To complete I use below in faces-config to activate spring usage.
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
Regards,
Miten.
Our team faced similar problems integrating JSF and Spring beans, including problems with their scopes. And here I am to share our knowledge.
Scopes
Basically now, when you defined in your application context, that Spring will be managing your beans, thus scopes. Spring will map JSF scope annotations to his native scope annotations.
Example when both Spring and JSF support provided scope:
#RequestScoped annotation will be mapped to #Scope("request") Spring's annotation, etc with other supported scopes.
Example when Spring does not support JSF's provided scope:
#ViewScoped is not defined in Spring's native scope annotations, thus (not sure) it will use Spring's default scope, which is singleton, or request scope (not sure).
Bean Injection
In JSF2 you used #ManagedProperty annotations for injection, while Spring uses #Autowired annotation. What are the differences and which to choose?
Injecting Spring beans with #ManagedProperty:
Spring component you wish to inject must have a value which will match jsf injection annotation's value: #Component(value = "valueMatches") injected with #ManagedProperty(value = "valueMatches").
Injecting Spring beans with #Autowired:
Spring component you wish to inject must does not require a custom value to distinguish, if it is the only implementation of the bean you are injecting: #Component injected with #Autowired.
Our way
We used Spring's annotations for defining Beans, Scopes and Injection.
We marked JSF beans with #Scope(value = "desiredScope"), #Controller(value = "beanName") and #Qualifier(value = "beanName") annotations. Later which could be accessed from JSF context with help of in faces-config.xml via "beanName" value defined in the #Controller annotation.
We marked Spring services with #Service annotation.
We injected Spring services and JSF beans with #Autowired annotation.
We found ViewScope and FlashScope custom implemetations on the web and used them for our beans. Thus we did not lose any of JSF2 scopes and even added new one.
Hope this helps.
Your approach is a bit confusing in the sense that it seems that you're mixing Spring XML configuration and Spring Annotation-based configuration. As described as an example here, if you're using annotated configuration then you should have:
<context:component-scan base-package="com.yourcom.package" />
to order Spring scan for the annotations. Otherwise, if you're using XML configuration then you should have:
<bean id="helloBean" class="com.mkyong.common.HelloBean" init-method="init" scope="request" />
as by default the scope for a Spring bean is singleton.
I have a #RequestScoped bean with a List property.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.springframework.stereotype.Controller;
#Controller
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
private List list;
// getters and setters
}
This property is linked to a datatable:
<ice:dataTable value="#{myBean.list}" ..other stuff.. />
The List is dynamically filled with no problem, and the datatable is displayed with no problems. But if, I navigate to another page, and then go back to the initial page the datatable is still with the data of the initial request. It shouldn't be empty again? If the bean is request scoped it should be destroyed after the request, and I should get and empty datatable as the beginning.
Even more strange is that if I open the page in one browser (like Firefox), fill the datatable with a request, then I open another browser (like Chrome) and go to the datatable page, it is filled with the data from previous request from another browser! I think the bean is behaving like an application one.
Any ideas?
Update 1: The class is not static neither its variables. Also, I disable tomcat cache, but still not working.
Update 2: I think probably found the problem. My backing beans are annotated with #Controller from Spring. I use this annotation because then use #Autowired to bind services. Could be this is creating a singleton and that why is not being created and destroyed with every request? I think pretty sure the problem is in the mix of Spring and JSF2 annotations.
You shouldn't manage a single bean by multiple different bean management frameworks like JSF, CDI and Spring. Choose the one or the other. When managing the bean by for example Spring's #Controller, all bean management related annotations of other frameworks like JSF's #ManagedBean and CDI's #Named are ignored.
I don't do Spring and I have no idea why you're using it instead of the standard Java EE 6 API, but the symptoms and documentation indicates that the scope of such a Spring bean indeed defaults to the application scope. You need to specify the bean scope by Spring #Scope annotation. You would also like to remove the JSF bean management annotations since they have no value anymore anyway and would only confuse the developer/maintainer.
#Controller
#Scope("request")
public class MyBean implements Serializable {
// ...
}
Alternatively, you can also get rid of Spring #Controller annotation and stick to JSF #ManagedBean. You can use #ManagedProperty instead of #Autowired to inject another #ManagedBean instance or even a Spring managed bean (if you have Spring Faces EL resolver configured), or the Java EE standard #EJB to inject an #Stateless or #Stateful instance.
E.g.
#ManagedBean
#RequestScoped
public class MyBean implements Serializable {
#EJB
private SomeService service;
// ...
}
See also:
Spring JSF integration: how to inject a Spring component/service in JSF managed bean?
I am trying to #javax.naming.Inject a Spring 3 Bean called WtvrBean into a JSF 2 #FacesConverter.
Both the Bean and the Converter are on the same package. And, in my spring's applicationContext.xml, I am scanning this package:
<context:component-scan base-package="my-package" />
But this is not working. For sure, the JSF 2 internal class that uses the converter is
definitely not in my-package.
For instance, if I remove the #ManagedBean from a JSF 2 ManagedBean, and replace it to #org.springframework.stereotype.Component or #Controller, the WtvrBean can be #Injected on this ManagedBean, by using Spring WebFlow.
Well, as far as I know, there is no such thing as a #Converter stereotype in Spring.
I know I can use
FacesContextUtils.getWebApplicationContext(context).getBean("WtvrBean")
But, with that approach, the coupling between the web app and the spring is getting more tight. (annotations are metadata, and are not even considered dependency by some authors).
I am using FacesContextUtils so far, if there is no better solution.
Any ideas?
If you want to inject beans into instances of a class, these instances have to be spring-managed. I.e. spring has to instantiate them. And this is not happening, so - no, you can't inject there.
But this is because you register the converter within jsf. You can skip that:
#Component("myConverter")
public class MyConverter implements Converter { .. }
And then, if you are using the spring <el-resolver>:
converter="#{myConverter}"
So that will do it. It has worked for me.
(A workaround worth mentioning is that you can do it by using aspectj weaving and #Configurable, but I'd prefer your FacesContextUtils approach. The weaving modifies classes so that they become spring managed even if they are not instantiated by spring.)
#FacesConverter(value = "examTypeConverter")
#Named
Simple answer.
hey i was facing the same problem that spring beans are not getting injected in the JSF Converter.
then by googling about it i found the answers that after JSF 2.2 we can make converters as jsf managed bean. and then we can inject the spring dependency.
it solved my problem.
#ManagedBean
#RequestScoped
public class CustomerByName implements Converter {
#ManagedProperty(value = "#{customerDao}")
private CustomerDao customerDao;
and in your jsf page use it like a managed bean
converter="#{customerByName}"
Add #Scope annotation (eg with "request" parameter) to your managed bean.
#ManagedBean
#Scope("request")
public class MyBean {
....
}