my dog learned polymorphism*
The moose likes JSF and the fly likes Using redirect from backing bean and getting IllegalStateException error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Using redirect from backing bean and getting IllegalStateException error" Watch "Using redirect from backing bean and getting IllegalStateException error" New topic
Author

Using redirect from backing bean and getting IllegalStateException error

Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

I am trying to validate a value in the request and if the value is NOT validated then I need to redirect the user in the web app to another page. In every instance I am getting an java.lang.IllegalStateException error. In googling for this error it was stated that I need to responeComplete() before and some stated after the redirect(URL). But trying both ways, I still get the IllegalStateException error. Obviously, I'm not understanding how to implement the responseComplete() method properly so that the redirect works.

Any help/direction would be greatly appreciated. Here is the code that I have if the value in the request is NOT validated and the BOLDED line below is where I am getting the IllegalStateException error whether I put the responseComplete() before or after this line of code:





Thanks in advance for any help/direction. Regards.
Ilari Moilanen
Ranch Hand

Joined: Apr 15, 2008
Posts: 198
I do not know why you setup does not work but I can tell how I am doing the redirect myself

http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/javax/faces/application/NavigationHandler.html

The only time I use the servlet response is when I want to write the result myself (writing pdf files to outputstream for example) and after I've written it I use the reponseComplete() method you mentioned.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

Thanks so much for the reply. Sorry for the delay in responding as I've been in an unscheduled meeting all day.

When I tried to use your code I forgot to explain that I'm having to return a string value to the method and I'm not sure what to return and get my page redirected.

Does this code not REDIRECT to defined redirect page before the app page is loaded? That is what I'm trying to accomplish or am I going about this all wrong?

Here is my full code:



Thanks so much again for any help/direction.
Ilari Moilanen
Ranch Hand

Joined: Apr 15, 2008
Posts: 198
The page returned has no meaning since JSF does not define where ii is going with the returned value but with the value you used in navigation handler. Or at least so it goes with JSF 2.
But since it does not matter your code should work as it is. But have you tested it?
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

Yes. I am running on JSF 1.1 not 2.0 since I'm running in IBM RAD. My understanding by talking to someone else on another list is that because my initial page has already started to render then I will not be able to get past the IllegalStateException. When I use your code the index.jsp and NOT the validationFailed.jsp page is rendered therefore going into my application which is where I do NOT want this user.

I am being told that I need to create a servlet Filter in order to do this before my page even starts to get rendered. So now I'm trying to figure out how to do that. This is such a beating. Unfortunately, JSF is not very easy to work with.
Ilari Moilanen
Ranch Hand

Joined: Apr 15, 2008
Posts: 198
I understood that you might be using JSF 1 so I checked first that the navigation handler even exists in JSF 1.

But the behavior has changed somewhat between JSF 1 and JSF 2 and since I have never used JSF 1 I have problems with that. In JSF 2 the action methods can return the outcome of the action (defined in faces-context) or the name of the page directly. But in JSF 1 (if I have understood it correctly) the actions return only outcomes. So is you method (getValueID()) action method? If it is can't it return the outcome that maps to the navigationFailure.jsp directly without redirects? (Or is the validationFailed.jsp even part of your JSF application?) If your method is not action method you can still use the navigation handler object and make it return the (predifened) outcome of the validationFailed.jsp page (and not the name of the page itself as you have done.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

Thanks for the reply. The getValueID is definitely an action method. And the validationFailed.jsp is within my application. I guess I'm stuck. I am looking into doing this via a servlet Filter and hopefully that will work.

I appreciate all your time and help on this issue. Regards.

B Nirvan
Ranch Hand

