I've spent a day looking for the right solution, but no luck!
The question is that how to call java constant variables from jsp with el ${bean.objectName} for example. What is the best practice?
I wonder if this is doable, im quite new to Spring and jsp.
Constant class:
public class RNConstant {
public static final String HELLO_WORLD = "Hello World again!";
public static final String DEFAULT_LOCALE = "id_ID";
public static final String CONTEXT_PATH_SOAP_SR = "soap.sr";
}
Expectation in jsp to be called with EL
<p>${RNConstant.HELLO_WORLD}</p>
I could do this with scriptlet as below, but i could not get this working if it runs in weblogic. This works in apache tomcat v7 or v8
<%# page import="static id.co.telkom.common.RNConstant.*" %>
...
...
<%= HELLO_WORLD %>
Error in weblogic
home.jsp:2:18: Syntax error on token "static", Identifier expected after this token
<%# page import="static id.co.telkom.common.RNConstant.*" %>
^-------------------------------------^
home.jsp:11:19: HELLO_WORLD cannot be resolved
Hello world! <%=HELLO_WORLD%>
^--------^
java version: 1.6
pom.xml
spring
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>3.2.8.RELEASE</org.springframework-version>
<org.springjs-version>2.0.5.RELEASE</org.springjs-version>
<org.springws-version>2.2.1.RELEASE</org.springws-version>
<org.springsecurity-version>3.2.3.RELEASE</org.springsecurity-version>
<jackson-version>1.9.10</jackson-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
Scriplet issue was solved with below codes, and Content of RNConstant is still the same.
<%# page import="id.co.telkom.common.RNConstant" %>
...
...
<%= RNConstant.HELLO_WORLD %>
Cheers,
Hendry
Keep the import statement simple
<%# page import="static id.co.telkom.common.RNConstant.*" %>
Remove ".*" after RNConstant. Also remove static word in the beginning.
<%# page import="id.co.telkom.common.RNConstant" %>.
To call HELLO_WORLD constant use
<p>${RNConstant.HELLO_WORLD}</p> <p>${RNConstant.HELLO_WORLD}</p>
Expectation in jsp to be called with EL
<p>${RNConstant.HELLO_WORLD}</p>
EL checks the bean and translates HELLOWORLD to getHELLOWORLD() because specs says that attributes must be accessed in this way, so you must create a getter or visibility for constants will be limited in jsp view:
public class RNConstant
{
public final static String HELLO_WORLD = "Hello World again!";
public static String getHELLO_WORLD() {
return HELLO_WORLD;
}
}
If you can't create getters check this answer
Related
Given
// Java abstract code
labelName = '<script> alert('xss'); </script>'
// JSP
<%# taglib uri="org.company.tag.tagobject" prefix="tagobject" %>
<tagobject:labelName/>
Expected result
JSP shows string properly without accidental JavaScript code activation
Actual result
JSP taglib tag activates JavaScript (thus can be easily used for XSS)
// Result from code at the start
shows alert with text xss
I tried:
<c:out value="<tagobject:labelName/>" />
<c:out value="${fn:escapeXml(tagobject:labelName)}" />
But it doesn't work.
Steps to reproduce:
taglib file tags.tld:
<tlib-version>1.0</tlib-version>
<jsp-version>2.2</jsp-version>
<short-name>org</short-name>
<uri>org.company.tag.tagobject</uri>
<tag>
<name>labelName</name>
<tag-class>org.company.tag.LabelName</tag-class>
<attribute>
<name>plural</name>
<required>false</required>
</attribute>
<body-content>empty</body-content>
</tag>
</taglib>
java class LabelName:
private void writeDescriptor (String descriptor) throws JspException, IOException {
final JspWriter writer = getJspContext().getOut();
writer.print(descriptor);
}
jsp file home.jsp
<%# taglib uri="org.company.tag.tagobject" prefix="tagobject" %>
<tagobject:labelName/>
write something into string variables of that tagobject, so they are used as descriptors and shown at jsp.
Part 2 String descriptor already contains string representation of JavaScript, so that probably I can filter JavaScript code there.
Probably c:out or fn:escapeXml can be used there but I'm not sure how. Also I'm not sure which code is needed to explain better.
First solution
I've tried to filter string on part of Java custom tags (step 2, in java class LabelName). Found library for this named owasp-java-html-sanitizer.
So, now LabelName class looks like this:
private void writeDescriptor (String descriptor) throws JspException, IOException {
final JspWriter writer = getJspContext().getOut();
String safeString = new HtmlPolicyBuilder().toFactory().sanitize(descriptor);
writer.print(safeString);
}
Have not checked all the possible xss inputs but at least it removes simplest ones i've checked.
I got the following code kind of inside of my <% %> in my jsp file.
Two problems here:
Why doesnt my breakpoint doesnt stop in those lines?
Why does have a nullpointerException happen when i use these variables somewhere inside my jsp like these <%=beneficiariesList%>. This value debugging in eclipse in the display view says " beneficiariesList cant be resolved" . For example tipoBeneciarioDatosClientes says the value which is "XXXX"
<% ...... bla bla bla
String tipoBeneficiarioDatosClientes = "XXXXX";
String beneficiariesList = "XXXXX";
if (null != polizaBean.xxxxx() && !polizaBean.getTipoBeneficiario().isEmpty()) {
tipoBeneficiarioDatosClientes = polizaBean.xxxxxx();
if(tipoBeneficiarioDatosClientes.equalsIgnoreCase("xxxxx")) {
JSONArray beneficiaries = JSONArray.fromObject(polizaBean.xxxxx());
beneficiariesList = beneficiaries.toString();
}
}
%>
You have a NullPointerException because variables which you are using inside Scriptlets <% ... %> are only available inside that scriplet.
If you want to declare variable which will be available in Expressions <%= %> you need to declare them inside a Declations block <%! %>.
From JSP 2.0 Specification :
Declarations are used to declare variables and methods in the
scripting language used in a JSP page.
...
Declarations are initialized when the JSP page is initialized and are made
available to other declarations, scriptlets, and expressions.
I got a situation with a project I'm working on (not my code). I'm a somewhat beginner with JSPs, so it would be great to find out what happened.
So I have a code like this (it's a lot simplified):
<jsp:useBean id="accessManager" scope="session" class="AccessManager" />
<%! Object x = accessManager %>
<% Object y = accessManager %>
The second line doesn't work, it doesn't know what accessManager is. The third line (y) works.
I know that declaration scriptlets translate into java class attributes or methods, which are executed once when the jsp in initialized, and normal scriptlets (<% %>) are translated into the _jspService method. But what's the scope of the two? Or why can't I access the bean from the declaration scriptlet?
Thanks!
! is used to specify a no-context.
If you use <%! Object x = accessManager; %> it will produce Code like this.
class Index {
Object x = accessManager;
}
If you use <% Object x = accessManager; %> it will produce Code like this:
class Index {
public void foo(){
Object x = accessManager;
}
}
Look at C:\Program Files\apache-tomcat-*\work\Catalina\localhost\*\org\apache\jsp\ for the Generated .java-File.
(The example is simplyfied.)
Use either of the declaration depending on where you would like to add the code in the servlet.
Scriptlet of the form <% code %> that are inserted into the servlet's service method. So, it becomes part of your application logic.
Scriptlet Declarations of the form <%! code %> that are inserted into the body of the servlet class, outside of any existing methods. So, it becomes part of the servlet class. One very good use of it is to insert a method into servlet and use that method from within service method (under tag <% code %>) For ex:
<%!
public int sum(int a, int b) {
return a + b;
}
%>
this is my index.jsp page:
<html>
<body>
<%!
public class myclass{
private final int foo = 42;
public int getFoo() {
return foo;
}
}
%>
</body>
</html>
how to call myclass method or variable in other jsp page ?
please help me .
You don't from any "other" JSP. Those declarations should be treated as local to the JSP. If you need a class to be used by multiple JSPs, write it as a separate Java source file, compile it, and include it in your webapp in WEB-INF/classes.
Did you try to use something like
<%# include file="/myFile.jsp" % >
???
This test was prompted by reading a question on the Sun java forums and thought I would try it out.
The JSP2.0 specification section JSP.13.8 contains an "Example Simple Tag Handler Scenario". I copy and pasted the code fragments and attempted to run it.
Environment:
Apache Tomcat version 5.5.26 and 6.0.14 (tested on both)
Java: 1.5
Code I am testing with:
Jsp page:
<%# taglib prefix="my" tagdir="/WEB-INF/tags" %>
<my:simpletag x="10">
<jsp:attribute name="y">20</jsp:attribute>
<jsp:attribute name="nonfragment">
Nonfragment Template Text
</jsp:attribute>
<jsp:attribute name="frag">
Fragment Template Text ${var1}
</jsp:attribute>
<jsp:body>
Body of tag that defines an AT_BEGIN
scripting variable ${var1}.
</jsp:body>
</my:simpletag>
And the tag file:
<%-- /WEB-INF/tags/simpleTag.tag --%>
<%# attribute name="x" %>
<%# attribute name="y" %>
<%# attribute name="nonfragment" %>
<%# attribute name="frag" fragment="true" %>
<%# variable name-given="var1" scope="AT_BEGIN" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Some template text.
<c:set var="var1" value="${x+y}"/>
<jsp:invoke fragment="frag" varReader="var1"/>
Invoke the body:
<jsp:doBody/>
This code is directly copied from the PDF copy of the JSP2.0 specification.
It is also available as part of the JSP-API here
Minor change made - I changed the name of the tagfile from simpletag.tag to simpleTag.tag to match the invocation of it in the JSP.
I also tried copying from the PDF of the spec (adjusting quotes as necessary) - same result.
When I execute the page I end up with a standard 500 error
Root cause:
java.lang.ClassCastException: java.io.StringReader
org.apache.jsp.tagVariableTest_jsp._jspService(tagVariableTest_jsp.java:62)
Line62 of the generated JSP turns out to be:
var1 = (java.lang.String) _jspx_page_context.findAttribute("var1");
Ok, I can understand ClassCastException - it thinks that var1 should be a String, and the actual attribute is a StringReader. But why is it a StringReader? Where did the variable get created? And why is it attempting to do this assignment at all?
Can someone please point me in the right direction?
What is wrong with the code/setup?
Is this a known issue? I googled for it but couldn't seem to find anything.
Thanks,
evnafets
Editing with resolution:
The ClassCastException was being caused by the line in the tag:
<jsp:invoke fragment="frag" varReader="var1"/>
As mentioned here the varReader attribute specifies the attribute to store the evaluation result as a StringReader. The exception was caused by Tomcat generated code trying to retrieve the value of "var1" and cast it to a String. As a String is not a StringReader so, it raised an exception at that point.
I'm not sure if the coding error is they should have used the "var" instead of the "varReader" attribute, or they shouldn't have used either and just evaluated it as is.
Removing that attribute completely prints out the fragment, and then the body both with the value of "var1":
Fragment Template Text 30.
Invoke the body: Body of tag that defines an AT_BEGIN scripting variable 30
Making the attribute var="var1" executes the fragment, and stores the result to var1. The body is then evaluated with this new value of var1 resulting in:
Invoke the body: Body of tag that defines an AT_BEGIN scripting variable Fragment Template Text 30
Personally I think the first case makes more sense, but this code is presented as an example of the innerworkings, not best practice.
I still would have expected the example to compile/run in any case. I was fairly surprised when it didn't.
From the syntax reference you can see that either var or varReader is
The name of a scoped attribute to store the result of the fragment invocation in
So I am afraid the sample code contains an error. If you need to write the result of jsp:invoke directly to the page you do not need to assign it to a var.
Can you try leaving out the "varReader" attribute?