Recently I've migrated from Wicket 1.4 to Wicket 1.5.
I've got problem Panel with AjaxSelfUpdatingTimerBehavior added to ModalWindow.
Closing modal Window does not stop the timer, so when it expires it tries to connect with (non-visible) Panel.
New Wicket release does not allow AJAX requests from disabled/non-visible components so I see "behavior not enabled; ignore call." warning in logs and "Access denied" on Page.
Any ideas how to fix it?
calling AjaxSelfUpdatingTimerBehavior.stop() from WindowClosedCallback does not work
Override canCallListenerInterface(Component component, Method method) in AjaxSelfUpdatingTimerBehavior
/**
* Overridden to get rid of "Access Denied" error after closing Modal Window
*/
#Override
public boolean canCallListenerInterface(Component component, Method method) {
if(SelfupdatingPanel.this.equals(component) &&
method.getDeclaringClass().equals(org.apache.wicket.behavior.IBehaviorListener.class) &&
method.getName().equals("onRequest")){
return true;
}
return super.canCallListenerInterface(component, method);
}
Note that class.getMethod("onRequest", (Class)null) throws NoSuchMethodException since onRequest() is not public
Related
I am trying to implement session timeout with help of a GWT Timer which will make a RPC call to server to check whether the session is valid or expired by using lastaccessedtime. but every time i make a RPC call it updates the lastaccessedtime (understandable as i am making a RPC call), any way i can prevent my Timer RPC call from updating the lastaccessedtime?
wrote some server side logic to get the lastaccessedtime and try to find out session is valid or not
com.google.gwt.user.client.Timer elapsedTimer;
public void onModuleLoad() {
elapsedTimer = new Timer () {
public void run() {
validateSession();
}};
//giving time delay of 1sec to call the batches
elapsedTimer.scheduleRepeating(60000);
}
public void validateSession(){
//Problem code every time i make this call it updates the last accessed time
viewService.validateSessionGWT(new AsyncCallback<ModuleData>() {
#Override
public void onFailure(Throwable e) {
//do something
}
#Override
public void onSuccess(ModuleData data) {
if(data.getSessionExpired()){
//redirect to login page
}
}
});
}
any idea how to overcome this problem or any other idea to implement Session management in GWT
NOTE: already gone through this which is similar to my approach
https://itsecrets.wordpress.com/2011/07/20/session-timeouts-with-gwt-rpc-calls/
Your GWT servlets extend the RemoteServiceServlet. So you can override processPost and add a custom last call timestamp in you http session. Every request updates this field.
I suggest to implement an abstract servlet that is extended by all your gwt servlets. Additionally you should not only set the custom last access field, but check it just before and only call the super method if everything is fine.
Then your timer and the servlet request you already have should only check this Session field.
Perhaps not the best solution but this should work.
I use wicket 7 with Stateful pages and every i change to new page i always use code like this:
PageParameters pageParameters = new PageParameters();
setResponsePage(new SecondPage(pageParameters));
Every i change page, a new page version is created and the page ID is increased by one.
But when I'm trying to load the previous page, i click the previous button from the browser, the page always expired.
i found the problem when i use this getApplication in my program i cant load the previous page. if i exclude getApplication i can load the previous page.
public class BasePage extends WebPage {
private ServletContext servletContext;
private boolean developmentMode;
public BasePage() {
NextApp app = (NextApp) getApplication();
servletContext = app.getServletContext();
developmentMode = app.usesDevelopmentConfig();
/** other code **/
}
}
Please help me, how to use getApplication and i can load the previous page too?
PageExpiredException's javadoc says:
Thrown when a {#link Page} instance cannot be found by its id in the page stores. The page may be
* missing because of reasons like:
* <ul>
* <li>the page have never been stored there, e.g. an error occurred during the storing process</li>
* <li>the http session has expired and thus all pages related to this session are erased too</li>
* <li>the page instance has been erased because the store size exceeded</li>
* #see HttpSession#setMaxInactiveInterval(int)
* #see org.apache.wicket.settings.StoreSettings#setMaxSizePerSession(org.apache.wicket.util.lang.Bytes)
* #see NotSerializableException
Check whether any of these is true.
Also I'd recommend you to use: setResponsePage(SecondPage.class,
new PageParameters());
I have a project that does 2 RPC calls and then saves the data that the user provided in tha datastore. The first RPC call works ok, but from the second I always recieve the onFailure() message. How can I determine why the onFailure() is triggered? I tried caught.getCause() but it doesn't return anything.
feedbackService.saveFeedback(email,studentName,usedTemplates,
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
caught.getCause();
Window.alert("Failure!");
}
public void onSuccess(String result) {
Window.alert("Saved!");
}
});
Throwable instance is instance of an Exception. You can check if it is a custom Exception like this:
if (caught instanceOf CustomException){
or if you want to show the message of exception you can use the getMessage():
Window.alert("Failure: " + caught.getMessage());
GWT-rpc is not not easy to ebug if an error occurs.
The easiest part is th check if the Exception is part of StatusCodeException.
A Statuscode of 404 means, you are pointing to a wrong endpoint
0 means, that
The searver is unreachable
You don't have permissions to check, if the server is available (X-domain-request)
You can use the Chrome-Web-Inspector to bedug GWT-RPC
You should be able to see all calls from the browser to you backend.
The most common failures are because of serialization of object. You have to ensure, that all dtransferred object implement java.io.Serializable
Most of the time it will just be a server side exception being raised which fires the onFailure() method.
Try putting breakpoints on your server side. That should help you pinpoint what's going wrong.
According to the answer of BalusC, I used
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
in my #PostConstruct method to stop JSF from rendering the view and redirect users. However, when I try to run the code, I still ran into the java.lang.IllegalStateException exception at the above line.
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:524)
at StudentManagedBean.CourseSummary.init(CourseSummary.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
UPDATE: I added the following line in my #PostConstruct method:
System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());
and what I saw was INIT true. I wonder if the response is supposed to be committed BEFORE the #PostConstruct method is called?
I'd be very grateful if you could give me an advice.
As mentioned in my update, the following line printed INIT true:
System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());
I finally found why the above situation occurred. On my page, before the ManagedBean X, which contains the redirect function, was referenced by UIComponent A, another ManagedBean Y was referenced beforehand by UIComponent B that is placed above UIComponent A in the page structure. As a consequence, the response was partially committed by ManagedBean Y, which makes it impossible for ManagedBean X to send a redirect request.
A redirect will not work here, because even though the response has been completed and finalized, JSF is not smart enough to avoid its typical routine of running through the lifecycle events anyway.
Instead you can try doing a Forward from a RequestDispatcher. A Forward is different from a redirect in the following ways:
Performed internally by the servlet
Browser is apathetic
original url stays intact
Here is some code that displays how this can be done...
RequestDispatcher dispatcher =
((ServletRequest) context.getExternalContext().getRequest())
.getRequestDispatcher("/j_spring_security_logout");
try {
dispatcher.forward((ServletRequest) context.getExternalContext().getRequest(),
(ServletResponse) context.getExternalContext().getResponse());
} catch (ServletException e) {
log.error("ServletException", e);
} catch (IOException e) {
log.error("IOException", e);
}
By doing this you are ending the execution of the FacesServlet prematurely and forwarding it onto a different servlet altogether. I imagine that from this other servlet it might be possible to redirect to the desired location.
I have a GWT application and I want to run some code when the user leaves the application to force a logout and remove any data etc.
To do this I am using a CloseHandler and registering it using Window.addCloseHandler.
I have noticed that when the refresh button is clicked the onClose method is run but I have been unable to differentiate this event from a close where the user has closed the browser. If it is a refresh I do not want to do the logout etc, I only want to do this when the user closes the browser/tab or navigates away from the site.
Does anybody know how I can do this?
There is no way to differentiate the 'close' from 'refresh'. But, you can set a cookie that holds the last CloseHandler call time and check, when loading the module, if this time is old enough to clean the information before showing the page.
You can do that with the folowing utility class (BrowserCloseDetector). Here is an example using it on the onModuleLoad.
The test lines:
#Override
public void onModuleLoad() {
if (BrowserCloseDetector.get().wasClosed()) {
GWT.log("Browser was closed.");
}
else {
GWT.log("Refreshing or returning from another page.");
}
}
The utility class:
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
public class BrowserCloseDetector {
private static final String COOKIE = "detector";
private static BrowserCloseDetector instance;
private BrowserCloseDetector() {
Window.addWindowClosingHandler(new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
Cookies.setCookie(COOKIE, "");
}
});
}
public static BrowserCloseDetector get() {
return (instance == null) ? instance = new BrowserCloseDetector() : instance;
}
public boolean wasClosed() {
return Cookies.getCookie(COOKIE) == null;
}
}
Have you tried
<BODY onUnload = "scriptname">
in your gwt hosting/launching html file?
I am thinking that if you defined a map "hash" (i.e. a javascript pseudo hash) in the hosting file and then accessed the "hash" in GWT through Dictionary class, you could update values in that hash as the user progresses through the gwt app. Which means, your programming style would require you to log milestones on the user's progress onto this map.
When the user closes the browser page, the onunload script of the launching html page would be triggered. That script would access the map to figure out what needs to be updated to the server, or what other url to launch.
I am intereted too if someone got a solution (GWT/java side only).
Maybe we can do it with HistoryListerner ?
1-set a flag for your current viewing page.
2-when ClosingHandler event, launch a "timeout" on server-side (for example 10s)
3-if during this time your got a massage from HistoryListerner with the same last flag so it was just a refresh.
of disconnect if timer is over...
Is not a good solution but I think it is easy to do... If someone have a better one...