aspose file tools*
The moose likes JSF and the fly likes When leaving a page need to set a boolean to false no matter Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "When leaving a page need to set a boolean to false no matter" Watch "When leaving a page need to set a boolean to false no matter" New topic
Author

When leaving a page need to set a boolean to false no matter

Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Hello,

Im very new to JSP/JSF and need some guidance on how to set a boolean in my backer bean to be false. The general situation that I'm in now is , I get some information from the database and populate the page all in a getter on the page. It seems that the getter for values on a jsp are called numerous times . I obviously don't want this to happen multiple times and so i set a boolean to true after the first time it happens. If the user decided to click on a nav link instead of pressing the button on the page, I need to change this boolean back to false. I looked into onunload, but didn't get very far with it. Am I heading in the right direction?

ty
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 60994
    
  65

Please be sure to ask JSF questions in the JSF forum. I have moved this post there for you.


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Was under the impression this was a jsp matter... anyway sry, still need help
Bauke Scholtz
Ranch Hand

Joined: Oct 08, 2006
Posts: 2458
Place them in separate forms or make use of outputlinks instead of commandlinks for navigation.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
The nav links are on a template that i can't change. The only thing i can actually edit is this individual page. I've been trying to add an onunload to the page and I'm having issues with that.

Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

"Joe Random",

We don't have many rules here at the JavaRanch, but we do insist that you use you Real Name and not some sort of "handle" or obvious alias. If you're not sure about this, see
http://www.javaranch.com/name.jsp .

Web applications are quite different from client/server apps, and one of the principal things that makes them different is the "Back" button. You can see it at its worst if you display a page that activates a large and unfriendly program such as Microsoft Excel. Before Microsoft got sued and lost, it was not uncommon for people to display a spreadsheet in the browser - which meant activating an embedded copy of Excel. Once activated, it had to STAY active because you could always use the "Back" button to go back to that page. So Excel would sit around, bloated, eating up resources, whether you ever actually went back or not. Similarly with Java applets or the Adobe Reader, to name 2 other common cases.

In other words, you never really "leave" a page. At best, you create a new one. So there's no notification available. HTTP goes TO places, but because its session continuity is an illusion, there's no real concept of "leaving".

However, there is one possibility. If you can operate the page with the bean in request scope, the semantics will dictate that a new request object will be created each time the page is displayed. Since you're looking for a one-time initialization for the page display, you'll get that, since a new backing bean instance is created for each request and of course, it will not yet be initialized.


Customer surveys are for companies who didn't pay proper attention to begin with.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Tim,

Appreciate the response and I wasn't fully aware of the leaving page illusion. I've tried to use RequestScope Variables, but found everytime past the first time i used the page, i'd always get nulls. I was resetting the RequestScope Variable everytime it entered the page in one of the getters for a faces component. So I was really unsure of as to why i was getting nulls when in my mind i was sure i was setting it. I was doing what i thought was correct in getRequestScope.put(code) and a few lines later when i tried to use the same variable it'd throw a null.

j
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

Request scope is a bit touchy. The data has to go out to the client, then get re-submitted back to the server on the next inbound request. A new Request bean gets build, and the data from the client gets injected into it (along with init stuff from faces-config). Side data that was in the old request bean but not sent to the client is lost.

There are a couple of ways to get around that. You can set up hidden fields to keep data. And some JSF tagsets have additional means to ensure non-visible data gets shuttled back and forth. However, be careful. Anything that gets sent to the client can be snooped/hacked by the client, so no State Secrets! For them, use a session-scope object.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
My codes blowing up here:

String getDIS_Serial() {
**null**> if(getRequestScope().get("populatePage")==null){
System.out.println("setter");
getRequestScope().put("populatePage","false");
}
return DIS_Serial
}

So if I put the value in a hidden field, how would that stop this null from happening?
Bauke Scholtz
Ranch Hand

Joined: Oct 08, 2006
Posts: 2458
Or the Tomahawk's t:saveState to simulate the conversation scope.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

Jason Delboch wrote:My codes blowing up here:

String getDIS_Serial() {
**null**> if(getRequestScope().get("populatePage")==null){
System.out.println("setter");
getRequestScope().put("populatePage","false");
}
return DIS_Serial
}