Joined: Oct 20, 2010
Posts: 82
Melinda,
What you should be doing is forwarding the request to "/validationFailed.jsp" page rather than doing a redirect. There is a difference between a forward and a redirect. Redirect requires an additional trip to browser before the intended page can be served. I have to say that you should validate your value before the page that you are intending to show up (both normal page and error page) starts to load. This means that your getValueID() should not be bound to any of your jsf page. If your getValueID() is value bound to any of the property of JSF page, then you are too late to validate it in the getValueID(). Perhaps that is why you are getting an IllegalStateException.
Secondly, when you use JSF navigation via handle navigation or otherwise, prior to JSF 2.0, you would require a navigation rule to be configured in faces-config.xml. The configuration is very simple. Here is an example


Once you configure your faces-config.xml, you have to return strings "success" or "error"(or anything you defined in faces-config.xml) from the action method(the method in your backing bean that is processing the request). JSF will handle the navigation.

regards,
Nirvan.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Your IDE should not be defining the limits of what you can do. IDEs are supposed to assist people, not replace competence. Your production target server options may be limiting you, but the IDE should not be a choke point.

However, this looks like the all-too-common case of trying to make a complex technology solution out of a problem with everyday simple (for JSF) solutions. Rule of thumb: anytime you find yourself including javax.faces components other than models, you may be doing things the hard way.

Firstly. JSF is predicated on an all-or-nothing data validity model. That is, the backing bean should not be updated nor the action processor (or listeners) be fired unless ALL data being passed to the bean has been confirmed valid. So for the bulk of JSF data input use cases, a Validator is a better solution.

Displaying a new page is generally not going to be desirable because it means that at a minimum you're hiding the data you were inputting and in the worst case, actually discarding it.

Although I'm not a big proponent of pop-up windows (I open them in new tabs), if you need extended help on a field, I'd generally go for a pop-up help dialog over a whole new page. You can also show/hide help panes and/or overlay panels. Some JSF extension frameworks allow modal dialogs on pages, too.

Because (as I mentioned) action processors shouldn't be fired when any of the data is invalid, using them for "redirect" operations isn't what I'd recommend. They're not really redirections anyway, they're simply page responses which present a new View. And forcing yourself out of JSF and down into low-level HTTP functions should only be done as a last resort. It makes the code more complex and more framework-dependent.


Customer surveys are for companies who didn't pay proper attention to begin with.
Ilari Moilanen
Ranch Hand

Joined: Apr 15, 2008
Posts: 198
And maybe I could have been more precise myself. What I proposed (and Nirvan Buddha showed in more detail) is not redirecting but choosing the page to show to user. And it is basic JSF so it should not be complicated and if it is then maybe JSF is a complicated framework as you suggested. I do not think so myself though...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Well, in the case of simply selecting which View to present next, you can't get much simpler than the JSF navigation system, short of hard-coding the destinations. And that would eliminate your ability to construct independent components that can be wired together. You have the same basic concept in play when you setup servlet configurations in web.xml where you use abstract linkages to map URLs and parameters to servlets.

The sticking point was, as I mentioned, the use of the word "validation". In the JSF term that's basically referring to elementary validation. When something's valid as an individual item, but not proper for a given business context, that's a different animal altogether and JSF doesn't get into that.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

I changed my code to:



I also changed my faces-config.xml file to include this navigation-rule:



I moved the valueID property that I was populating from the backing bean above to another backing bean on my JSP page but it calls the getValueID() in the backing bean above:



In my JSP page I now have:



instead of value="#{valueBean.valueID}"

However, I AM NOT forwarded to the "/validationFailed.jsp" page but to the /index.jsp page where in my valueID field in my JSP page I get the word "failed". The forward is not working either from the navigation-rule. I had tried this early on in this process but could not make it work.

Do you see what I'm doing wrong in the code above?

Thanks.
When I start my page from the browser
B Nirvan
Ranch Hand

