I would like to write my business logic after the getters and setters are called (twice),
because I use their object values inside the business logic.
However Construct, Post construct, actionevents,.. are called before the getters.
So how can I use the values of the getters if I don't want to write business logic inside them?
I want to navigate to the site and get data from a database displayed into outputText.
Do the job in (post)constructor of the bean.
#ManagedBean
#RequestScoped
public class Bean {
private String data;
#EJB
private SomeService service;
#PostConstruct
public void init() {
data = service.load();
}
// Getter.
}
with
<h:outputText value="#{bean.data}" />
When I change a (primefaces)selectOneMenu value the bean gets the selectOneMenu's value and performs a query in the database for this value, and writes the query result inside the outputText.
Do the job in the ajax listener method of the bean which is attached to input component's change event.
#ManagedBean
#ViewScoped
public class Bean {
private String selectedItem;
private String result;
#EJB
private SomeService service;
public void changeSelectedItem(AjaxBehaviorEvent event) {
result = service.find(selectedItem);
}
// Getters+setter.
}
with
<p:selectOneMenu value="#{bean.selectedItem}">
<f:selectItems ... />
<p:ajax listener="#{bean.changeSelectedItem}" update="result" />
</p:selectOneMenu>
<h:outputText id="result" value="#{bean.result}" />
Doing it after the getters are called would be too late. JSF would at that point already be finished with rendering the HTML output. You can't change the HTML output afterwards.
You are making a basic mistake in your thinking.
There is no such phase as "The Getters". Getters are just a convention to read a property of a bean.
Those properties can be read individually throughout the entire request. Some may be consulted as early as during "create/restore view", while others may be consulted during "render response".
There is no such thing as that JSF in one particular phase does a sweep through your code and for the fun of it calls every getter it finds.
The solution for you is to let this thinking go. I know it might be hard to let go of something you think is true, but inhale, clear you mind, say goodbye to your current understanding of how things work, and just re-learn from scratch.
You'll then find the answer yourself in no-time. Good luck!
Did not understand your question fully, but obvious way is to put logic in getters and setters.
Related
App running with JSF, Primefaces, eclipselink, not a small app, about 100 pages/bean all working perfectly
I got some troubles understanding how my #ViewScoped page works, I got a select UI component, filled with a simple List<People> and a back-end selectedPeople in my bean
// all getters, setters, JPA annotations, all good
public class People {
private String name;
private List<Car> cars;
}
#ManagedBean
#ViewScoped
public class PeopleBean {
#EJB
private Service sPeople;
private People selectedPeople;
private List<People> listPpl;
#PostConstruct
public void init(){
listPpl = sPeople.readAll(); // always good, same as DB values
}
public People getSelectedPeople(){
return selectedPeople;
}
public People setSelectedPeople(People p){ // p is an old element
selectedPeople = p; // BREAKPOINT
}
// getter for the list too
public void method(){
Logger.getAnoymousLogger().severe(selectedPeople.getCars()); // the one the old people, not the ne contained in the actual list
}
}
<p:selectOneMenu id="selectP" value="#{peopleBean.selectedPeople}" converted="#{genericSecuerdConverter}" >
<p:ajax event="change" partialSubmit="true" listener="#{peopleBean.method()}" />
<f:selectItems value="#{peopleBean.listPpl}" var="people" itemLabel="#{people.name}" itemValue="#{people}" />
</p:selectOneMenu>
Sequence of use and problem is (information taken from debugging) :
go to peoplePage.xhtml where the select element is, IDs of the list's element are #410, #411, #412 (3 peoples)
go to modif.xhtml, change the 3rd people (remove a car, saved in DB (check in DB))
come back to peoplePage.xhtml, list is OK, IDs in debug are #650, #651, #652
change the value (from null) of the selectUI to choose a people, and at the breakpoint, p appears to be the #412 element, so the changes on its car's list are not visible, it does not come from the listPpl (because contains only valid elements and corresponds to DB), it's kind of caching
I tried to disable ecpliselink cache as states EclipleLink cache
change eclipselink property
change JPA propery
use #Cacheable(false)
No one had an effect, nor go to private navigation neither clear the browser cache and come back to the page, the p element is still the old one from first loading
I thought #ViewScoped allows to open a page each time as if it was the first time, but seems not, can't figure where the element can be stored/cached
Edit I used a workaround for the moment but this is obviously o the best solution
public People setSelectedPeople(People p){
if(p!=null)
selectedPeople = sPeople.read(p.getId());
}
What you are looking for is #RequestScoped. It will create everything each and every time you do a suitable HTTP request. Otherwise it is not guaranteed to destroy the #ViewScoped beans. An example in the Omnifaces documentation: ViewScoped.
This feature could be used to help the recreation of the page when the user is using the back and forward buttons of the browser for example.
#RequestScoped
Bean lives as long as the HTTP request-response lives. It gets created upon a HTTP request and gets destroyed when the HTTP response associated with the HTTP request is finished.
#ViewScoped
Bean lives as long as the user is interacting with the same JSF view in the browser window/tab. It gets created upon a HTTP request and gets destroyed once the user postbacks to a different view.
Source of descriptions: https://www.tutorialspoint.com/jsf/jsf_managed_beans.htm
Let's say I specify an outputText component like this:
<h:outputText value="#{ManagedBean.someProperty}"/>
If I print a log message when the getter for someProperty is called and load the page, it is trivial to notice that the getter is being called more than once per request (twice or three times is what happened in my case):
DEBUG 2010-01-18 23:31:40,104 (ManagedBean.java:13) - Getting some property
DEBUG 2010-01-18 23:31:40,104 (ManagedBean.java:13) - Getting some property
If the value of someProperty is expensive to calculate, this can potentially be a problem.
I googled a bit and figured this is a known issue. One workaround was to include a check and see if it had already been calculated:
private String someProperty;
public String getSomeProperty() {
if (this.someProperty == null) {
this.someProperty = this.calculatePropertyValue();
}
return this.someProperty;
}
The main problem with this is that you get loads of boilerplate code, not to mention private variables that you might not need.
What are the alternatives to this approach? Is there a way to achieve this without so much unnecessary code? Is there a way to stop JSF from behaving in this way?
Thanks for your input!
This is caused by the nature of deferred expressions #{} (note that "legacy" standard expressions ${} behave exactly the same when Facelets is used instead of JSP). The deferred expression is not immediately evaluated, but created as a ValueExpression object and the getter method behind the expression is executed everytime when the code calls ValueExpression#getValue().
This will normally be invoked one or two times per JSF request-response cycle, depending on whether the component is an input or output component (learn it here). However, this count can get up (much) higher when used in iterating JSF components (such as <h:dataTable> and <ui:repeat>), or here and there in a boolean expression like the rendered attribute. JSF (specifically, EL) won't cache the evaluated result of the EL expression at all as it may return different values on each call (for example, when it's dependent on the currently iterated datatable row).
Evaluating an EL expression and invoking a getter method is a very cheap operation, so you should generally not worry about this at all. However, the story changes when you're performing expensive DB/business logic in the getter method for some reason. This would be re-executed everytime!
Getter methods in JSF backing beans should be designed that way that they solely return the already-prepared property and nothing more, exactly as per the Javabeans specification. They should not do any expensive DB/business logic at all. For that the bean's #PostConstruct and/or (action)listener methods should be used. They are executed only once at some point of request-based JSF lifecycle and that's exactly what you want.
Here is a summary of all different right ways to preset/load a property.
public class Bean {
private SomeObject someProperty;
#PostConstruct
public void init() {
// In #PostConstruct (will be invoked immediately after construction and dependency/property injection).
someProperty = loadSomeProperty();
}
public void onload() {
// Or in GET action method (e.g. <f:viewAction action>).
someProperty = loadSomeProperty();
}
public void preRender(ComponentSystemEvent event) {
// Or in some SystemEvent method (e.g. <f:event type="preRenderView">).
someProperty = loadSomeProperty();
}
public void change(ValueChangeEvent event) {
// Or in some FacesEvent method (e.g. <h:inputXxx valueChangeListener>).
someProperty = loadSomeProperty();
}
public void ajaxListener(AjaxBehaviorEvent event) {
// Or in some BehaviorEvent method (e.g. <f:ajax listener>).
someProperty = loadSomeProperty();
}
public void actionListener(ActionEvent event) {
// Or in some ActionEvent method (e.g. <h:commandXxx actionListener>).
someProperty = loadSomeProperty();
}
public String submit() {
// Or in POST action method (e.g. <h:commandXxx action>).
someProperty = loadSomeProperty();
return "outcome";
}
public SomeObject getSomeProperty() {
// Just keep getter untouched. It isn't intented to do business logic!
return someProperty;
}
}
Note that you should not use bean's constructor or initialization block for the job because it may be invoked multiple times if you're using a bean management framework which uses proxies, such as CDI.
If there are for you really no other ways, due to some restrictive design requirements, then you should introduce lazy loading inside the getter method. I.e. if the property is null, then load and assign it to the property, else return it.
public SomeObject getSomeProperty() {
// If there are really no other ways, introduce lazy loading.
if (someProperty == null) {
someProperty = loadSomeProperty();
}
return someProperty;
}
This way the expensive DB/business logic won't unnecessarily be executed on every single getter call.
See also:
Why is the getter called so many times by the rendered attribute?
Invoke JSF managed bean action on page load
How and when should I load the model from database for h:dataTable
How to populate options of h:selectOneMenu from database?
Display dynamic image from database with p:graphicImage and StreamedContent
Defining and reusing an EL variable in JSF page
Measure the render time of a JSF view after a server request
With JSF 2.0 you can attach a listener to a system event
<h:outputText value="#{ManagedBean.someProperty}">
<f:event type="preRenderView" listener="#{ManagedBean.loadSomeProperty}" />
</h:outputText>
Alternatively you can enclose the JSF page in an f:view tag
<f:view>
<f:event type="preRenderView" listener="#{ManagedBean.loadSomeProperty}" />
.. jsf page here...
<f:view>
I have written an article about how to cache JSF beans getter with Spring AOP.
I create a simple MethodInterceptor which intercepts all methods annotated with a special annotation:
public class CacheAdvice implements MethodInterceptor {
private static Logger logger = LoggerFactory.getLogger(CacheAdvice.class);
#Autowired
private CacheService cacheService;
#Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
String key = methodInvocation.getThis() + methodInvocation.getMethod().getName();
String thread = Thread.currentThread().getName();
Object cachedValue = cacheService.getData(thread , key);
if (cachedValue == null){
cachedValue = methodInvocation.proceed();
cacheService.cacheData(thread , key , cachedValue);
logger.debug("Cache miss " + thread + " " + key);
}
else{
logger.debug("Cached hit " + thread + " " + key);
}
return cachedValue;
}
public CacheService getCacheService() {
return cacheService;
}
public void setCacheService(CacheService cacheService) {
this.cacheService = cacheService;
}
}
This interceptor is used in a spring configuration file:
<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut">
<bean class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
<constructor-arg index="0" name="classAnnotationType" type="java.lang.Class">
<null/>
</constructor-arg>
<constructor-arg index="1" value="com._4dconcept.docAdvance.jsfCache.annotation.Cacheable" name="methodAnnotationType" type="java.lang.Class"/>
</bean>
</property>
<property name="advice">
<bean class="com._4dconcept.docAdvance.jsfCache.CacheAdvice"/>
</property>
</bean>
Hope it will help!
Originally posted in PrimeFaces forum # http://forum.primefaces.org/viewtopic.php?f=3&t=29546
Recently, I have been obsessed evaluating the performance of my app, tuning JPA queries, replacing dynamic SQL queries with named queries, and just this morning, I recognized that a getter method was more of a HOT SPOT in Java Visual VM than the rest of my code (or majority of my code).
Getter method:
PageNavigationController.getGmapsAutoComplete()
Referenced by ui:include in in index.xhtml
Below, you will see that PageNavigationController.getGmapsAutoComplete() is a HOT SPOT (performance issue) in Java Visual VM. If you look further down, on the screen capture, you will see that getLazyModel(), PrimeFaces lazy datatable getter method, is a hot spot too, only when enduser is doing a lot of 'lazy datatable' type of stuff/operations/tasks in the app. :)
See (original) code below.
public Boolean getGmapsAutoComplete() {
switch (page) {
case "/orders/pf_Add.xhtml":
case "/orders/pf_Edit.xhtml":
case "/orders/pf_EditDriverVehicles.xhtml":
gmapsAutoComplete = true;
break;
default:
gmapsAutoComplete = false;
break;
}
return gmapsAutoComplete;
}
Referenced by the following in index.xhtml:
<h:head>
<ui:include src="#{pageNavigationController.gmapsAutoComplete ? '/head_gmapsAutoComplete.xhtml' : (pageNavigationController.gmaps ? '/head_gmaps.xhtml' : '/head_default.xhtml')}"/>
</h:head>
Solution: since this is a 'getter' method, move code and assign value to gmapsAutoComplete prior to method being called; see code below.
/*
* 2013-04-06 moved switch {...} to updateGmapsAutoComplete()
* because performance = 115ms (hot spot) while
* navigating through web app
*/
public Boolean getGmapsAutoComplete() {
return gmapsAutoComplete;
}
/*
* ALWAYS call this method after "page = ..."
*/
private void updateGmapsAutoComplete() {
switch (page) {
case "/orders/pf_Add.xhtml":
case "/orders/pf_Edit.xhtml":
case "/orders/pf_EditDriverVehicles.xhtml":
gmapsAutoComplete = true;
break;
default:
gmapsAutoComplete = false;
break;
}
}
Test results: PageNavigationController.getGmapsAutoComplete() is no longer a HOT SPOT in Java Visual VM (doesn't even show up anymore)
Sharing this topic, since many of the expert users have advised junior JSF developers to NOT add code in 'getter' methods. :)
If you are using CDI, you can use Producers methods.
It will be called many times, but the result of first call is cached in scope of the bean and is efficient for getters that are computing or initializing heavy objects!
See here, for more info.
You could probably use AOP to create some sort of Aspect that cached the results of our getters for a configurable amount of time. This would prevent you from needing to copy-and-paste boilerplate code in dozens of accessors.
If the value of someProperty is
expensive to calculate, this can
potentially be a problem.
This is what we call a premature optimization. In the rare case that a profiler tells you that the calculation of a property is so extraordinarily expensive that calling it three times rather than once has a significant performance impact, you add caching as you describe. But unless you do something really stupid like factoring primes or accessing a databse in a getter, your code most likely has a dozen worse inefficiencies in places you've never thought about.
I would also advice using such Framework as Primefaces instead of stock JSF, they address such issues before JSF team e. g in primefaces you can set partial submit. Otherwise BalusC has explained it well.
It still big problem in JSF. Fo example if you have a method isPermittedToBlaBla for security checks and in your view you have rendered="#{bean.isPermittedToBlaBla} then the method will be called multiple times.
The security check could be complicated e.g . LDAP query etc. So you must avoid that with
Boolean isAllowed = null ... if(isAllowed==null){...} return isAllowed?
and you must ensure within a session bean this per request.
Ich think JSF must implement here some extensions to avoid multiple calls (e.g annotation #Phase(RENDER_RESPONSE) calle this method only once after RENDER_RESPONSE phase...)
Right now I use the f:viewParam tag to inject the request parameter into a field of my bean
<f:viewParam name="id" value="#{surveyController.id}" />
But I would much rather prefer to use annotations for this. I know about the #Value annotation, and I guess I could do something like this
#Component
#Scope("view")
public class SurveyControlador {
#Value("#{new Long.parseLong('${param.id}')}")
private Long id;
....
}
But this is just plain ugly.
Is there a better way, where I don't need to convert the value explicitly, and maybe even omit the "param"? I'm even willing to install third party libraries
I've used omnifaces' #Param successfully, like so:
#Named #ViewScoped
public class SurveyController {
#Inject #Param(name = "id")
private ParamValue<Long> idParam;
public void doStuff() {
if (idParam.getValue().equals(1)) {
throw new IllegalAccessException("you don't dare");
}
}
}
Pro: You additionally get access to the raw submitted value and omnifaces optionally applies validations/conversions (check the docs).
Con: Wrapper around your real parameter. And you still need to specify <f:viewParam> (you don't need to bind it to a backing bean, tho) if you want to keep the parameter for navigation.
Note that this leverages CDI, which may or may not fit the way you do things.
I'm just trying to port a tiny desktop app of mine to web.
Since days I'm trying to find out how I can make use of the builder pattern (I already have) in JSF?
Or do I have to refactor to Bean Entities and cannot use Builder?
Consider following code:
public class MyFacade {
private MyClass bar;
publich save() {
crudService.persist(bar);
}
}
<h:inputText id="name" value="#{MyFacade.bar.property}" />
//submit button
I want so store text field values to my DB / entities of course. Which is quite easy if you have normal backend beans.
But what if I create my objects like the following?
MyClass newObject = MyClass.Builder("mandatory field").setOptionalFields("optional field").build();
How can I make use of this in jsf, if at all?
Thanks lot
If I understand you correctly you should introduce another type of beans into your JSF application just for interaction with your view and leave your facade (dao) beans as they are.
You would end up with something like this:
#RequestScoped
public class YourBean{
#Inject
private MyFacade facade;
//bean created with builder
private MyBean bean;
public String someMethodExecutedwithEL(){
//build your object here and save it with the dao layer
facade.save(objectFromBuilder);
}
#PostConstruct
public void init(){
//create your bean with builder pattern
}
}
Example above is of course just a scribbled idea, the point is that there is nothing stopping you from creating your objects using builder pattern, just introduce another layer for separation of concerns.
EDIT:
If you want to create your objects before they are used on the jsf page you can add method annotated #PostConstruct
(updated the code sample as well)
Possibilities are endless.
Tip - consider naming your classes and variables using standard naming conventions and common sense.
Given the following example:
<h:inputText id="foo" size="#{configBean.size}" />
I would like to get the id of the calling component foo in the getter method so that I can return the size from a properties file by a key of foo.length.
public int getSize() {
String componentId = "foo"; // Hardcoded, but I should be able to get the id somehow
int size = variableConfig.getSizeFor(componentId);
return size;
}
How can I achieve this?
Since JSF 2.0, there's a new implicit EL variable in the component scope: #{component} which refers to the current UIComponent instance. Among its getter methods there's a getId() which you need.
So you can just do:
<h:inputText id="foo" size="#{configBean.getSize(component.id)}" />
with
public int getSize(String componentId) {
return variableConfig.getSizeFor(componentId);
}
Alternatively you can also make the variableConfig an #ApplicationScoped #ManagedBean so that you can just do:
<h:inputText id="foo" size="#{variableConfig.getSizeFor(component.id)}" />
(using the full method name in EL instead of the property name is necessary whenever you want to pass arguments to the method, so just variableConfig.sizeFor(component.id) won't work, or you must rename the actual getSizeFor() method to sizeFor() in the class)
I think the answer BalusC gave is the best possible answer. It shows one of the many small reasons why JSF 2.0 is such a big improvement over 1.x.
If you're on 1.x, you could try an EL function that puts the ID of the component into the request scope under some name your backing bean method can pick up.
E.g.
<h:inputText id="foo" size="#{my:getWithID(configBean.size, 'foo')}" />
The EL method's implementation could look something like this:
public static Object getWithID(String valueTarget, id) {
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
context.getExternalContext().getRequestMap().put("callerID", id);
ValueExpression valueExpression = context.getApplication()
.getExpressionFactory()
.createValueExpression(elContext, "#{"+valueTarget+"}", Object.class);
return valueExpression.getValue(elContext);
}
In this case, whenever the getSize() method of the config bean is called, the ID of the calling component would be available via "callerID" in the request scope. To make it a little neater you should maybe add a finally block to remove the variable from the scope after the call has been made. (note that I didn't try the above code, but it hopefully demonstrates the idea)
Again, this would be a last resort when you're on JSF 1.x. The cleanest solution is using JSF 2.0 and the method BalusC describes.