So if I put the value in a hidden field, how would that stop this null from happening?


Ouch. Create a hidden field named "populated" on the page. Back it with a property named "populated" in the backing bean. Lose the clever code and replace it with simple setPopulated(boolean value)/boolean isPopulated() methods. Set the "populated" property in the bean when you've finished populating the data.

There's also an annotation - I believe it's "@PostCreate". A method tagged with this annotation will be invoked after the bean has been constructed and injected, so it's also a good way to manage dataset population. However, I believe you need JSF 1.2 to use it.

Incidentally, you cannot keep a JDBC connection object across Requests - Connection is an Interface, not an Object, so it's not serializable. The same applies to ResultSets.

ORM database results can be detached and serialized, but generally shouldn't be passed between client and server because A) the extra traffic will slow down page response speed and load your network and B) like I said, if it goes to the client, an evil client can misuse it.

If you use one of the various state-management JSF tags available, they also usually require serializable data.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Tim,

It's not an option for me to change the page to request scope, it must stay in session scope(this is not up to me). Which is making me think im in a heap of trouble with my original problem. How can i reset this variable when i come back to the page everytime? The page is in sessionScope, which i believe is why my declarations and constructor are only called on the original call to the page. I'm looking into the jsf tagsets you were talking about related to hidden fields and the annotation.

thnx,
Jason
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

A session scope object is constructed when first referenced and remains until the session is destroyed by logout (session.invalidate()) or timeout on the server. Assuming that an explicit call to remove the session object wasn't made.

The other methods in a session object get called as needed.

You can't detect when a page is exited, but when you transfer into a page that references a session object, you can warn the session object you're coming.

The easy way to do that is to inject the session object into the "from" backing bean, then fire off a "prepareForDisplay" method that you've created in the target object to detect page entry. You'd invoke that method as part of the action processor that transferred you to the page you're interested in.

There are some disadvantages to that approach. First, it means that the session object will get created even earlier, since the framework has to construct it before it can be injected. Secondly, any entry into the page that doesn't originate from your pre-defined point(s) won't (obviously!) have called your "prepareForDisplay" method.

Some of this ugliness I hope will eventually be solved. Some of it we're stuck with until something more suitable than HTTP comes along.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
So i was just informed we have jsf 1.0 , which means i can't use annotations. The prepareForDisplay method makes sense, although i can't honestly say i totally understand injection. So would I basically just create a new object in the 'from' page? Also if I make two objects from the same backerbean, which one will I actually be going to? Confused on some stuff, been reading , but alot of info.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

The annotations would not help here. @PostCreate - or maybe it's @PostConstruct (I can't remember) is only called once.

Injection is simply the act of having an outside mechanism connect 2 objects. In the case of JSF, that's commonly the JSF framework. It would construct the 2 beans of interest, then inject the first bean into the second by invoking a setter mechanism. So the second bean will contain an instance of the first bean. The advantage of injection is that the framework is usually something that's configured by a declarative construct such as the faces-config.xml file. If you wanted to temporarily replace "FirstBean" with a "TestFirstBean" and they implemented a common interface or superclass, you could simply modify the declaration without having to recompile code.

Within a JSF context, each named bean is unique. You can make 2 different instances of a bean, but each will have its own name, and you inject by name, so there's no confusion. Here's a an example that's actually close to something I'm doing right now:

FirstBean:


SecondBean:


And here's how to initialize them and wire them together (faces-config)


When referenced in a JSF page, the epxression:

#{targetBean.bean1.message}, #{targetBean.bean2.message}!

Will output:

Hello, World!

Or, if you prefer:

<h:outputText value="#{targetBean.bean1.message + ','+ targetBean.bean2.message + '!'}"/>

Although in practice, I recommend adding a "getHelloWorld()" method to targetBean and letting it do the message formatting.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Tim,

Thats a super useful example, most appreciated. That will totally help me when the user goes from the 'from' page. Now I'm still stuck on how to deal with this boolean when users leave the page via template links. If i turn the 'from' page into requestScope and declare the boolean there, then in turn make an instance of that object in the main page im dealing with. Wouldn't that fix my issue because everytime I made the object the boolean would be false, because the page would be requestScope right?

Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

