Show success message and then redirect to another page after a timeout using PageFlow - redirect

How can I show a success message and then redirect the user to another page after a timeout of e.g. 5 seconds?
I need this for the login page after a successful login. I tried the following and I can see the warning message on login failure, but not the success message on login success. It shows immediately the target page.
public String check(){
if (username.equals("test") && password.equals("test")) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!"));
return "Success";
}else{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN,"Sample warn message", "Watch out for PrimeFaces!"));
return "Failure";
}
}
I'm using Seam's PageFlow for navigation.
I have a
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
on the login page.

It is one of the utilities of Flash. Instead of
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!"));:
simply use this code
FacesContext facesContext = FacesContext.getCurrentInstance();
Flash flash = facesContext.getExternalContext().getFlash();
flash.setKeepMessages(true);
flash.setRedirect(true);
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Sample info message", "PrimeFaces rocks!"));

First of all, with the code you posted you won't see the FacesMessage before the redirect, you'll see it after the redirect. But also, in order to make that happen you'll need to add a filter, because messages are lost when you redirect. This is the code for the filter you need (don't forget to declare it in web.xml):
public class MultiPageMessagesSupport implements PhaseListener {
private static final long serialVersionUID = 1250469273857785274L;
private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";
#Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
/*
* Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
* have arrived here and the response is already complete, then the page is
* not going to show up: don't display messages yet.
*/
#Override
public void beforePhase(final PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
int msg = this.saveMessages(facesContext);
if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
if (!facesContext.getResponseComplete()) {
this.restoreMessages(facesContext);
}
}
}
/*
* Save messages into the session after every phase.
*/
#Override
public void afterPhase(final PhaseEvent event) {
if (event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES ||
event.getPhaseId() == PhaseId.PROCESS_VALIDATIONS ||
event.getPhaseId() == PhaseId.INVOKE_APPLICATION) {
FacesContext facesContext = event.getFacesContext();
int msg = this.saveMessages(facesContext);
}
}
#SuppressWarnings("unchecked")
private int saveMessages(final FacesContext facesContext) {
List<FacesMessage> messages = new ArrayList<FacesMessage>();
for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext();) {
messages.add(iter.next());
iter.remove();
}
if (messages.isEmpty()) {
return 0;
}
Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> existingMessages = (List<FacesMessage>) sessionMap.get(sessionToken);
if (existingMessages != null) {
existingMessages.addAll(messages);
} else {
sessionMap.put(sessionToken, messages);
}
return messages.size();
}
#SuppressWarnings("unchecked")
private int restoreMessages(final FacesContext facesContext) {
Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> messages = (List<FacesMessage>) sessionMap.remove(sessionToken);
if (messages == null) {
return 0;
}
int restoredCount = messages.size();
for (Object element : messages) {
facesContext.addMessage(null, (FacesMessage) element);
}
return restoredCount;
}
}
If this doesn't work for you, and you need to show the message before, then you'll have to something like the following: make the method return void, invoke it through ajax, and after adding the success message invoke some javascript method that will wait a couple of seconds and then make the redirect (maybe by programmatically clicking a hidden button that redirects to next page).
In my opinion this is not worth the trouble, you will just delay the login process. Anyway user will know tha tlogin succeeded because he will be redirect to home page (or whatever page you send him to)
EDIT:
the messages are displayed in the page when the method finishes, so waiting in the managed bean method won't work. after adding the FacesMessage, use
RequestContext.getCurrentInstance().execute("waitAndRedirect()");
And in your xhtml, you'll need to have a javascript function similar to this:
function waitAndRedirect() {
setTimeout(function() {
hiddenButtonId.click();
}, 2000);
}
where hiddenButtonId is the ID of a p:button which redirects to home page and is hidden (display:none)
But again, this a nasty approach, in my opinion there's no need to do this, you will just delay the login process.

you can not declare MultiPageMessagesSupport in the web.xml you must declare MultiPageMessagesSupport in the faces-config.xml. por example:
enter code here
<lifecycle>
<phase-listener>your.package.MultiPageMessagesSupport</phase-listener>
</lifecycle>

Related

onActivityResult never fires unless I use getActivity() when calling startActivityForResult from a Fragment

