Why doesn't the following work:
<c:set var="formId" value="#${otherFormId}"/>
where
<c:set var="formId" value="# ${otherFormId}"/>
notice the space ^
works fine (though is invalid for my purposes). Im trying to prepend ${otherFormId} with a # symbol (i.e. creating jquery id selector).
The first form ends up with
#${otherFormId}
literally in the output. How can I get the outcome I am after?
Got the answer.
#{expr}
is an expression whose evaluation is deferred (something to do with JSF lifecycle requirements) and was introduced as part of the Unified EL. To get around my problem you now need to escape any literal #'s. e.g.
<c:set var="formId" value="\#${otherFormId}"/>
Related
I am trying to use s:url and the value contains a property. And it's not working.
<s:url value='/js/myJS-<s:property value="locale"/>.js'/>
Expected output:
....../contextPath/js/myJS-en_US.js
Nesting JSP tags like that is illegal.
Use normal JSP EL (assuming you're on a container supporting it):
<s:url value="/js/myJS-${locale}.js"/>
If you're not running a container that supports JSP EL (ew), use OGNL:
<s:url value="/js/myJS-%{locale}.js"/>
It's arguable this is the preferred mechanism since OGNL is S2's default EL.
When reporting something as "not working", you should also include what error(s) you get, for example, in this case, the JSP would never compile.
I've got a variable from an object on my JSP page:
<%= ansokanInfo.getPSystem() %>
The value of the variable is NAT which is correct and I want to apply certain page elements for this value. How do I use a tag to know the case? I tried something like
<c:if test = "${ansokanInfo.getPSystem() == 'NAT'}">
process
</c:if>
But the above doesn't display anything. How should I do it? Or can I just as well use scriptlets i.e.
<% if (ansokanInfo.getPSystem().equals("NAT"){ %>
process
<% } %>
Thanks for any answer or comment.
Try:
<c:if test = "${ansokanInfo.PSystem == 'NAT'}">
JSP/Servlet 2.4 (I think that's the version number) doesn't support method calls in EL and only support properties. The latest servlet containers do support method calls (ie Tomcat 7).
<c:if test="${ansokanInfo.pSystem eq 'NAT'}">
I think the other answers miss one important detail regarding the property name to use in the EL expression. The rules for converting from the method names to property names are specified in 'Introspector.decpitalize` which is part of the java bean standard:
This normally means converting the first character from upper case to lower case, but in the (unusual) special case when there is more than one character and both the first and second characters are upper case, we leave it alone.
Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays as "URL".
So in your case the JSTL code should look like the following, note the capital 'P':
<c:if test = "${ansokanInfo.PSystem == 'NAT'}">
You can use scriptlets, however, this is not the way to go. Nowdays inline scriplets or JAVA code in your JSP files is considered a bad habit.
You should read up on JSTL a bit more. If the ansokanInfo object is in your request or session scope, printing the object (toString() method) like this: ${ansokanInfo} can give you some base information. ${ansokanInfo.pSystem} should call the object getter method. If this all works, you can use this:
<c:if test="${ ansokanInfo.pSystem == 'NAT'}"> tataa </c:if>
I'm using Spring Web Flow (v. 1.0.5) and I have a JSP page that makes an AJAX call to a flow and needs to read in the XML results. That flow successfully sets an object into the FlowScope, then calls a JSP page to render the results. In the JSP page, I'd like to test whether the object has a property (say, .firstName) and if so, do something. I can access the variable in the FlowScope using JSTL expression language (by saying ${userObj}), but that just lets me spit it out. I've tried the methods below to get at it and put logic around it, with varying success.
Update: The remaining question is: How do I get the context and flow scope in the scriptlet (<% %>) section?
<rootnode>
<!-- Attempt 1: c:if isn't being interpreted (though ${userObj.firstName} is),
it's just displaying the tags on the page. -->
<!-- Update, I didn't have the <%# taglib directive for jstl/core.
Now I do, and they're being interpreted, but it says
"According to TLD or attribute directive in tag file,
attribute test does not accept any expressions"
How can the if/#test not accept expressions? Isn't that its whole purpose
in life? -->
<!-- Update 2, I also forgot the taglib for the rt language, which is separate,
I guess (jstl/core_rt). <c:if test now works properly. -->
<c:if test="${!empty(userObj.firstName)}">
<test>not empty</test>
</c:if>
<%
/* Attempt 2: This throws an error, can't resolve "context". How do I get the context? */
if (context.getFlowScope().userObj != null) {
out.write("not null");
} else {
out.write("not not null");
}
%>
<!-- Attempt 3: This works, I get the reference to the Object and it
spits out the correct firstName, gives me no control other than
spitting out the value. -->
<userReference>${userObj}</userReference>
<userReference_firstName>${userObj.firstName}</userReference_firstName>
</rootnode>
Attempt 1 should work if you installed JSTL and declared the taglib the right way and declared the web.xml to be at least Servlet 2.4. Also see the questions:
Where do I put jstl.jar and standard.jar so that Netbeans don't give errors/warnings?
ModelAttributes not accessible on jsp
To test if an object is empty or not, you should rather use the following construct:
<c:if test="${not empty userObj.firstName}">
or
<c:if test="${userObj.firstName != null}">
Attempt 2 is strongly discouraged. Scriptlets are a poor practice and should always be replaced by taglibs like JSTL and EL (as you did in attempt 1). If it's not possible for technical reasons, then the coding ought to be done in a real Java class, (indirectly) starting with a Servlet.
Attempt 3 is doable, but I would recommend to use servlet with a Javabean-to-XML serializer like XStream instead. This way you can just feed a collection of Javabeans to the outputstream of the response transparently.
In files.jsp I am using following anchor and JSTL c:url combination -
<c:url value="downloadfile.jsp" var="dwnUrl" scope="request">
<c:param name="fileType" value="PDF"/>
<c:param name="fileId" value="${file.fileId}"/>
<c:param name="fileName" value="${file.fileName}"/>
</c:url>
Download
On downloadfile.jsp getting the file name value in JavaScript variable as -
selectedFile = <c:out value='${param.fileName}'>
Now, if file name contains some extra character e.g. XYZ 2/3" Technical then on the other page I am getting some different character as - XYZ 2/3#034; Technical
However, if I print request.getParameter("fileName"), its giving correct name. What is wrong?
The <c:out> by default escapes XML entities, such as the doublequote. This is done so to get well-formed XML and to avoid XSS.
To fix this, you should either get rid of <c:out>, since JSP 2.0, EL works perfectly fine in template text as well:
selectedFile = '${param.fileName}';
.. or, if you're still on legacy JSP 1.2 or older, set its escapeXml attribute to false:
selectedFile = '<c:out value="${param.fileName}" escapeXml="false">';
Note that I have added the singlequotes and semicolon to make JS code valid.
Needless to say, you'll need to keep XSS risks in mind if you do so.
The funky characters in your <c:param> values are being URL encoded by <c:url> as they should be. As far as downloadfile.jsp is concerned, the servlet container takes care of URL decoding incoming variables so you don't have to. This is normal behavior and shouldn't pose any problems for you.
If you simply turn escapeXml to false as #BalusC suggests, you will add an XSS vunerability to your page. Instead, you should encode the user input at the time of injection into the destination language, and escape characters that would be evaluated in the destination language. In this case, if the user input contained a single quote character (I'm assuming the string literal in your original example was supposed to be wrapped in single quotes, but the same would be true for double quotes if you were using them), any JavaScript code that followed it would be interpreted by the browser and executed. To safely do what you are trying to do, you should change the line in downloadfile.jsp to:
selectedFile = '${fn:replace(param.fileName, "'", "\'")}';
That will escape only single quotes, which would otherwise end the string literal declaration.
If you were using double quotes, then this would be appropriate:
selectedFile = "${fn:replace(param.fileName, '"', '\"')}";
It is worth noting that escapeXml could be appropriate for escaping JavaScript string literals (and it often is) when the string literal will eventually be dumped into HTML markup. However, in this case, the value should not be XML escaped as it is evaluated in the context of a file path, rather than in the context of HTML.
I have the following code to set a userId variable:
(userId set in prior code)
<c:set var="userId" value="(Cust#${userId})" />
Which produces the following string: (Cust#${userId})
The following code works as expected, however:
<c:set var="userId" value="(Cust# ${userId})" />
displays the following string (Cust# 0001) .
Why does the '#' character before a '${string}' expression prevent the string from being evaluated? Is there a work around I could use that doesnt involve having to insert a space?
Since JSF would use:
#{userId}
To return a user Id, I would venture to guess that this is either a bug or expected behavior caused by the # sign making the parser unhappy. Just use either of:
<c:set var="userId" value="(Cust#${userId})" />
<c:set var="userId" >(Cust#${userId})</c:set>
I tested the above and it does not work. Its ouput would be:
Cust#0002 or whatever.
You can use an escape to get it to work right though. For example:
<c:set var="userId" value="(Cust\#${userId})" />
The output is:
Cust#0002