2

I'm implementing an auction system using jsf.

in the item page, I have a countdown showing how much time is left for this sale. I show it with <p:outputlabel value=#{itemBean.timeToEnd()} />.

the timeToEnd() method returns a string in the format: 1 days, 2 hours.. etc. it calculates it on a Date object inside that bean. I update the label with <p:poll>, on a 1 second interval.

my problem is, that when counter reaches 0 seconds, I want to refresh the whole page, where it will show that the sale is inactive.

in timeToEnd(), I added a logic that if the end date is passed, or seconds to end is 0, then execute the following code that suppose to refresh the page:

ExternalContext ec1 =FacesContext.getCurrentInstance().getExternalContext();             
ec.redirect(((HttpServletRequest) ec.getRequest()).getRequestURI());

But it doesn't refresh the page. I think it doesn't refresh since the page is "live" for some time. (user is on item page from a time where sale was active).

any ideas on how this could be implemented?

P.S I also tried to implement this countdown on client level, when I store the end date with c:set and then use javascript or something for the view update. but then I noticed that also for the code

 <c:set var = "enddate" value = "#{itemsBean.endDate}" scope="session"  />

for every use of "enddate" the server is called, rather than storing the date locally and then perform the calculation without bothering the server. so I didn't even get to the javascript part. if there's a way to implement locally, would be happy to hear about it.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
springer
  • 31
  • 6
  • 1
    You should not fire a redirect from a getter. That's the root of your problem. – Luiggi Mendoza May 25 '15 at 21:30
  • thanks, but this is not a getter, but a utility method. (there's no property "time to end". the property is "endDate" and this method uses it for calculation. further more, if I just put the redirect code in the beginning of the method with no condition, it works. but I only want it to be invoked when endDate .before(now() [pseudo code] ) – springer May 25 '15 at 21:34
  • Provide the relevant code in your JSF page and in your managed bean to reproduce your error then. With that basis, explain the flow of your actions and see if the action (not action listener) isn't an ajax request and thus it can successfully generate a redirect. – Luiggi Mendoza May 25 '15 at 21:41
  • @Luiggi is completely right. Technically, you're performing the job in a value expression method which is invoked during render response phase (which is exactly the same as a getter behaves!), not a method expression method which is invoked during invoke application phase (ass used by normal action and listener methods). Redirecting is not possible while the response is already committed (I'm wondering if you didn't see an ISE in server logs). You should be performing the job in `` instead of a "getter". Give it a try. – BalusC May 26 '15 at 07:22
  • @BalusC, it did the trick! I added a void method to just refresh the page on condition, called it from the listener attribute of the and it works like a charm. thank you! but, is my attitude here is right? isn't it a bad idea to ask the server each second about time to end? won't it be better to implement this as a client-side solution? and one more thing, is there a way to store an integer or date value locally in the xhtml page? (c:set didn't work as I mentioned). – springer May 26 '15 at 09:11

1 Answers1

4

Never do business/controller logic in a getter method. Also not if that getter represents EL 2.2 direct method invocation. It's after all still a value expression which is only evaluated during generating the HTML output and writing the response body during render response phase. That moment is clearly too late to set a response header (to instruct the client to perform a redirect).

Move that logic to an action(listener) method.

<p:poll ... listener="#{bean.onpoll}" />
public void onpoll() {
    // ...

    if (someCondition) {
        redirect();
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555