My main activity opens a dialog fragment with 2 items in a listview. Clicking either one starts a new Activity. Unless I use getActivity().startActivityForResult() my code for onActivityResult never runs. Everything I've read here discourages using getActivity().startActivityForResult() and says just use startActivityForResult(). Normally I'd say "doesn't matter, code works" but its driving me nuts why its discouraged so much and why it won't work without getActivity(). I've been pouring over documentation and can't find an answer, help me stackoverflow, you're my only hope.
My onActivityResult() code located in my main activity (Landing.class):
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
String s = "";
Session current = new Session();
Gson gson = new Gson();
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
s = data.getStringExtra("SESSION_JSON");
current = gson.fromJson(s, Session.class);
}
}
sessions.add(current);
adapter.notifyDataSetChanged();
}
Code that calls startActivityForResult() located in my DialogFragment class:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dismiss();
if (position == 0) {
Intent intent = new Intent(getActivity(), ActiveSessionActivity.class);
getActivity().startActivityForResult(intent, 1);
}
}
Code in ActiveSessionActivity class that should be returning the result to onActivityResult() in my main activity:
public void saveSession(View v) {
Session session;
Gson gson = new Gson();
String json = gson.toJson(session);
Intent intent = new Intent();
intent.putExtra("SESSION_JSON", json);
setResult(RESULT_OK, intent);
finish();
}
Android DialogFragments are still fragments, as such calling startActivityForResult from your dialog will actually be getting the result in the dialog. If you were to implement onActivityResult in your DialogFragment you'll get your callback. The reason getActivity().startActivityForResult() is discouraged is because the dialog has no control of the activity and it might not be attached anymore. Try...
if (getActivity() != null && !isDetached() && !isRemoving()) {
getActivity().startActivityForResult(...);
}

confusion in running small history GWT application

When I am running a small login application consisting of history management, it works fine at my home where im using latest chrome and firefox versions and GWT 2.4
The same application when I run at my office works wild. I have used a Global static boolean variable which has correct value in the debug mode while it has wrong value when I run it normally. In Office Im using IE 7 and GWT 2.2
Also, onModuleLoad() is called only once at my home environment whereas it is called everytime when I type someURL#sometoken and press enter to change the internal page. When is onModuleLoad() called. Only once per session or evrytime user loads some page (or even token)?
Can anyone tell is this some problem due to IE 7 or GWT 2.2 or some other issue.
EDIT - Its very small app. Code ---
TestHistory.java
public class TestHistory implements EntryPoint, ValueChangeHandler<String> {
static boolean isLoggedIn = false;
static final String PAGENAME = "mainscreen";
public void onModuleLoad()
{
History.addValueChangeHandler(this);
String startToken = History.getToken();
System.out.println("onModuleLoad Called..... start token= -------"+startToken+"--------");
if(startToken.isEmpty())
History.newItem("login");
else
History.fireCurrentHistoryState(); //to execute onValueChange 1st time since 1st time history is not setup
}
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String token = event.getValue();
System.out.println("onValueChange called with token = ***"+token+"***");
String args = "";
int question = token.indexOf("?");
if (question != -1) {
args = token.substring(question + 1);
token = token.substring(0, question);
}
if(!isLoggedIn)
{
if(token.isEmpty() || "login".equals(token)) //1st time opened the site normally
new Login().display(false, RootPanel.get());
else {
new Login().display(true, RootPanel.get());
}
}
else //User has logged in
{
if(token.isEmpty() || "login".equals(token))
{
if(isLoggedIn)
Window.alert("Ur already logged in!!!");
else
new Login().display(false, RootPanel.get());
}
else if("withdraw".equals(token))
new Withdraw().display(RootPanel.get(), args);
else if("deposit".equals(token))
new Deposit().display(RootPanel.get(), args);
else //token not clear
Window.alert("Unrecognized token=" + token);
}
}
}
Login.java
public class Login {
static final String PAGENAME = "login";
void display(final boolean hasTypedSomeToken,final Panel myPanel) //Process login
{
System.out.println("login display called");
Label displayLabel = new Label("This is the Login Page");
Label enterName = new Label("Enter ur name");
final TextBox txtName = new TextBox();
Label enterPasswd = new Label("Enter ur Passwd");
final TextBox txtPasswd = new TextBox();
Button btnLogIn = new Button("Login", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
/* Real app will check DB. Here we r jst chckng d txt fields hv value */
if(txtName.getValue().length()>0 && txtPasswd.getValue().length()>0)
{
TestHistory.isLoggedIn = true;
if(hasTypedSomeToken) {
System.out.println("adsljasdlfjljkfsd");
History.fireCurrentHistoryState();
System.out.println("hoolala "+History.getToken());
}
else
{
myPanel.clear();
Label displayLabel = new Label("Thank U for logging. U can now access the application.");
myPanel.add(displayLabel);
}
}
}
});
myPanel.clear();
myPanel.add(displayLabel);
myPanel.add(enterName);
myPanel.add(txtName);
myPanel.add(enterPasswd);
myPanel.add(txtPasswd);
myPanel.add(btnLogIn);
}
}
Deposit.java
public class Deposit {
static final String PAGENAME = "deposit";
void display(Panel myPanel, String param)
{
System.out.println("deposit display called");
myPanel.clear();
Label displayLabel = new Label("This is the Deposit Page & ur parameter = "+param+")");
myPanel.add(displayLabel);
}
}
Class Withdraw is same as Deposit.
The problem Im facing is that once Im logged in I should be able to open all the internal pages which works perfectly at my home (and onModuleLoad() is called just once) whereas I have to log in everytime to open a internal page at my office (and onModuleLoad() is called evrytime)
onModuleLoad is called when the page is loaded, but:
pressing the enter key while in the address bar can reload the page in some browsers
changing the hash in the URL from outside the application (typing in the address bar, or using a bookmark) can confuse IE6/7; when GWT detects it, it reloads the page (have a look inside the HistoryImplIE6 class). Note that it does not happen when navigating in the history (this is what the hidden iframe is for)
Did you included the hidden iframe for history support in gwt in your html host page?
See http://code.google.com/intl/de-DE/webtoolkit/doc/latest/DevGuideCodingBasicsHistory.html#mechanism

