Code Of Block Execute Multiple Time in jsf and jboss server [duplicate] - java

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...)

Related

Bypass #Cacheable for (un)authenticated requests

Can Spring's caching framework be made aware of the authentication status of the request context, or is it easier to roll your own caching solution?
Regardless of the fact I find the use case super weird, you can condition caching for pretty much anything that works with SpEL. And since you can call any method you want with SpEL, you're good to go.
I realized that it is harder than it should but the following works. First create a static method that does your check (you can use the SecurityContextHolder for that)
public class SecurityChecker {
public static boolean isSecured() {
// Whatever
return SecurityContextHolder.getContext().getAuthentication() != null;
}
}
Then in your annotated method, specify the following (assuming myCache should be affected):
#Cacheable(cacheNames = "myCache", condition = "T(com.example.SecurityChecker).isSecured()")
public Foo doIt(String key) { ... }
There's two problems currently:
You can't create a meta-annotation to avoid repeating the condition attribute over and over again (see SPR-13475)
The SpEL setup does not allow you to easily call a method on a bean (which would be nicer than calling a static method). I've just created SPR-13812 for that

Perform business logic after getters are called

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.

How to get ID of calling component in the getter method?

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.

How to make Spring accept fluent (non-void) setters?

I have an API which I am turning into an internal DSL. As such, most methods in my PoJos return a reference to this so that I can chain methods together declaratively as such (syntactic sugar).
myComponent
.setID("MyId")
.setProperty("One")
.setProperty2("Two")
.setAssociation(anotherComponent)
.execute();
My API does not depend on Spring but I wish to make it 'Spring-Friendly' by being PoJo friendly with zero argument constructors, getters and setters. The problem is that Spring seems to not detect my setter methods when I have a non-void return type.
The return type of this is very convenient when chaining together my commands so I don't want to destroy my programmatic API just be to compatible with Spring injection.
Is there a setting in Spring to allow me to use non-void setters?
Chris
Thanks to all (and especially Espen who went to a lot of effort to show me the various options within Spring).
In the end, I found a solution myself that doesn't require Spring configuration.
I followed the link from Stephen C then found a reference to the SimpleBeanInfo class within that set of Threads. This class allows a user to write their own bean method resolution code by placing another class in the same package as the class with the non-standard setters/getters to override the logic of with 'BeanInfo' appended onto the classname and implementing the 'BeanInfo' interface.
I then did a search on Google and found this blog which pointed the way. The solution on the blog was quite basic so I padded it out for my purposes.
Per Class (with fluent setters)
public class MyComponentBeanInfo<T> extends SimpleBeanInfo {
private final static Class<?> _clazz = MyComponent.class;
PropertyDescriptor[] _properties = null;
public synchronized PropertyDescriptor[] getPropertyDescriptors() {
if (_properties == null) {
_properties = Helpers.getPropertyDescriptionsIncludingFluentSetters(_clazz);
}
return _properties;
}
public BeanDescriptor getBeanDescriptor() {
return new BeanDescriptor(_clazz);
}
}
PropertyDescriptor generation method
public static PropertyDescriptor[] getPropertyDescriptionsIncludingFluentSetters( Class<?> clazz) {
Map<String,Method> getterMethodMap = new HashMap<String,Method>();
Map<String,Method> setterMethodMap = new HashMap<String,Method>();
Set<String> allProperties = new HashSet<String>();
PropertyDescriptor[] properties = null;
try {
Method[] methods = clazz.getMethods();
for (Method m : methods) {
String name = m.getName();
boolean isSetter = m.getParameterTypes().length == 1 && name.length() > 3 && name.substring(0,3).equals("set") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
boolean isGetter = (!isSetter) && m.getParameterTypes().length == 0 && name.length() > 3 && name.substring(0,3).equals("get") && name.charAt(3) >= 'A' && name.charAt(3) <= 'Z';
if (isSetter || isGetter) {
name = name.substring(3);
name = name.length() > 1
? name.substring(0,1).toLowerCase() + name.substring(1)
: name.toLowerCase();
if (isSetter) {
setterMethodMap.put(name, m);
} else {
getterMethodMap.put(name, m);
}
allProperties.add(name);
}
}
properties = new PropertyDescriptor[allProperties.size()];
Iterator<String> iterator = allProperties.iterator();
for (int i=0; i < allProperties.size(); i++) {
String propertyName = iterator.next();
Method readMethod = getterMethodMap.get(propertyName);
Method writeMethod = setterMethodMap.get(propertyName);
properties[i] = new PropertyDescriptor(propertyName, readMethod, writeMethod);
}
} catch (IntrospectionException e) {
throw new RuntimeException(e.toString(), e);
}
return properties;
}
Advantages to this approach:
No custom spring configuration (Spring is not aware of the non-standard setters and sees them as normal). No dependancy on any Spring .jar files but accessible from Spring.
Just seems to work.
Disadvantages to this approach:
I have to place create a BeanInfo class for all of my API classes with non-standard setters. Luckily there are only around 10 such classes and by moving the method resolution logic into a seperate class I only have one place to maintain.
Closing Thoughts
In my opinion, Spring should deal with fluent setters natively, they don't hurt anyone and it should just ignore the return value.
By requiring that setters be rigidly void, it has forced me to write a lot more boiler plate code than I would have needed otherwise. I appreciate the Bean Specification, but bean resolution is trivial using reflection without even using the standard bean resolver so Spring should offer the option of its own bean resolver that will handle this situations.
By all means, leave the standard mechanism as the default, but offer a one-line configuration option. I look forward to future versions where this might be optionally relaxed.
Is there a setting in Spring to allow me to use non-void setters?
The simple answer is No - there is no such setting.
Spring is designed to be compatible with the JavaBeans spec, and that requires the setters to return void.
For a discussion, refer to this Spring Forums thread. There are possible ways around this limitation mentioned in the forum, but there is no simple solution, and I don't think anyone actually reported that they had tried this and that it worked.
Spring can also be configured with Java configuration.
An example:
#Configuration
public class Config {
#Bean
public MyComponent myComponent() {
return MyComponent
.setID(id)
.setProperty("One", "1")
.setProperty("Two", "2")
.setAssociation(anotherConfig.anotherComponent())
.execute();
}
#Autowired
private AnotherConfig anotherConfig;
#Value("${id}")
private String id;
}
You have a nice immutable object. You have actually implemented the Builder pattern!
Updated to respond to Chris's comment:
I guess it's not exactly what you want, but using properties files solves some issues. See the id field in the example above.
Else, you can use Spring's FactoryBean pattern:
public class MyComponentFactory implements FactoryBean<MyComponent> {
private MyComponent myComponent;
public MyComponentFactory(String id, Property propertyOne, ..) {
myComponent = MyComponent
.setID(id)
.setProperty("One", "1")
.set(..)
.execute();
}
public MyComponent getObject() throws Exception {
return myComponent;
}
public Class<MyComponent> getObjectType() {
return MyComponent.class;
}
public boolean isSingleton() {
return false;
}
}
With the FactoryBean, you shield the configuration from the object returned from the getObject() method.
In the XML configuration, you configure the FactoryBean implementation. In this case with <constructor-arg /> elements.
One simple suggestion, it is customary not to use setters, but the properties names themselves. So have a setter, and have another method for the builder:
component.id("MyId")
.property("One")
.property2("Two")
.association(anotherComponent)
.execute();
As far as I know, there is no simple switch. Spring uses the Beans convention, and expects a void setter. Spring works with beans at the property level via an instance of the BeanWrapper interface. The default implementation, BeanWrapperImpl, uses introspection, but you could create your own modified version that uses reflection to find methods matching your pattern.
EDIT: Looking at the Spring code, BeanWrapperImpl is hard-wired into the bean factories, there is no simple way to replace this with another implementation. However, as spring uses introspection, we can work on getting java.beans.Introspector to produce the results we want. Here are the alternatives in order of decreasing pain:
change the method signature on your setters to comply.
implement your own BeanInfo classes for each of your beans
Use reflection to plug dynamically generated BeanInfo classes into the introspector.
The first two options are probably not really options for you, as they involve quite a lot of changes. Exploring the third option in more detail:
To know which beans are being instantiated by spring, implement your own BeanFactoryPostProcessor. This gets to see all the bean definitions before they are used by the BeanFactory. Your implementation iterates over all the BeanDefinitions in the factor, and fetches the bean class from each definition. Now you know all the classes that are being used.
With a list of classes, you can set about creating your own BeanInfos for these classes. You use the Introspector to generate the default BeanInfo for each class, which would give you read-only properties for your properties with return value setters. You then create a new BeanInfo, based on the original, but with PropertyDescriptors referencing setter methods - your return value setters.
With new beanInfos generated for each class, you need to make sure that the Introspector returns these when asked for the beaninfo for your class. The introspector has a private Map that is used to cache beanInfos. You can get hold of this via reflection, enable access - setAccessible(true) - and add your BeanInfo instances to it - map.put(Class,BeanInfo).
When spring asks the Introspector for the BeanInfo for your bean class, the introspector returns your modified beanInfo, complete with setter methods mapped to your setters with return values.
As others have said, it's not just Spring-friendliness you risk losing. A non-void setter isn't really a setter as far as JavaBeans are concerned, and all sorts of other tools (validators, marshallers, viewers, persisters, whatever else you can dream up) will probably use Introspector and BeanInfo, which expect setters to be null.
With this in mind, how flexible is the requirement that they be called setX? A lot of fluent interfaces in Java use withX instead. If you're using Eclipse, you can probably create a code generation template to make X getX(), void setX(X x), and X withX(X x) for you. If you're using some other codegen tool, I can imagine adding withX fluent setter/getter methods would also be easy.
The with word seems a bit odd, but when you see it alongside a constructor it reads really well.
Request r = new Request().withEndpoint("example.com")
.withPort(80)
.withSSL(false)
.withFoo("My Foo");
service.send(r);
One such API is the AWS SDK for Java, which you can consult for examples. An off-topic caveat is that boolean getters may be called isX, but Boolean getters must be called getX.

