continueToOriginalDestination does not bring me back to originating page - wicket

I am trying to sign into my application. First I throw the RestartResponseAtInterceptPageException (this is in a WicketPanel on my BasePage):
add(new Link<String>("signin") {
#Override
public void onClick() {
throw new RestartResponseAtInterceptPageException(SignIn.class);
}
});
The SignIn Page class contains a form (an inner private class) for the sign in, with the following submit button:
add(new Button("signinButton") {
#Override
public void onSubmit() {
final User user = model.getObject();
final boolean result = MySession.get().authenticate(user);
if (result) {
if (!continueToOriginalDestination()) {
setResponsePage(MySession.get().getApplication().getHomePage());
}
} else {
error("Authentication failed");
}
}
});
When this button is clicked and the user is successfully authenticated, I am not redirected to the page where I clicked on the signIn link but instead I stay on the SignIn page? I've tried debugging this, but haven't been able to find out where things go wrong.
I am glad for any hints that lead to my finding the error of my ways.
This is wicket 1.5.1 by the way.
Small Update because I got the hint I needed from the answer, there is still a bit of explaining to do. The solution looks like this:
add(new Link<String>("signin") {
#Override
public void onClick() {
setResponsePage(new SignIn(getPage()));
}
});
The SignIn class gets a constructor that takes a page obviously and I simply set that page as with setResponsePage to return to where I started without all the continueToOriginalDestination and exception throwing.

RestartResponseAtInterceptPageException is meant to be used to redirect to an interception page while rendering a page. For example, in the constructor of a Page class ProtectedPage, if there is no user signed in, you throw new RestartResponseAtInterceptPageException(SignIn.class). When the SignIn page calls continueToOriginalDestination(), the user is taken back to the original ProtectedPage destination.
Your use is not a typical use of RestartResponseAtInterceptPageException since you throw it in a link handler. Why don't you do a setResponsePage(SignIn.class) directly instead? If you really want to return to the exact page you were on when the "signin" link is clicked, you could also try changing it to:
add(new Link<String>("signin") {
#Override
public void onClick() {
setResponsePage(getPage());
throw new RestartResponseAtInterceptPageException(SignIn.class);
}
});

Related

How to prevent gwt app to go to login page after page refresh?

I have a gwt app with a login page and a main page. After login app goes to main page. What i want is if i refresh the page to stay in main page and not going to login page. I have read many things and i tried History Mechanish but no result. Here is my code:
#Override
public void onSuccess(Login result) {
if (result.getLoginCount() == 1) {
final VerticalPanel userPanel = new VerticalPanel();
Anchor logout = new Anchor("logout");
logout.addStyleName("user");
logout.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
loginPanel.setVisible(true);
tablePanel.setVisible(false);
addPanel.setVisible(false);
userPanel.setVisible(false);
}
});
Label user = new Label("Hi " + usernameBox.getText());
userPanel.add(user);
user.addStyleName("user");
userPanel.add(logout);
userPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
userPanel.setVisible(true);
usernameBox.setText("");
passwordBox.setText("");
RootPanel.get("user").add(userPanel);
loginPanel.setVisible(false);
tablePanel.setVisible(true);
addPanel.setVisible(true);
History.newItem("main");
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
if(History.getToken().equals("main")){
loginPanel.setVisible(false);
tablePanel.setVisible(true);
addPanel.setVisible(true);
}
}
});
}
i also tried:
String historyToken = event.getValue();
if(historyToken.substring(0 , 4).equals("main")){
loginPanel.setVisible(false);
tablePanel.setVisible(true);
addPanel.setVisible(true);
} else {
loginPanel.setVisible(true);
tablePanel.setVisible(false);
addPanel.setVisible(false);
}
Is this the right way to handle page refresh with History.addValueChangeHandler? I would appreciate any help.
GWT application is a single page application. It means that if your reload page, the state of your application will be lost. What you can do, is to use local storage to store same state data, but that is not a good idea for an authentication data.
I recommend you to refactor your code in a way that the authentication is done against the back end and your GWT client will recover it's state from back end data when user refreshes the page.

Codename one. Facebook login issues

I am having problem with facebook login in my cn1 app. I followed all the instructions given here: http://www.codenameone.com/facebook-login.html. I create a new instance of FacebookConnect then I set the clientId, secret etc. Then I set a LoginCallback and call doLogin(). However when I tried to run it on my device the screen just loads and it never stops. It doesn't even call LoginFailed. It just never stopped loading.
Here is my code:
faceBookButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
fb.setClientId("XXXXXXXXXXXXXXXX");
fb.setClientSecret("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
fb.setRedirectURI("");
fb.setCallback(new LoginCallback(){
#Override
public void loginFailed(String errorMessage) {
Dialog dg = new Dialog();
dg.setDisposeWhenPointerOutOfBounds(true);
dg.setTitle("Login succeeded");
dg.show();
}
#Override
public void loginSuccessful() {
String token = fb.getAccessToken().getToken();
Dialog dg = new Dialog();
dg.setDisposeWhenPointerOutOfBounds(true);
dg.setTitle("Login succeeded");
dg.show();
}
});
fb.doLogin();
}
});
Check out the full guide on facebook login here.
On login success you need to show a new Form and not a Dialog as you are moving away from the login screen of your application. There is a full end to end sample in the chat tutorial.