Why does my History.newItem(someToken) not fire onValueChange()?

Even though it is correctly fired when I use History.fireCurrentHistoryState();
EDIT: All classes in the same package. Code updated -
TestHistory.java
public class TestHistory implements EntryPoint, ValueChangeHandler<String> {
static boolean isLoggedIn = false;
static final String PAGENAME = "mainscreen";
public void onModuleLoad()
{
History.addValueChangeHandler(this);
String startToken = History.getToken();
System.out.println("onModuleLoad Called..... start token= -------"+startToken+"--------");
if(!startToken.isEmpty())
History.newItem(startToken);
History.fireCurrentHistoryState(); //to execute onValueChange 1st time since 1st time history is not setup
}
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String token = event.getValue();
String args = "";
int question = token.indexOf("?");
if (question != -1) {
args = token.substring(question + 1);
token = token.substring(0, question);
}
if(!isLoggedIn)
{
if(token.isEmpty() || "login".equals(token)) //1st time opened the site normally
new Login().display(false, RootPanel.get());
else {
new Login().display(true, RootPanel.get());
}
}
else //User has logged in
{
if(token.isEmpty() || "login".equals(token))
{
if(isLoggedIn)
Window.alert("Ur already logged in!!!");
else
new Login().display(false, RootPanel.get());
}
else if("withdraw".equals(token))
new Withdraw().display(RootPanel.get(), args);
else if("deposit".equals(token))
new Deposit().display(RootPanel.get(), args);
else //token not clear
Window.alert("Unrecognized token=" + token);
}
}
}
Login.java
public class Login {
static final String PAGENAME = "login";
void display(final boolean hasTypedSomeToken, Panel myPanel) //Process login
{
System.out.println("login display called");
Label displayLabel = new Label("This is the Login Page");
Label enterName = new Label("Enter ur name");
final TextBox txtName = new TextBox();
Label enterPasswd = new Label("Enter ur Passwd");
final TextBox txtPasswd = new TextBox();
Button btnLogIn = new Button("Login", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
/* Real app will check DB. Here we r jst chckng d txt fields hv value */
if(txtName.getValue().length()>0 && txtPasswd.getValue().length()>0)
{
TestHistory.isLoggedIn = true;
if(hasTypedSomeToken) {
//History.back(); //send him to the URL(token) he bookmarked b4 loggin in
History.newItem("login",false);
History.back();
System.out.println(History.getToken());
}
else{
myPanel.clear();
Label displayLabel = new Label("Thank U for logging.);
myPanel.add(displayLabel);
}
}
}
});
myPanel.clear();
myPanel.add(displayLabel);
myPanel.add(enterName);
myPanel.add(txtName);
myPanel.add(enterPasswd);
myPanel.add(txtPasswd);
myPanel.add(btnLogIn);
}
}
Deposit.java
public class Deposit {
static final String PAGENAME = "deposit";
void display(Panel myPanel, String param)
{
System.out.println("deposit display called");
myPanel.clear();
Label displayLabel = new Label("This is the Deposit Page & ur parameter = "+param+")");
myPanel.add(displayLabel);
}
}
Withdraw.java
//similar to deposit.java
The problem was with the usage of History.newItem(). the problem was occuring when I was using the bookmarked url and calling History.newItem() with a new token. Since already a token was present for the same internal page and I was giving it a new token so there was some confusion and onValueChange() was not being called.
Now Im clear that History.newItem() should be used when there is no token attached to the current view to mark the view with a token. Generally when a user opens a site normally (with no token), we should use history.newItem to mark the 1st view.
Also worth noting is that History.fireCurrentHistoryState() just calls onValueChange with the current token. And by going through the GWT's Code I found that History.newItem() simply calls History.fireCurrentHistoryState()
Actually if I replace
if(!startToken.isEmpty())
History.newItem(startToken);
History.fireCurrentHistoryState();
in my code with
if(startToken.isEmpty())
History.newItem("login");
else
History.fireCurrentHistoryState();
& also the code
if(hasTypedSomeToken) {
//History.back(); //send him to the URL(token) he bookmarked b4 loggin in
History.newItem("login",false);
History.back();
System.out.println(History.getToken());
}
with
if(hasTypedSomeToken) {
History.fireCurrentHistoryState();
System.out.println("getToken() in Login = "+History.getToken());
}
it works pretty well.
Although newItem(...) generally fires an event, it is a no-op if the current token is the same as the one you're trying to add. If that's not the case, there's a problem with your implementation.