JSF: navigation

I have to warn you: the question may be rather silly, but I can't seem to wrap my head around it right now.
I have two managed beans, let's say A and B:
class A
{
private Date d8; // ...getters & setters
public String search()
{
// search by d8
}
}
class B
{
private Date d9; //...getters & setters
public String insert()
{
// insert a new item for date d9
}
}
and then I have two JSP pages, pageA.jsp (the search page) and pageB.jsp (the input page).
What I would like to do is placing a commandbutton in pageB so to open the search page pageA passing the parameter d9 somehow, or navigating to pageA directly after b.insert(). What I would like to do is showing the search result after the insertion.
Maybe it's just that I can't see the clear, simple solution, but I'd like to know what the best practice might be here, also...
I though of these possible solutions:
including **A** in **B** and linking the command button with **b.a.search**
passing **d9** as a **hiddenInput** and adding a new method **searchFromB** in **A** (ugly!)
collapsing the two beans into one
JSF 1.1/1.2 raw doesn't provide an easy way to do this. Seam/Spring both have ways around this and there are a couple of things you can do. JSF 2 should also have solutions to this once it is released.
Probably the easiest and most expedient would be to collapse the two beans into one and make it session scoped. The worry, of course, is that this bean will not get removed and stay in session until the session times out. Yay Memory leaks!
The other solution would be to pass the date on as a GET parameter. For instance, you action method could call the
FacesContext.getCurrentInstance().getExternalContext().redirect("pageB?d9=" + convertDateToLong(d9));
and then get the parameter on the other side.
You should configure the navigation flow in faces-config.xml. In ideal scenario you would return a "status" message which would decide the flow. Read more at following link:
http://www.horstmann.com/corejsf/faces-config.html
http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=/com.businessobjects.integration.eclipse.doc.devtools/developer/JSF_Walkthrough8.html
As far as passing the values from one page to another is concerned you can use backing beans. More about backing beans here:
http://www.netbeans.org/kb/articles/jAstrologer-intro.html
http://www.coderanch.com/t/214065/JSF/java/backing-beans-vs-managed-beans
Hope i have understood and answered correctly to your question
Way to share values between beans
FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
return valueExp.getValue(elContext);
In above code "expression" would be something like #{xyzBean.beanProperty}
Since JSF uses singleton instances, you should be able to access the values from other beans. If you find more details on this technique, I am sure you'll get what you are looking for.
Add commandButton action attribute referencing to B'insert method
<h:commandLink action="#{b.insert}" value="insert"/>
In B'insert method,add d9 parameter as request parameter. Then return an arbitrary string from insert method.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().put("d9", d9);
Then go to faces context and add navigation from B to A with "from-outcome" as the arbitrary String you returned from insert method. But don't add redirect tag to navigation tags as it will destroy the request coming from B and the parameter you added (d9) will be cleared.
<from-outcome>return string of insert method</from-outcome>
<to-view-id>address of A</to-view-id>
Then you might get the "d9" in A class by fetching it from request map at its constructor or in a place where its more appropriate (getters). You might add it into a session scope or place it to a hidden variable if you want to keep track of it later.
in class A, when page is navigated, A should be initialized as it will be referenced.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().get("d9", d9);
Sorry i cant give full code, as i have no ide at here, its internet machine at work. I could not give details therefore.
In my opinion, the simplest way is 3-rd option - have both query and insert methods in same class. And you can do something like that:
public String query () {
//...
}
public String Insert() {
//insert
return Query(); }
If your classes are managed Beans you can load class A from class B and call A.query() in your insert method at the end. Also class A can have
<managed-bean-scope>session</managed-bean-scope>
parameter in faces-config.xml and it wouldn't be instantiated again when loaded.

Categories