Does anyone know a workaround for https://java.net/jira/browse/JAVASERVERFACES-3947 ?
In my project , I am using primefaces 5.3 , mojarra 2.2.12
wilfly 8.2.1
I profile the application , and I see ViewScopedManaged beans are not garbaged collected , and the heaps keeps increasing and increasing until there is a memory leak
In faces-config, I have this to integrate with Spring:
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
I think my issue is related to https://java.net/jira/browse/JAVASERVERFACES-3947 . Does anyone know a workaround ? I think there are some jsf parameters to configure the max number of views scopbed beans in memnory ? will it work out ?
This is an example of a bean class:
#ManagedBean
#ViewScoped
#Data
public class JSFBean {
//springBeanImpl is a Spring bean
#ManagedProperty(value = "#{springBeanImpl }")
private SpringBean springBean;
}
In our last JSF project, we did the following:
#ManagedBean
#ViewScoped
public class CountryBean extends SpringBeanAutowiringSupport {
#Autowired // you can also use #Inject
private SpringBean springBean;
}
So you don't use the newer CDI Annotations, but the 'old' ones from JSF. By extending your class from SpringBeanAutowiringSupport, Spring will handle the dependency injection. I suppose the JSF annotations will be removed one day and be completely replaced by CDI annotations. So that might not work in future releases of JSF.
About the garbage collection - are you sure that they are not removed at some time? Be aware that by default the last 25 Views are kept in memory. This link JSF 2.2 Memory Consumption: Why does Mojarra keep the ViewScoped Beans of the last 25 Views in Memory? explains it a little. Hopefully those parameters are better documented in JSF 2.3.
Anyway, as balusc mentioned - Spring and JSF are currently not the best combination since JSF relies more and more on CDI. I personally think that it is a pity that the current situation is like that. This was one of the main reasons why we stopped using JSF in new projects. It is just to unclear whether JSF and Spring will be less or more compatible in coming releases.
Related
I am creating new JSF 2.2 application and found this issue:
I have:
1) EL Resolver
<application>
<locale-config>
<default-locale>ru</default-locale>
</locale-config>
<resource-bundle>
<base-name>i18n.messages</base-name>
<var>msg</var>
</resource-bundle>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
<!--<variable-resolver>org.springframework.web.jsf.WebApplicationContextVariableResolver</variable-resolver>-->
</application>
2) Faces Bean
#Named("SubscriberBalance")
#RequestScoped
public class SubscriberBalance extends AbstractManagedBean {
private static final long serialVersionUID = -7018658511320101002L;
private SupportService supportService;
private SubscriberBalanceWrapper subscriberBalance;
private Long subscriberId;
private Integer subscriberType;
private Integer months;
3) Spring4+Hibernate4
And after that,my bean shares data between all users. It behaves like spring singleton. It seems like it ignore JSF scopes and process only Spring scopes. So #Scope("request") is working, but #RequestScope doesnt. How to do it correctly? And why it happening? Thank you
I think I figured out this issue and may be it will be helpful for someone.
So we have:
1) CDI - feature of Java EE 6
2) Spring framework
3) JSF
First of all, Spring never interact with CDI in my case. CDI #Named annotation is JSR 330 annotation. But since spring 3.0, Spring also scans those annotations. So that`s why in my case #Named works.
The second, #Named is full equivalent to #Component. So I could use #Component there as well.
#RequestScope and other JSF annotations will not work because its not JSF context, but Spring context. If we need to use JSF context, we need to use #ManagedBean, etc.
#Scope annotation works because its Spring-managed bean, because I have package-scan enabled for my bean.
So approaches are:
1) Use pure JSF with #ManagedBean annotations. I dont prefer this way. Disadvantages are: poor DI integration, much handy work, etc
2) Use CDI. I dont like it as we have Spring
3) Use Spring everywhere. I love this way as it gives me one-way control on all parts of my system. I will not have to think about JSF specific annotations until I really need them.
So in JSF backend bean should be:
#Controller
#Scope(...)
Please see this article
Thank you
I'm using Spring 3.1 JSF 2.2.
Annoting Bean with ViewScoped introduced by JSF 2.2 not work.
#javax.inject.Named
#javax.faces.view.ViewScoped
public class TestBean {
#PostConstruct
public void init(){sysout("Why spring invoke this when initializing context :-( ");}
}
In my applicationContext.xml there is an annotation component-scan tag
<context:component-scan base-package="com.test"/>
Spring 3.1 detect and deal with CDI annotation but #javax.faces.view.ViewScoped not work. I know there is another solution by creating my own ViewScoped implementation but i want to know why #javax.faces.view.ViewScoped not work
Best solution was removing spring and using a Java EE implementation of CDI
You should notice that JSF annotations will nor work for Spring beans, because JSF beans located in different context.
But view scope implementation is pretty simple. I've created an artifact to solve this problem.
See my github javaplugs/spring-jsf repository.
javax.faces.view.ViewScoped will only work for JSF Managed Bean and not for CDI.
Use javax.faces.bean.ManagedBean annotation if you want to have a correct behavior with View scope instead of javax.inject.Named.
Regards
JSF is very popular technology in Java world, however, cooperation with Spring is still painfull and requires 'nasty' hacks. I have currently the problem with one of this 'hacks'.
Spring services are injected using the SpringBeanFacesELResolver. It is configured in faces-config.xml:
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
The injection of Spring services is very ugly, but it is working:
#ManagedProperty(value="#{customerService}")
CustomerService customerService;
But there are issues. JSF requires from me that the managed bean should be serializable. That means, that the Spring service must also be serializable, or the field should be transient. When the field is transient, the injection is not working (I have null in that field). And making Spring services serializable is in my opinion not a good idea and a potential performance issues - what should happen with Hibernate context, data sources, which all are injected into Spring service?
So, what is the correct and less painfull way of using Spring services withing JSF managed beans?
I experienced a lot of issues with org.springframework.web.jsf.el.SpringBeanFacesELResolver, too. Mostly related to unmatching object scopes (Spring has no equivalent to JSF's view scope and conversation scope). Some people also complain about serialization problems.
I successfully applied the solution proposed in this article: http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely/.
In my case, serialization, was not a problem and I was only concerned with bean scopes. I wished JSF to fully manage the backing beans lifecycle without interference with Spring beans lifecycle.
I made JSF managed beans to load the Spring context and autowire themselves to access Spring-managed beans from the JSF context.
I developed the following JSF bean superclass:
public abstract class AutowireableManagedBean {
protected AutowireCapableBeanFactory ctx;
#PostConstruct
protected void init() {
logger.debug("init");
ctx = WebApplicationContextUtils
.getWebApplicationContext(
(ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext())
.getAutowireCapableBeanFactory();
// The following line does the magic
ctx.autowireBean(this);
}
...
}
Then, my concrete JSF backing beans looked like this (I was able to use view scope without problems):
#ManagedBean
#ViewScoped
public class MyBackingBean extends AutowireableManagedBean {
#Autowired
private MyDao myDao;
I would like to achieve this idealism :
To have only 1 implementation for the JSF Bean container, like to use only Spring or Weld but not both. Currently i am using Spring for my backend, so i prefer Spring.
To have only 1 annotation, to choose between #ManagedBean, #Named, #Model
To be able to use all supported scopes, like #RequestScoped, #SessionScoped, #ViewScoped, #FlashScoped, maybe also #ConversationScoped
The JSF Beans could be injected with spring-managed-services (The backend services), perhaps using #Inject or #Autowired
So far i've been finding no best combination to achieve these because as far as i know, please correct me if i am wrong, :
#ManagedBean can not be injected with spring services ?
#Named can be injected with spring services using #Inject, but #Named is using Weld. Can i just use spring to managed the #Named instead of Weld ?
#Named doesnt support #ViewScoped and FlashScope ?
Please share your thoughts and experiences.
Thank you :-)
UPDATE 15 March 2011
Found an interesting page that describes how to replace Jboss Weld with Spring as the JSR 299 CDI implementation. So basically, the question number 2 is answered. Number 1 is also answered indirectly since i can now inject spring services.
But still, the number 3 question remains. I would find very helpful if i can use the #ViewScoped and Flash Scope in the #Named, something like this article. Flash scope implementation has yet to be seen, but the closest one i can get so far is this page.
Hopefully, replacing weld with spring as the jsr 299 implementation will still enable me to use #ConversationScoped.
Gotta test things now, wish me luck :-)
UPDATE 18 MARCH 2011
Successfully make use of Spring 3 instead of weld to do the #Named, #Inject. The important thing is to set the el-resolver in the faces-config.xml.
AFAIK, Spring 3 currently doesnt support CDI yet, so bye2 #ConversationScoped.
For the scoping, i must still use #Scope("request") or #Scope("session"), but if i prefer the #RequestScoped (javax.enterprise.context.RequestScoped) and #SessionScoped, i can make use of the bridge provided from this article.
The Scope("view") for spring from this article works like magic :-)
One problem remain though, how to pass objects between Scope("view")-beans ..
Wish me luck !
update
Ahhh .. finally done ..
Passing the variables using Flash provided by JSF2 really works like magic.
I dont need an 3rd party implementation for that.
So basically, i can do without weld, but with spring, with the common scopes available, including the view scope, dan can pass between beans using the flash object.
One thing missing is the conversation scope, which isnt a major problem to me yet.
Hopefully the future spring can support this conversation scope.
Cheers :-)
I can successfully Inject Spring bean using ManagedProperty annotation like below. This is on JSF Managed Bean. Spring bean is for backend and I prefer spring for backend.
#ManagedProperty(name="userRepository", value="#{userRepository}")
private UserRepository userRepository;
//Setter and/or Getter
value is the most important thing here. It's actually the bean name of spring. I hope this helps.
Weld (actually, the reference implementation of JSR-299 Context and Dependency Injection, also known as Java EE 6 CDI) was less or more invented to supplant Spring in Java EE 6 environments. I would suggest to use Java EE 6 CDI instead of Spring. Why would you use a 3rd party framework when Java EE 6 provides the same functionality out the box?
If the Spring backend really cannot be changed, then I'd suggest to stick to it and not to intermix with Java EE 6 CDI annotations to save yourself from confusions and maintenance headache.
I know this sounds strange, mixing CDI (Weld) and Spring for the controller.
But imagine this situation :
With CDI, i can make use of the #ConversationScoped, which is one of my requirement (And so far i dont know whether i can use spring for this kind of scope, because if i can, i could just replace Weld with Spring, with the el-resolver in faces-config.xml)
My services objects(#Service) along with the DAOs(#Repository) are to be managed by Spring
Now one question arise is that, inside my controller, how can i access my service object ?
Something like this wouldnt work i think :
#Named
#ConversationScoped
public class MyBean {
#Named
private SomeOtherBeanManagedByCDI myOtherBean; // this will work
#Autowired
private MySpringBean mySpringBean; // dont think that this will work
....
}
Any ideas on how to make use of spring beans inside a cdi bean ? Thank you !
update
I've just tested the solution from this article, and so far it works fine, and i feel relieved.
Thank you !
Rick Hightower wrote a nice Extension library which supports to inject Spring beans into CDI beans and vice versa:
http://rick-hightower.blogspot.com/2011/04/cdi-and-spring-living-in-harmony.html
There is still a good accepted answer and some good edits in the OP, but I think there still is time to point out the Seam Spring module.
Also, if you're trying to manage state across a series of pages, and want the effective of conversation management for Struts or JSF or Spring MVC, Spring Web Flow provides just what you need, complete with flow-scoped beans that live for the duration of a flow, more or less equivalent to a conversation in Seam / CDI. If you want a more long lived flow managment solution, the Activiti SPring module makes it dead simple to configure some beans that live for the duration of the process scope, akin to the functionality that Seam had for jBPM.