GWT - Hiding or showing a Div at runtime

I have a GWT App where I need to call a webservice to check whether the user signed in is an administrator - and then set the admin Div to visible (hidden by default) if the web service returns true.
The problem is the program passes the check before the web service can return the result. It's looking something like this
public class ModelClass{
boolean isAdmin = false;
public ModelClass(){
//Call webservice in constructor, if returns true, set isAdmin to true via setter
}
}
Then, in my widget, I create an instance of the ModelClass and then in the last step before the page finishes loading, I check the isAdmin property to see if it's true, if so - set the Admin panel to visible. No matter how early I try to make the call, and how late I check the property, the admin check always happens before the web service response returns.
I've tried change listeners - but they only apply to widgets. I tried rigging the property as a label and using a click event by calling click() on the label from the web service response.
Nothing seems to work - does anyone have any ideas?
If you are using a callback mechanism, you will have to do it in the callback function.
e.g. If you are using the GWT's request builder, You will have to do it in onResponseReceived of your request callback:
public ModelClass() {
isAdmin();
}
private void isAdmin() {
RequestBuilder builder = new RequestBuilder(
RequestBuilder.GET, webserviceurl);
try {
request = builder.sendRequest(null, new RequestCallback() {
public void onResponseReceived(Request request,
Response response) {
int code = response.getStatusCode();
if(code >= 400) {
Window.alert(response.getStatusText());
return;
}
if(code == 200) {
// if admin is logged in
// hide your div
}
}
public void onError(Request request, Throwable exception) {
Window.alert("Error checking admin status");
}
});
}catch(RequestException re) {
Window.alert("Error checking admin status");
}
}

