h:link in JSF gets called automatically - java

I am creating a user authentification in JSF2, and my header displayed on every page contains this:
<c:if test="#{user.loggedIn}">
<li><h:link value="Log out" outcome="#{user.logout}"/></li>
</c:if>
User refers to the userBean, and logout() simply invalidates the session, and issues a redirect to the login page. So when the user logs in, user.loggedIn becomes true, and logout link gets displayed, but it somehow immediately gets called, and the user is immediately logged out.
Does anyone have an idea why is this happening? I thought of using h:commandLink, but it requires a form, and I'm trying to avoid it.
Edit:
I copied the wrong code... just my luck after spending an hour figuring out why the user cannot login. You can look at the previous revision to see miscopied code.

That can happen when the JSF tags are not recognized and parsed as such and it effectively get rendered as plain text wherein all EL expressions are evaluated as value expressions. It would in your case basically print the returned value of #{user.logout()}. But while EL does that, the method's logic is of course invoked.
If you remove the action attribute and open the page in browser and do a View Source, then you'll see an unparsed <h:commandLink> tag instead of the generated HTML <a> element.
Make sure that you have the h: XML namespace definied on the right URI in the root tag of the view file.
xmlns:h="http://java.sun.com/jsf/html"
Update: the <h:link> isn't intented to invoke bean actions. It's intented as a pure GET link. The outcome is per specification evaluated as a value expression, not as a method expression. The outcome must represent a view ID where the link has to navigate to. When the EL evaluates your method as a value expression, it's of course immediately invoked. Just keep using <h:commandLink> in combination with a redirect. Additional advantage is that this isn't bookmarkable nor searchbot-crawlable.

This is the example from jsfToolbox:
<h:commandLink id="link1"
value="#{bundle.checkoutLabel}"
action="#{shoppingCartBean.checkout}" />
Get rid of your parens at the end of logout.

Related

expiring the session of user if new tab is opened in browser using struts2 interceptors

My application is in struts2.
I have requirement that I am storing my application details in session. I cannot remove those attributes from session. After I log-in I have to choose an object to work on. Now I open a new tab and choose another object for working. Due to which my first object values are over written. Hence if in my first tab I do some work wrong information is updated for that action.
This is how I am planning to solve the issue.
I am trying to set a value in setter method in interceptor class but I cannot access that value in my index.jsp.
This interceptor is called on all the actions and index.jsp is also included in every jsp.
I will maintain a hashtable which will store the userid and a random string of 40 characters. This id will be unique and I will update the userid after comparing the value present in jsp to value stored against the value stored in hastable.
If I find that value matches then I will generate another value and store in jsp and hastable. If value does not matches I will destroy the session.
Kindly advice how can I proceed or is there any other work around to achieve the same.
code
Interceptor class
String strFrom = (String)aContext.get(ServletActionContext.ACTION_NAME);
HttpServletRequest httpReq = (HttpServletRequest)aContext.get(ServletActionContext.HTTP_REQUEST);
HttpSession session = httpReq.getSession();
String sessionValue = (String)httpReq.getSession().getAttribute("sessionValue");
String test = httpReq.getParameter("sessionValue");
if(strFrom.equals("ValidateUser")){
// Do nothing
}else if(sessionValue == null && strFrom.equals("HomePage")){
session.setAttribute("sessionValue", getRandomString(20));
}else if (sessionValue.equals(session.getAttribute("sessionValue"))){
session.setAttribute("sessionValue", getRandomString(20));
}else{
httpReq.setAttribute("message","Session Expired. Please Login Again");
return "loginAgain";
}
index.jsp
<body>
<s:hidden id="hidBidType" value="%{#session.tenderBidType}"/>
<s:property value="%{#session.sessionValue}"/>
<s:hidden name="sessionValue" id="sessionValue" value="%{#session.sessionValue}"/>
</body>
login.jsp
<form name="loginPage" method="post">
<s:hidden name="sessionValue" id="sessionValue" value="1"/>
</form>
For your randomly generated value of 40 characters, why not use timestamp?
Well, I don't see much advantages of your aproach (but I could be wrong, of course). You still can register a SessionListener and check if the user has session, cant't you? So, do you realy need to do all this kind of stuff is up to you, but I wouldn't do it that way - Interceptor for all pages, store value in the page, check if is the same... Just register one SessionListener and put your user ID or some otrher user's unique value in session, compare and destroy session (or whatelse you need).
Hope this helps.
EDITED
I'm working on a web application with a similar requirements. What we do (and I'm sure is not the best choice) is after logging open new window without navigation bar and close the loggin window. Then we capture all the events on the window and disable many features like ctrl+tab, right click etc. In this application the user is not allowed to open more than one window. I repeat - this is probably not the best choice. Just an idea.

Sending info from Servlet to JSP