Hmmm. I'm not sure I got all that. There are a couple of "gotchas" that I think are going to interfere.

Gotcha #1 is that you can't inject a short-lived bean into a longer-lived bean. So while you can inject a session-scope bean into a request-scope bean, you can't do the opposite. Although I don't quite have what you described mapped out in my head, I'm thinking that you're going to run into that.

Gotcha #2 is basic HTTP. Like I said, there's no real way to tell when you're exiting a page, since every HTTP request/response is self-contained. HTTP sessions are just a way to hack up a workflow between requests. To actually get a departure notification, you'd need a commandLink (since it fires an action in the backing bean) or alternatively, some sort of JavaScript onclick handler on the displayed page.

Here's something that may work better.

Get a copy of prettyfaces. It's an open-source product that allows JSF pages to be accessed by direct URLs. It's easy to install - just drop the jar into the project, set up the prettyfaces filter in the web.xml and create a pretty-config.xml file (in WEB-INF) to map the direct URLs. Here's a sample mapping:


What this does is invoke the "setupSearch" method on the search backing bean. This will be done after the search bean is constructed and injected, which is pretty much what you're looking for. If you then use an commandAction or commandLink on the actual page, it will use a JSF URL, bypassing the setup function on subsequent requests, since in order to invoke the setup method, you have to use your setup URL. It's also handy because it's bookmarkable. You can do a direct jump to it from anywhere (including other web sites or your browser favorites) and be assured that the required setup will be done.

IIRC, prettyfaces is located on SourceForge. If not, it's easily found via Google.
Jason Delboch
Greenhorn

Joined: Apr 01, 2009
Posts: 9
Tim,

Basically what im trying to say is...

Page1 - the from page - RequestScope

Page2 - the page im populating with data and main concern - SessionScope

So the flow is , i enter a serial num on page1 and a table with rows pops up displaying records dealing with that serial.
I then click on the table row i want to goto, in turn im brought to page2 with all the data displayed in the respective inputbox.

So let me describe more clearly what my situation is:
When i populate page2, I'm doin a select on a db table to do so. I have this done inside a getter on the page. In order for this to only happen once I use a boolean to check if its false do the db stuff and then set to true so it wont go through again. Because theres going to be 20-40 people running the application at the sametime and that would be bad news if it happened more than once. Since this page is sessionScope after the initial call, the constructor is never called again and like wise with the pageScope variables. A boolean wont be reset to false if I come back to this page. I can't always guarunte the user will click the given buttons on the page i can use to reset the bool back to false. They may click on the template links and leave the page that way, in which i need to deal with that also. I was propsing that I make the boolean i need to reset in Page1 and inject it in page2 (which you just said i can't). Can i possibly then, in the constructor for page1 have the boolean initialized there, create a Page1 object in Page2 and then call a getter on the object to get the boolean? I'm trying to get this to work anyway I can simply because I'm put inside this box of having to use jsf,not being able to change the scope or installing prettyfaces(which sounds cool to try) - really I'm stuck using what I've got to do it. I've tried onunload and an array of other stuff, but no luck. The only issue with doing what I proposed is im not exactly sure on the lifetime of the object of type page1. Lemme know if that cleared up things alittle more.

thnx,
Jason
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16012
    
  19

I do a lot of that, but I don't keep the item under edit in a separate backing bean - I make it a property of the originating bean (which is session scope). The originating bean manages the search and table display, then when you select a row in the table, I set the detail item using the getSelectedItem method on the table model, then dispatch the action to the detail editing page, but still using the original backing bean. So the edit fields are named things like "search.item.id", "search.item.title", etc. This works especially well when the table item is either an ORM model object or a front for an ORM model object, but it applies to any persistent storage, including raw JDBC.

To see this sort of tactic in use, check out Rick Hightower's multi-part series "JSF for Nonbelievers" at IBM Developerworks. I'll admit that I think it's kind of warty, but it works and there is a definite method to the madness.
 
jQuery in Action, 2nd edition
 
subject: When leaving a page need to set a boolean to false no matter