Facebook: FB.apiClient TypeError: $wnd.FB.Facebook is undefined" why this error occures?

We are facing one problem with facebook.
we integrated FB in our web application, when user login through fconnect in our web application then he registered with our system(1st time only) just providing his email id.For normal user few user i/p for registration in our system
Our web-application developed in java [GWT2.0].
Problem is when FACEBOOK or normaluser login through FB in our web-application.( 1 at a time)
when user refreshes page then FB pop window Occues with message
"Debug: Exception while loading FB.apiClient TypeError: $wnd.FB.Facebook is undefined"
or sometimes $wnd.FB.Facebook.apiClient is null occures
we get above error[pop-up] message 3 times.
we used following script in html page
< script type="text/javascript" language="javascript"
src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php">
In only 1 page of our web-application i.e UserHome page where we display users info .
on that page only above error message occurs
We used following GWT Code [from Gwittit] In controller class[Singleton class ]
/**
* Function get called when all the data on first page get loaded.
*
* */
public void notifyFinishedLoadinPage() {
FacebookConnect.waitUntilStatusReady(new
RenderAppWhenReadyCallback());
}
private MyLoginCallback
loginCallback = new MyLoginCallback();
class MyLoginCallback implements LoginCallback {
public void onLogin() {
isFacebookSign = true;
fbLoggedInUserId = ApiFactory.getInstance().getLoggedInUser();
for (FacebookObserver Observer : facebookObservers) {
Observer.notifyFacebookLogin(true);
}
}
}
public void publishStream(final FacebookObserver fbObserver) {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
FacebookConnect.requireSession(new
AsyncCallback() {
public void onFailure(Throwable caught) {
Window.alert("Require session failed: " + caught);
GWT.log("Require session failed: " + caught, null);
}
public void onSuccess(Boolean isLoggedIn) {
if (isLoggedIn) {
for (FacebookObserver Observer :
facebookObservers) {
Observer.notifyPublishStream();
}
}
}
});
}
public void facebookConnection() {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
//SERVER
FacebookConnect.requireSession(new
AsyncCallback() {
public void onFailure(Throwable caught) {
GWT.log("Require session failed: " + caught, null);
}
public void onSuccess(Boolean isLoggedIn) {
if (loginCallback != null && isLoggedIn) {
loginCallback.onLogin();
} else {
//User not logged in
}
}
});
}
/**
* Fired when we know users status
*/
private class RenderAppWhenReadyCallback implements
AsyncCallback {
public RenderAppWhenReadyCallback() {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
//SERVER
}
public void onFailure(Throwable caught) {
Window.alert("Unable to login through Facebook: " + caught);
}
public void onSuccess(ConnectState result) {
if (result == ConnectState.connected) {
isFacebookSign = true;
for (FacebookObserver Observer : facebookObservers) {
Observer.notifyFacebookLogin(true);
}
//History.newItem(HistoryConstants.USERHOME_PAGE_HISTORY_TOKEN);
} else {
//rightSideFlexTable.clearCell(0, 0);
//rightSideFlexTable.setWidget(0, 0,
facebookPanel);
isFacebookSign = false;
}
}
};
Now we unable to found solution to this problem.
Can any one help Us to solve this problem ASAP
Hope-for the Best Co-operation
we found solution for above Question.
Facebook (login)loading requires few time.
In Our web page we fetch fb details like fb users loggedInId ,Image,etc.
so at the time of page loading we get all values null because facebook not load properly
so we get $wnd.FB.Facebook.apiClient is null or
Debug: Exception while loading FB.apiClient TypeError: $wnd.FB.Facebook is undefined"
To solve this problem we write one method which calls when user refreshes page or after facebook loading done properly.
public void notifyFacebookLogin(boolean isLogin) {
Long fbLoggedInUserId = ApiFactory.getInstance().getLoggedInUser();
if (fbLoggedInUserId != null) {
if (globalEndUserInfo == null) {
globalEndUserInfo = new EndUserInfo();
globalEndUserInfo.setFbLoggedInUserId(fbLoggedInUserId);
}
}
// code wherever we deal with FB related object
}
Now no error message display when user refreshes page or if fb takes time to loading
In this way we solve our Problem. :)