Primefaces TabMenu active tab remembered on logout - java

As the title explains by itself, I have an issue with managing the currently active tab in the tab menu. I'm using JSF 2.1 w/ PF 3.4. Here is the code fragment with the tab menu:
<h:form>
<p:tabMenu activeIndex="#{navigationMB.activeIndex}" >
<p:menuitem value="Početna" action="#{navigationMB.navigateStudent('home')}" icon="ui-icon-home" />
<p:menuitem value="Konsultacije" action="#{navigationMB.navigateStudent('konsultacije')}" icon="ui-icon-search" />
<p:menuitem value="Zakazivanje" action="#{navigationMB.navigateStudent('zakazivanje')}" icon="ui-icon-document"/>
<p:menuitem value="Profesori" action="#{navigationMB.navigateStudent('profesori')}"/>
<p:menuitem value="Moj profil" action="#{navigationMB.navigateStudent('profil')}" icon="ui-icon-person" />
</p:tabMenu>
</h:form>
Here is the code of the backing bean which serves for the sole purpose of navigating that tab menu:
#Named(value = "navigationMB")
#RequestScoped
public class NavigationMB {
private int activeIndex = 0;
public NavigationMB() {
}
public String navigateStudent(String page) {
System.out.println("go to page " + page);
if ("home".equals(page)) {
activeIndex = 0;
return "/student/home?faces-redirect=true";
}
if ("konsultacije".equals(page)) {
activeIndex = 1;
return "/student/allConsults?faces-redirect=true";
}
if ("zakazivanje".equals(page)) {
activeIndex = 2;
return "/student/newConsult?faces-redirect=true";
}
if ("profesori".equals(page)) {
activeIndex = 3;
return "/student/allProfessors?faces-redirect=true";
}
if ("profil".equals(page)) {
activeIndex = 4;
return "/student/profile?faces-redirect=true";
}
return "";
}
This runs fine when just browsing, but when I logout (invalidate the session) and later return with same or different user, the activeIndex is remembered. Am I not understanding something here? I suppose that the request scoped bean would be created every time there's a navigation action, and even if the user doesn't navigate anywhere, the integer I set to 0 would always point to "home" but it doesn't.
Any help would be awesome.
edit:
It seems that even without logging out, when two users (two tabs in browser) navigate around, if user 1 clicks on, for instance, tab menu item 2, and user 2 refreshes his page, user 2 will see tab menu item 2 selected as well, and vice versa.
edit2: I made a mistake with the previous edit, please forget about this above (I didn't notice that refresh on user 2 side actually loads user 1 with his view).

As discussed among the comments of the question, the bean is not recognized as being request scoped. It is created during application startup and lives as long as the application is running.
As Spring is used, using Spring annotations will resolve this issue:
#Scope("request")
public class NavigationMB {
}
For a request scoped bean, or:
#Scope("session")
public class NavigationMB {
}
to make it session scoped.

Related

Tapestry: How to display an alert dialog from my Java code

I'm actually writing a java code in the setupRender() method. Depending of a value provided by the server side, i would like to display an Alert dialog box to the user. By clicking on ok, the application should be closed.
I have not already found how to display an Alert dialog box with tapestry. Do somebody know how to procedd?
Thanks
It's not quite clear to me what you are trying to achieve, but perhaps the following two suggestions are useful.
Suggestion 1 - Display a message using AlertManager
In the page class, inject AlertManager and add the message to it.
public class YourPage {
#Inject
AlertManager alertManager;
Object setupRender() {
// ...
alertManager.alert(Duration.UNTIL_DISMISSED, Severity.INFO, "Love Tapestry");
}
}
Then use the <t:alerts/> component in the page template file to have the message displayed.
Note: The user may dismiss the message, that is, make it disappear. But it doesn't 'close the application' (whatever it is that you mean by that).
Suggestion 2 - Redirect to another page
The setupRender method can return different things. For example, it could return another page class, causing a redirect to that page. On that page, you could have the messages displayed and the session subsequently invalidated (if that's what you meant by 'application should be closed'.
public class YourPage {
Object setupRender() {
// ...
return AnotherPage.class;
}
}
public class AnotherPage {
#Inject
Request request;
void afterRender() {
Session session = request.getSession(false);
session.invalidate();
}
}
See the Tapestry docs for details about what setupRender() can return.
Suggestion 3 - Use JavaScript to display Alert and trigger Component Event
This approach uses JavaScript to display an Alert and subsequently trigger a component event via ajax. The event handler takes care of invalidating the session.
Note: Closing the current browser windows/tab with JavaScript isn't as easy as it used to be. See this Stackoverflow question for details.
YourPage.java
public class YourPage {
boolean someCondition;
void setupRender() {
someCondition = true;
}
#Inject
private JavaScriptSupport javaScriptSupport;
#Inject
ComponentResources resources;
public static final String EVENT = "logout";
void afterRender() {
if (someCondition) {
Link link = resources.createEventLink(EVENT);
JSONObject config = new JSONObject(
"msg", "See ya.",
"link", link.toAbsoluteURI()
);
javaScriptSupport.require("LogoutAndCloseWindow").with(config);
}
}
#Inject Request request;
#OnEvent(value = EVENT)
void logout() {
Session session = request.getSession(false);
if (session != null) session.invalidate();
}
}
YourPage.tml
<!DOCTYPE html>
<html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p="tapestry:parameter">
<h1>Hit the Road Jack</h1>
</html>
LogoutAndCloseWindow.js
define(["jquery"], function($) {
return function(config) {
alert(config.msg);
$.ajax({
type: "GET",
url: config.link
});
window.close(); // Legacy. Doesn't work in current browsers.
// See https://stackoverflow.com/questions/2076299/how-to-close-current-tab-in-a-browser-window
}
})

Wicket : throw new RestartResponseException to logout and redirect

I have a problem to redirect a page after invalidating session using Wicket.
Careers1 is a page, that needs user to be logged in, with six buttons linked to other pages and an a href button, which get the user logged out.
My code apparently works, because if I click to log out, and I click to one of the six buttons, it redirects me to the log in page.
But I need it to redirect me immediately, after I clicked "log out".
I tried setResponsePage() and also adding signOut() the problem is the same of the RestartResponseException.
Here is my code
Careers1:
public class Careers1 extends WebPage
{
public Careers1()
{
Link logoutLink = new Link("logout")
{
#Override
public void onClick()
{
getSession().invalidate();
throw new RestartResponseException(Careers1.class);
}
};
add(logoutLink);
}
}
On careers.html I have
<div class="logout" > <a wicket:id="logout" href="#"> LOG OUT </a></div>
Which should invalidate the session, and redirect the user to the login.
You can try forcing wicket to redirect immediately using a fake page that just redirects back to Careers1. Let's name it RedirectorPage:
public class RedirectorPage extends WebPage
{
#Override
protected void onBeforeRender()
{
throw new RestartResponseException(Careers1.class);
}
}
Now in the logout link of Careers1 you redirect to RedirectorPage. That worked for me, but only after I moved the exception of RedirectorPage into onBeforeRender(). Throwing the exception in the page constructor still makes wicket ignore the fact the session has already been invalidated.

JSF Java Server Faces dynamic loading of component

I am attempting to load a custom component(descending from UIInput). I then encode an html input back to the client. My component loader is thus:
#FacesComponent("TomsWidgetComponent")
#SessionScoped
public class TomsWidgetComponent {
public TomsInput getNewInput(UIComponent parent)
{
ExpressionFactory factory = getFacesContext().getApplication().getExpressionFactory();
TomsInput newComponent = (TomsInput) getFacesContext().getApplication().createComponent(getFacesContext(), "org.tom.example.toms.TomsInput", "org.tom.example.toms.TomsInput");
String newId = FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
newComponent.setId(newId);
elements.put(newId, newComponent);
newComponent.setInputData(new InputData());
ValueExpression valueExpression = factory.createValueExpression(getFacesContext().getELContext(),"#{tomsInput.string}",String.class);
newComponent.setValueExpression("value", valueExpression);
getChildren().add(newComponent);
pushComponentToEL(getFacesContext(), newComponent);
return newComponent;
}
html:
<"input type="tel" id="j_id2" oninput="mojarra.ab(this,event,0,'execute',0)" /input >"
The input shows up just fine, but ajax event never seems show up in my component. I've tried several permutations, with the key on setValueExpression, and adding behavior listeners.
...
Ive gotten passed the exceptions but the Ajax now coming back from the form is causing my component to reload. It's content is:
tomswidgetform=tomswidgetform&j_id2=fffdsdfgbg&javax.faces.ViewState=-6270730402975544133%3A7227399941332846704&javax.faces.source=j_id2&javax.faces.partial.event=input&javax.faces.partial.execute=j_id2%20j_id2&javax.faces.behavior.event=change&AJAX%3AEVENTS_COUNT=1&javax.faces.partial.ajax=true
Any idea what might be wrong? Thanks.

Wicket - refresh component on evry Request (implementing session timeout countdown)

i have a Wicket 6.10.0 Web Application. I want to implement a timer display the remaining time in the current user session. Something link this:
http://jsfiddle.net/justinobney/uZMGD/
I have a Wicket Label in the footer of my Page. This label uses JavaScript to countdown the time from for example 5 minutes down to 0 min 0 sek. This countdown (label) should be refreshed on every request.
Now the question is how to do this?
In the init() method i added and AbstractRequestCycleListener which notifies me of every end request like this:
getRequestCycleListeners().add(new AbstractRequestCycleListener() {
#Override
public void onEndRequest(RequestCycle cycle) {
super.onEndRequest(cycle);
System.out.println("End Request - here i would like to refresh somehow the label");
}
});
but i dont know how to send this message to the Label to refresh itself. Any ideas?
* E D I T : *
I have a SPA:
<body>
lots of AJAX components here
<div wicket:id="footer">Footer always stays here. <br />
Session timeout in: <span wicket:id="sessionTimeoutLabel">countdown here</span>
</div>
</body>
The countdown works a little bit like this: http://jsfiddle.net/justinobney/uZMGD/
Now on every AJAX Request i need the sessionTimeoutLabel label to rerender to start counting from lets say 600 seconds down to 0.
Don't focus too much on the "end of request". This is about 10µs after to the render phase. Also note that the session timeout is reset after each request, so there is no need to update the label with a new value, other than to reset it to the session timeout parameter.
You should just have a parameter somewhere that dictates the session timeout you configured, and use that to show the label, if it is application specific you can create a getter in your Application class:
public MyApplication extends WebApplication {
public static final int SESSION_TIMEOUT = 30; // minutes
public int getSessionTimeout() {
return SESSION_TIMEOUT;
}
}
And in your footer you can add a label:
add(new Label("timeout", PropertyModel.of(this, "application.sessionTimeout")));
Or if it is a property of your session, you can add the getter to your custom session:
public MySession extends WebSession {
public static final int SESSION_TIMEOUT = 30; // minutes
public int getSessionTimeout() {
return SESSION_TIMEOUT;
}
}
And retrieve it in your label:
add(new Label("timeout", PropertyModel.of(this, "session.sessionTimeout")));
The expression for the property models make use of the fact that Component has a getter for the Application and a getter for the Session.

SelectOneMenu not displayed correctly

I would appreciate some input on the following issue:
I got one login screen followed by another page with a Panel and inside this Panel a SelectOneMenu. Unfortunatly the output of the SelectOneMenu after login is sometimes like this:
Instead the full(!) name of the User should be placed in the middle of the SelectOneMenu.
Sometimes it works, sometimes it doesn't.
Also if I switch User now, I only get the first letter of it. (Inside the dropdown the full name is written tho)
I populate the content inside a ManagedBean (#ViewScoped) in it's PostConstruct and get the data from database. (View -> ManagedBean -> DAO class -> ManagedBean).
I also tried to put the code inside public Classname{} with the same result.
I think there is a problem with the SelectOneMenu not correctly being rendered.
How to fix that?
users.xhtml:
<p:selectOneMenu id="somSelect" value="#{userManagerBean.somValue}"
styleClass="selecters">
<p:ajax update="userDataTable" listener="#{userManagerBean.changeSomValue}" />
<f:selectItems value="#{userManagerBean.userList}" />
</p:selectOneMenu>
ManagedBean #ViewScoped:
#PostConstruct
public void init() {
// DAO Method
retrieveTableData();
String loggedInUser = "";
try{
loggedInUser = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("sprintUser").toString();
}catch(Exception e){
System.err.println("> No previous login");
}
// Check for session login name and select from table - if session null select first
if (somValue == null && userList.size() != 0) {
somValue = userList.get(0);
for(int i = 0; i < userList.size(); i++){
if(loggedInUser.equals(userList.get(i))){
somValue = loggedInUser;
}
}
}
selectedUser = somValue();
userData = new ArrayList<User>();
// a Table population
populateUser(userData);
}

Categories

Resources