Joined: Oct 20, 2010
Posts: 82
Melinda,
Your index.jsp might be submitted using a commandButton(using action=#{yourBean.yourMethod}, if not, neglect these steps and let me know how you are submitting the index.jsp.

In the action method validate using getValueID() and store valueID in an instance variable in yourBean, if valid. If not valid, return "failed" from that method. So your actionMethod() will look like this.



The getter method in your backing bean should only return valueID. Thats it.

In short, validate in action method and return the valueID obtained through the getter in your backing bean.

regards,
Nirvan.


Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

I'm going to say the exact same thing as Nirvan, slightly differently, since it seems like you're confused.

Backing beans are POJOs. So the set/get methods set and get properties in the beans. That's all they're intended for, and in fact, if you attempt to do anything more than that, you can get into trouble.

Action methods are where your logic goes. When a form is submitted, the action method that's bound to the submit button is fired IF AND ONLY IF the bean validators accept whatever data is being posted (via the setter methods) to the backing bean. And that data will ONLY be posted if ALL validators approve of all the data. In the case of an "immediate" submit, that doesn't apply. The data isn't posted, the bean isn't update, just the action gets called.

The action returns a String. That string is the action name that the navigator uses to select which view to display next. Not the getters/setters.

All of the above can be done without any reference (direct or indirect) to the FacesContext or any javax.faces classes or methods. It's all POJO because the JSF framework does all the work.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

In my index.jsp here is what I am using in the SUBMIT button:



The createTransaction() populates my object from the values entered in the page as well as populates the DAO to insert the data into my DB table.

It's a pretty simplistic page. I am sorry I am not understanding how I am suppose to get to my createTransaction() if I am using the getValueID() in the transactionBean. I already have an instance variable in the getValueID(). Can you please elaborate?

Thanks.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

OK, Tim. So what I am understanding you to say is that the ACTION in my submit button should execute the getValueID() that returns a string and if that string equals "failed" then the navigation-rule, will forward the user to my /validationFailed.jsp page.

Is that correct? Just trying to confirm what I understand.

Thanks.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

Simpler than that, even.

You don't need a "getvalueID" method unless you want one. All that actually counts is that action method returns a navigation id. There's not a requirement for that ID to be a bean property, and in fact JSF itself has no use for it, since the navigation control is done based only on the action method's return value.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

Hopefully, last question. Before I had the createTransaction() as the action method associated with my submit button as I described above. Now that the getValueID() is the method associated with the submit button how do I get the createTransaction() to execute?

Thanks.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15952
    
  19

OK. First of all, I think you're still thinking that the action processor is a property method. It is not. You shouldn't name the action processor "getXXXXX", because that's not how it's being used, and JSF isn't going to treat it the same way it treats properties. My own personal convention is to prefix my action methods with "do". JSF doesn't attach any special meaning, but when I look at my source code, I can tell by the name that "doSave()" is an action method. The view attribute on my submit button that fires it is "action="#{myBean.doSave}".

Because the action processor is an action processor, it should be the control point for all the business logic invoked by that action. For really simple stuff, the action processor method can contain the business logic itself. For more complex stuff, it can delegate to other internal methods and/or to separate business and/or persistence objects. So the action processor would call createTransaction() either within its own code or in code that it calls.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

First of all let me thank IIlari, Nirvana and Tim. All the help and direction have been extremely helpful and more than appreciated. JSF has proven to be a very complex and complicated framework that my NEW boss wanted me to try and see if it was feasible to work with. My background has been in Stripes so going to JSF has been a lot more than I bargained for and unfortunately he has no desire to go to Stripes.

At any rate, Tim, you are correct in your last response that I am confused and that this web page that I'm working on is VERY SIMPLE. There have been so many posts on this so I would like to try and narrow down what I am trying to accomplish.

Here is my scenario:

1. I have TWO web pages in this web app. 1)index.jsp (main web page) 2)validationFailed.jsp
2. When I enter in the browser: http://testAppDev
3. The ValueBean method called getValueID() is called and that is because the first field in the index.jsp page is called Value and which has a value="#{transactionBean.valueID}" and in that method I was getting the valueID from a querystring in the REQUEST and returning it to the property in my index.jsp page ultimately.
4. Please remember STILL at this point my index.jsp page has NOT even been displayed to the user because I wanted to validate the String valueID from the getValueID() before displaying any pages.
6. If the String valueID was validated then I would send the user to the index.jsp page and if the valueID was not validated then I would REDIRECT or FORWARD the user to the validationFailed.jsp page.
7. I think we got off track a few posts ago, and I'm sure that is my fault when trying to understand everyone's instruction and answering questions. Then it was suggested that my action on my submit button on my index.jsp should be the validation code and it was as that point that I knew we had gotten off track.
8. The point is that I do not want to display any pages to the user UNTIL the valueID is validated.