What I want to do:
I have a form with a lot of fields(nick, email, name, surname, etc.) but the user has to fill Nick and Email first in order to be able to fill the other fields(this is because we want to check that the nick and mail aren't in use by another client before he can introduce the rest of his information(name, surname, etc.)).
So, the user introduces Nick and Email and then he must press a button named "Validate", if the values are available(successful validation) then the rest of the fields are enabled and the user can continue filling the form, otherwise the fields stay disabled and an error is showed to the user.
The form will be located in a JSP, it will be submitted to a Servlet, once in the servlet I must validate the information that is in the form(i have a .JAR file included in this servlet, the validation consists in calling a function from that library, the function returns a boolean) and then I must return back to the same JSP the boolean that will represent the result of the validate function.
Now in the JSP I must enable(or not, depending on the value of the boolean) the rest of the TextFields.
I'm not sure if this is right but i was trying to submit with the button and at the same time run a javascript(onclick) that will use this boolean value that the servlet sends back to the JSP after making the validation. The javascript consists on an IF sentence that evaluates the boolean and if it's true then it enables all the fields on the JSP.
Problems so far:
I was able to send the Nick and Email from the JSP to the Servlet and to make the validation of the values, now i have the boolean but i have no idea on how to send it from the Servlet to the same JSP and use it in the onclick event of the same button I used to submit the info. I don't even know if it's possible to do this...
I'd be grateful if someone could give me a hand with this, i'm newbie in Java programming so i would appreciate simple explanations if possible.
Also, if there is a better way of doing what i want please share it, and if there are any doubts ask and i will try to explain it better.
There is no need for JavaScript at all.
In your servlet you can store the validation result into the request context:
req.setAttribute('checkResult', checkResult);
where req is of type HttpServletRequest and checkResult is a Boolean.
Then you can forward to your JSP:
RequestDispatcher dispatcher = req.getRequestDispatcher("/your.jsp");
dispatcher.forward(req, resp);
In your JSP you can set your form elements as read only depending on the attribute checkResult which you have put into the request context:
<textarea name="text" cols="50" rows="10"
<%= request.getAttribute("checkResult") != null && request.getAttribute("checkResult") ? "" : "readonly" %>
>...</textarea>
So if the check is not valid then the <textarea> element will contain the readonly attribute. Otherwise readonly is not present.
As Roy mentioned AJAX is best suited for your problem. You can use DWR! , it makes normal java classes available as AJAX services, just call the method on them and get the result. So easy.
I think AJAX is more suitable for your application, which will not require to submit the whole form and you can send back the validation flag as plain responseText or well-formatted responseXML. Also you can use a lot of good javascript library such as jQuery that helps you send an AJAX request quickly and simply.

c:out value behavior

I am relatively new to working with JSPs and I have a feeling I'm overlooking something simple. I have a segment that appends a key onto a URL before sending the user back to where they came from. The key is a string value and when it consists of only numberic values(for example 12345) it works fine, but when it contains non-numerics(for example abcde) it simply appends "#" to the url and stays on the same page.
<core:when test="${dataTransferObject.someBoolean}">
Back to Home
</core:when>
When it's a string the JavaScript will be illegal–it will think you're trying to reference a non-existent JavaScript variable. You will see an error your JavaScript console.
Don't do any JavaScript operations; JSP is evaluated on the server side before the client sees it:
onclick="javascript:location='path/back/to/their/home.request?cachekey=<core:out value="${dataTransferObject.stringVariable}"/>';return false;"
Better yet, use JSP EL:
onclick="javascript:location='path/back/to/their/home.request?cachekey=${dataTransferObject.stringVariable}';return false;"
Also, if this is the JSTL core tag library, the canonical prefix is "c".

Various Questions about JSF

i'm doing a JSF2 project.
1 . i have a form with some checkbox. Look the following code
<ui:repeat>
<h:selectManyCheckbox value="#{wagent.selectedPra}">...
</h:selectManyCheckbox>
</ui:repeat>
So i use selectManyCheckbox inside ui:repeat and i want that the value of the different selectManyCheckbox point to the same value.
But when the form is submit i didn't have all the selected boxs.
How i can do that ?
2 . I have a form with some inputs. On my action i want to merge some pdf files, stay on the same page and that a pop-up appear to offer to download the merged files.
3 . Does all the managed beans with request scope are created for each request or just if i used them in the xhtml page?
4 . I have a commandlink to logout. On my action i use session.invalidate() and return "login". So i go back to the login, but when validating the login, my session managed bean doesn't seem to be created. Error is something like yourSessionBean is null. What's wrong ?
1: So i use selectManyCheckbox inside ui:repeat and i want that the value of the different selectManyCheckbox point to the same value. But when the form is submit i didn't have all the selected boxs. How i can do that ?
Let them point to a different value instead. With the given example the bean value will be overridden everytime until end of the loop. As an example, use a List<List<Pra>> in a bean (or whatever Pra means in your question):
<ui:repeat value="#{wagent.allSelectedPra}" var="selectedPra">
<h:selectManyCheckbox value="#{selectedPra}">
...
</h:selectManyCheckbox>
</ui:repeat>
2: I have a form with some inputs. On my action i want to merge some pdf files, stay on the same page and that a pop-up appear to offer to download the merged files.
At least two things needs to be done:
facesContext.getExternalContext().addResponseHeader("Content-Disposition", "attachment;filename=name.pdf"); // Force "Save As" dialogue.
facesContext.responseComplete(); // Prevent JSF from taking response in hands.
3: Does all the managed beans with request scope are created for each request or just if i used them in the xhtml page?
They are created for every HTTP request. The scope which you described only applies on view scope (if I understand you right).
4: I have a commandlink to logout. On my action i use session.invalidate() and return "login". So i go back to the login, but when validating the login, my session managed bean doesn't seem to be created. Error is something like yourSessionBean is null. What's wrong ?
You are probably accessing the session scoped managed bean the wrong way. You need to either inject it as #ManagedProperty or to grab it by Application#evaluateExpressionGet().

why use<bean:include instead of <jsp:include in struts?

why use<bean:include instead of <jsp:include in struts?
from the documentation for bean:include
Perform an internal dispatch to the specified application component (or external URL) and make the response data from that request available as a bean of type String. This tag has a function similar to that of the standard jsp:include tag, except that the response data is stored in a page scope attribute instead of being written to the output stream. If the current request is part of a session, the generated request for the include will also include the session identifier (and thus be part of the same session).
first hit on google
bean:include works almost like jsp:include except that the result is stored in the page scope. This means that your code on the current page can access the results and manipulate it. See this page.

Categories