Link to last version of stateful page

I have a number of stateful pages with some state for each page. For example each page has a form that was submitted.
How can I organize a menu with links to last versions of these stateful pages? Should I store anywhere (may be in the session) reference to appropriate object for each page? If I use
onClick() { setResponsePage(MyPage.class); }
than I lose the previous state of the page. I want to link to last state of the page.
Each time the page is rendered store the page's id in the session.
int pageId = pageInstance.getPageId();
A list or stack data structure could be used to hold the identifiers.
You can implement the navigation menu using a repeater (RepeatingView or such) that creates a new link for each page id in the session.
In the link's click handler you can redirect the user as follows:
Page pageInstance = (Page) new PageProvider(pageId, null).getPageInstance();
setResponsePage(pageInstance);
pageId = this.getPageId(); // get current version of lets say a HomePage
//OnClick for Link
public void onClick()
{
WebPage homePageInstance =
(WebPage) new PageProvider(HomePage.pageId, null).getPageInstance();
setResponsePage(homePageInstance);
}
});
I make it passing int previousId parameter via constructor :
#MountPath(value = "editSomethingPage")
public class TestPage extends WebPage {
int previousPageId = 0;
public TestPage(int previousPage) {
super();
this.previousPageId = previousPage;
}
#Override
protected void onInitialize() {
super.onInitialize();
add(new Link("goBack") {
#Override
public void onClick() {
if (previousPageId != 0) {
setResponsePage((Page) AuthenticatedWebSession.get().getPageManager().getPage(previousPageId));
} else {
setResponsePage(PreviousPage.class);
}
}
});
}
}
It prevents creation of new page instance and keeps all states of page made by user.

Apache Wicket bookmarkable url added one additional parameter to the link, why?

my map is
mountPage("/page/#{code}/#{name}", Page.class);
but when I click on the link
localhost/page/10/toy?2
wicket add also one parameter like a counter, when I refresh the page I have
localhost/page/10/toy?3
why?
This is because your page are stateful, Wicket manages its own states to your page by appending this "counter". This way, when your user navigate backward using its browser built-in functionnality, the page is displayed has it has been previously.
If you don't want such a parameter in your URL, you'll need to dig out and eradicate every stateful component in your pages.
You can create
public class MountedMapperWithoutPageComponentInfo extends MountedMapper {
public MountedMapperWithoutPageComponentInfo(String mountPath, Class<? extends IRequestablePage> pageClass) {
super(mountPath, pageClass, new PageParametersEncoder());
}
#Override
protected void encodePageComponentInfo(Url url, PageComponentInfo info) {
}
#Override
public Url mapHandler(IRequestHandler requestHandler) {
if (requestHandler instanceof ListenerInterfaceRequestHandler) {
return null;
} else {
return super.mapHandler(requestHandler);
}
}
}
and map page on Application class like this
mount(new MountedMapperWithoutPageComponentInfo("/page/#{code}/#{name}", Page.class));

not able to set focus on TextBox in a GWT app

This should not be causing me so much pain but it is. It is a very weird problem. In a GWT application, I have two .java files, login.java and application.java.
In login.java, I'm creating a user login page where if the username and password is verified the user is logged into the application and application.java takes from here.
Now in application. java's onModuleLoad() this is how i'm starting with a login page.
public void onModuleLoad() {
Login login = new Login();
login.textBoxUsername.setFocus(true);
RootLayoutPanel.get().add(login);}
This works great, except for the tiny problem of not being able to set focus on the username TextBox when the page loads. I have tried evrything I can think of. But the focus just doesn't get set on the TextBox. If anyone can suggest a solution, please do. Your help is greatly appreciated.
Solution: (In case it helps anyone facing the same issue)
final Login login = new Login();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
Try using Scheduler.scheduleDeferred():
public void onModuleLoad() {
Login login = new Login();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand () {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
}
Update: answer updated to use Scheduler.get().scheduleDeferred() instead of DeferredCommand, which is deprecated.
Why using DefferedCommand, I think it's better to use someWidget.getElement().focus() which is a native Javascript. I'm using it everywhere, I've not seen any problem.
If your Widget extends Composite, you can:
#Override
protected void onAttach() {
super.onAttach();
textBoxUsername.setFocus(true);
}
It would be so easy for GWT to store a 'wantsFocus' in the internal state, and call focus after the widget is attached. We are still waiting after many years for that feature however...
Still, even after the attach handler is called, setFocus does not always work.
So in the meantime, our GwtUtil library has used the following code. It is a combination of several other solutions, and has been wrapped in a utility function:
static public void setFocus(final FocusWidget focusWidget) {
if (focusWidget.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
} else {
focusWidget.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
}
}
});
}
}
And call it like this:
setFocus(myTextBox);
It makes sense to use a utility function; If and when GWT finally makes setFocus work, you won't have to change your source code in multiple places.