I apologies for all the confusion that I certain I have caused. But this list has given me the most help and that is why I come here with my questions. On another list it was suggested to me that the navigation-rule would NOT work because my the page had already started to be rendered even though it had not been displayed. It was further suggested that I use a PhaseListener(?) or a Servlet Filter.

I am hoping that one of you guys can help me understand how to do what I want to accomplish.

Thanks.
B Nirvan
Ranch Hand

Joined: Oct 20, 2010
Posts: 82
Melinda Savoy wrote:

Here is my scenario:

1. I have TWO web pages in this web app. 1)index.jsp (main web page) 2)validationFailed.jsp
2. When I enter in the browser: http://testAppDev

At this point before forwarding the request to index.jsp, you should call the getValueID() method and extract the value required by index.jsp in your bean. If validate is ok, forward to index.jsp, else forward to validationFailed.jsp. Now your decision part is done, and when index.jsp page is loading, you can return Value by coding a getValueId() method in the backing bean that is bound to the index.jsp. The getValueID method should do nothing more than returning the Value.

3. The ValueBean method called getValueID() is called and that is because the first field in the index.jsp page is called Value and which has a value="#{transactionBean.valueID}" and in that method I was getting the valueID from a querystring in the REQUEST and returning it to the property in my index.jsp page ultimately.

You don't validate when the index.jsp is loading. Validation should be done before forwarding the request to index.jsp(as described above).


4. Please remember STILL at this point my index.jsp page has NOT even been displayed to the user because I wanted to validate the String valueID from the getValueID() before displaying any pages.

In your existing design, even though the index.jsp is not displayed, it is in the process of loading itself and that is why your getValueId() is getting called in first instance.


6. If the String valueID was validated then I would send the user to the index.jsp page and if the valueID was not validated then I would REDIRECT or FORWARD the user to the validationFailed.jsp page.

Again, handle all validation before forwarding your request to index.jsp (or validateFailed.jsp).

7. I think we got off track a few posts ago, and I'm sure that is my fault when trying to understand everyone's instruction and answering questions. Then it was suggested that my action on my submit button on my index.jsp should be the validation code and it was as that point that I knew we had gotten off track.

Yes, I thought that you are processing request from index.jsp, when infact your index.jsp is the response.


8. The point is that I do not want to display any pages to the user UNTIL the valueID is validated.

If you are validating the request before forwarding to index.jsp, you have a plethora of choices for the jsp page that can be displayed(including validateFailed.jsp which can be displayed if validation failed).


I apologies for all the confusion that I certain I have caused. But this list has given me the most help and that is why I come here with my questions. On another list it was suggested to me that the navigation-rule would NOT work because my the page had already started to be rendered even though it had not been displayed. It was further suggested that I use a PhaseListener(?) or a Servlet Filter.

If you can validate before forwarding request to index.jsp, you don't need anything other than your backing bean and jsp pages.


That should clear all your doubts. Cheers.

regards
Nirvan.
Melinda Savoy
Ranch Hand

Joined: Jun 21, 2005
Posts: 386

Nirvan -- thanks for the response.

I'm moving on to creating a servlet filter as I understand from your post I will validate user before the page is rendered.

I will post another question so that this post does not get any longer.

Thanks again.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Using redirect from backing bean and getting IllegalStateException error
 
Similar Threads
sendRedirect()
Servlet Filter question
Error message: Cannot forward after response has been commited
nullpointer with @Autowired AuthenticationManager
Critical ::Download data in .CSV file problem with navigation,html writes to CSV