I have a question related to bean scope and abstract bean.
Hard to explain but here's an example:
<bean id="prototypeBean" class="...X" scope="prototype" />
<bean id="singletonParentBean" class="..Y" abtract="true"> <!--No scope so Singleton. -->
<property name="bean" ref="prototypeBean" />
</bean>
<bean id="childPrototypeBean" class= "..z" parent="singletonParentBean" scope="prototype">
Is the attribute "prototypeBean" in the bean "childPrototypeBean" will have the scope "prototype" ? Because it is injected in the parent bean that is singleton.
Thanks
David
So response is yes. Was able to try it in my project. Every different instance of "childPrototypeBean" has a different "prototypeBean" instance.
Related
I have a product.xhtml and a ProductBean. I use /product/{id} to access the products so I have a viewParam in product.xhtml with value=ProductBean.id. The problem is that inside the bean I use an init function with a PostConstruct annotation in order to fill the details of the product. To do this I need the id to call an external function. I guess though that init is called before viewParam sets the id of the bean and therefore inside init I cannot call the external function because id is not set yet. What am I doing wrong and how do I fix this?
UPDATE
I found what was wrong. I think the viewParam method works with CDI beans but the ManagedProperty method works with JSF beans..
I do have one other problem now. My CDI bean is RequestScoped and when the product.xhtml is rendered the bean is created and I guess is later discarded. The funny thing is that I have a function inside that bean which when I call, I can read the id (which I assume this happens because is connected to the view param) but not any other properties. Any ideas how to fix this?
You need a <f:event type="preRenderView"> instead.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
With
public void onload() {
// ...
}
Note that this is in essence a little hack. The upcoming JSF 2.2 will offer a new and more sensible tag for the sole purpose: the <f:viewAction>.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
Communication in JSF 2.0 - Processing GET request parameters
I am looking to get header value to pass it on bean properties in spring integration.
I have tried below steps but it is not working:
<bean id="loggingInterceptorId" name="loggingInterceptor" class="LoggingInterceptor">
<property name="id" value="#{headers.get('id')}"></property>
</bean>
Try value="headers['id']" as #{....} is reserved for property replacement.
I have the below case:
<p:selectBooleanCheckbox id="couponAgreement">
<h:panelGroup rendered="#{!couponAgreement.valid}">
Is it possible to get an component by its id? Setting the binding would do it, but when I include this multiple times in my JSF page, only the last instance is rendered.
I imagine something like this:
<h:panelGroup rendered="#{!fn:getComponentById('couponAgreement').valid}">
You can use UIComponent#findComponent() for this. It will be searched relative to the naming container parent. So if you can guarantee that those components have an unique naming container parent (e.g. <ui:repeat>, <f:subview>, <h:form>, etc), then do so:
<h:someInput id="someInput" ... />
<h:someOutput ... rendered="#{component.findComponent('someInput').valid}" />
As to binding, you should just make sure that the value of the binding attribute is exclusively tied to the component itself, and not shared across multiple components.
So, this is wrong when it concerns a component in a reusable include/tagfile/composite:
<h:someInput binding="#{someInput}" ... />
<h:someOutput ... rendered="#{someInput.valid}" />
Rather bind it to an unique key. Let the include/tagfile/composite require a id param/attribute and then use <c:set> to create a variable which appends the id so that you can ultimately use it as key of request scope map.
<c:set var="binding" value="binding_someInput_#{id}" />
<h:someInput id="#{id}" binding="#{requestScope[binding]}" ... />
<h:someOutput ... rendered="#{requestScope[binding].valid}" />
To keep the request scope clean, consider creating a hash map in request scope via faces-config.xml:
<managed-bean>
<description>Holder of all component bindings.</description>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<h:someInput id="#{id}" binding="#{components[id]}" ... />
<h:someOutput ... rendered="#{components[id].valid}" />
In case of composite components, there's another way. Bind it to the backing component.
<cc:interface componentType="someComposite">
...
</cc:interface>
<cc:implementation>
<h:someInput binding="#{cc.someInput}" ... />
<h:someOutput ... rendered="#{cc.someInput.valid}" />
</cc:implementation>
#FacesComponent("someComposite")
public class SomeComposite extends UINamingContainer {
private UIInput someInput; // +getter+setter
// ...
}
In a decently designed composite you often already have or ultimately need it anyway.
I developing a simple application using JSF and PrimeFaces and here's a problem that I'm facing:
These are managed beans that have a Person property:
ClientBean
EmployeeBean
I have the person.xhtml that shows the data from a person. I include the person.xhtml on a client.xhtml and employee.xhtml. I need to create two person.xhtml because I'm using different beans. What I want to do is something like that:
<c:set var="person" value="clientBean.person" />
<ui:include src="person.xhtml"/>
<c:set var="person" value="employeeBean.person" />
<ui:include src="person.xhtml"/>
And in my person.xhtml I can use #{person.name} , #{person.dateOfBirth}.
I searched and use <c:set/> in JSF is wrong.
Anyone can help?
Pass it as <ui:param>.
<ui:include src="person.xhtml">
<ui:param name="person" value="#{clientBean.person}" />
</ui:include>
<ui:include src="person.xhtml">
<ui:param name="person" value="#{employeeBean.person}" />
</ui:include>
Register person.xhtml if necessary as a tag file to make it look better, see also When to use <ui:include>, tag files, composite components and/or custom components?
<my:personForm value="#{clientBean.person}" />
<my:personForm value="#{employeeBean.person}" />
Beware of duplicate component ID errors. See also Avoiding duplicate ids when reusing facelets compositions in the same naming container.
I have a controller that is stateless which takes care of processing forms. This is defined as ApplicationScoped. On my page I have a form associated to a backing bean defined as a ViewScoped.
The error I got when I want to process the form:
serverError: class com.sun.faces.mgbean.ManagedBeanCreationException Unable to create managed bean myController. The following problems were found:
- The scope of the object referenced by expression #{myFormBean}, view, is shorter than the referring managed beans (myController) scope of application
In my form:
Name: <h:inputText value="#{myFormBean.name}" id="name" />
<h:commandButton value="Save Name" action="#{myController.processForm}">
<f:ajax render="nameResult" />
</h:commandButton>
Your name is <h:outputText value="#{myFormBean.name}" id="nameResult"/>
The controller:
#ManagedBean
#ApplicationScoped
public class MyController {
#ManagedProperty("#{myFormBean}")
private MyFormBean myBean;
public void processForm() {
System.out.println(myBean.getName());
// Save current name in session
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
"name", myBean.getName());
}
}
The backing bean:
#ManagedBean
#ViewScoped
public class MyFormBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I could solve that by setting the controller as SessionScoped but it’s not a clean way since the controller is stateless, so I don’t need one controller for each session. One controller for the whole application should be sufficient.
I have a Spring MVC background, that’s why I am confused on how to do things with JSF 2.0
There is a flaw in your design. Your controller is not stateless at all. It has a property which is different for each request/view, namely the myBean. If it was supported, then every new request/view would override the previously set one and the enduser will face the property value of a completely different enduser. This leads to problems in high concurrent situations.
You need to make it request/view scoped instead of application scoped. Still then, I believe that you have to approach it completely different. You're manually setting an attribute in the session scope in the action method instead of setting it as a property of an (injected) session scoped bean. How to solve it properly depends on the functional requirement which is not clear from the question.
I have JSF Managed Beans with different scopes referencing each other, and I have found Spring adequately addresses my needs. The key to success was the Spring AOP that proxifies bean references and gives me more flexible autowiring. I think it would make sense for you to mix JSF and Spring similarly to achieve your goals.
I don't use the JSF scope declaration annotations to declare my beans. Instead, I use Spring to declare my beans, assign their scopes, and specify that I want the oddly-scoped beans to have aop proxies generated for them (so they can get autowired appropriately whenever they are referenced.) I use the spring el-resolver to make my Spring beans addressable as JSF2 managed beans in EL.
I don't use view scope in my program, I use session scope with request-scoped beans referencing them. But, I suspect my approach could be adapted for your view-scoped beans as well.
I don't use annotations to declare my beans, I use XML for declaring my beans and their scopes. I just find it handy to have all of my bean declarations cataloged in one place. I'm sure there's a pure annotation-based approach to achieve what I've got. I do use the #Autowired annotation in my beans to indicate where references to other beans should be wired in. This keeps my XML configuration short, eliminates the need for getter/setters, and gives me a little more Java-side flexibility than I've been able to get from going pure XML.
Finally, I gave myself a custom "SmartSession" scope. This is essentially just like session scope, except, it re-autowires every time a bean is pulled out of session (this guards against bean replicas appearing unwired in a failover scenario in a cluster.)
I have come to the conculsion that for session- (and I presume view-) scoped beans to work, you need to make the bean Serializable and mark any #Autowired fields as transient. The SmartSession gives me the confidence in that context to be assured that I stay autowired even in exceptional cases. I based my SmartSession custom scope idea off of this answer: Initialize already created objects in Spring as well as internet sources for how to write custom scopes.
Here's some code snippets to hopefully give you some ideas -
Sample Session-scoped bean:
public class UserProfileContainer implements Serializable {
private static final long serialVersionUID = -6765013004669200867L;
private User userProfile;
public void setUserProfile(User userProfile) {
this.userProfile = userProfile;
}
public User getUserProfile() {
return this.userProfile;
}
}
Bean that references my smartSession-scoped bean:
public class KidProfileEditor implements Serializable {
private static final long serialVersionUID = 1552049926125644314L;
private String screenName;
private String password;
private String confirmPassword;
private String firstName;
private String lastName;
private String city;
private String state;
private String notes;
private String country;
#Autowired
private transient UserProfileContainer userProfileContainer;
}
Snippet from my applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
default-lazy-init="true" >
<!-- BOILERPLATE magic AOP setup tags -->
<context:annotation-config />
<context:component-scan base-package="com.woldrich.kidcompy" />
<aop:aspectj-autoproxy />
<!-- JSF2+Spring custom scope configurations -->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="safetySession">
<bean class="com.woldrich.kidcompy.faces.util.SpringSafetySessionScope"/>
</entry>
</map>
</property>
</bean>
<bean id="userProfileContainer" class="com.woldrich.kidcompy.auth.UserProfileContainer" scope="safetySession">
<aop:scoped-proxy />
</bean>
<bean id="kidProfileEditor" class="com.woldrich.kidcompy.faces.actionview.KidProfileEditor" scope="request" />
</beans>
web.xml snippet:
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee /WEB-INF/includes/schema/web-app_2_5.xsd" id="KidCompy" version="2.5" metadata-complete="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee">
<distributable/>
<context-param>
<description>Allows the Spring Context to load multiple application context files</description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/mainApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
</web-app>
faces-config.xml snippet:
<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 /WEB-INF/includes/schema/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>