Java JSP Using Include with Variable Parameters - java

I'm trying to pass a parameter to the jsp file that I am including in my main jsp. From what I've seen online the way to do this using c:set
approot/index.jsp
<c:set var="Arg01" value="Argument01"/>
<jsp:include page="include/other.jsp">
<jsp:param name="myArg01" value="${Arg01}"/>
<jsp:param name="myArg02" value="Argument02"/>
</jsp:include>
Although when I try to use the variables in the included jsp page only the one argument seems to be coming through (the second one which is not using c:set)
approot/include/other.jsp
<!-- this doesn't work -->
<p>${param.myArg01}</p>
<!-- this does -->
<p>${param.myArg02}</p>
Nothing crashes but I can see that myArg01 is blank

This way of getting around it is probably awful but it's the only way I could find to get around the issue.
I used a different kind of include in my main JSP
public static String myArg01 = "Argument01";
public static String myArg02 = "Argument02";
<%# include file="include/other.jsp" %>
Then I could reference the variables directly inside the included JSP file
<p><%= myArg01 %></p>
<p><%= myArg02 %></p>

Related

Is it possible to create a local page scope in a JSP?

I'm working on a componentization system based on JSPs. This means that parts of the JSP can be moved from one JSP to an other one via drag and drop and leads to a need for a local page scope as variable of a component defined in one JSP my collide in an other JSP.
I can use Servlet 3.0 / JSP 2.2 / JSTL 1.2.
++ Tag File ++
The straight way of doing that would be to create a tag file for a component or something similar as they have this local page scope. But for every change in the tag file it would need to get redeployed and needing to create a tag file needs some time by itself. But if there is no other solution this direction (custom tags, tag files, JSP includes,...) is probably the way to go.
++ Namespace prefixing/suffixing ++
In Portlets one is supposed to concatenate each variable with a namespace provided from the portlet response object. I could do something similar but this can lead to side effects and unexpected behavior. If someone forgets to prefix/suffix the namespace it might work for some time but stops working at an other time without changing the code when the component moved to an other JSP with a conflicting variable name.
++ Custom Tag wrapping ++
I was hoping that I as a component framework developer can wrap the component code of a component developer with a tag file for a component tag like this
<a:component>
<div data-component-id="9">
<c:set var="componentId" value="9"/>
<c:set var="path" value='${abc:getCurrentPath()}_${componentId}'/>
<c:set var="resource" value='${abc:getResourceFromPath(path)}'/>
<c:set var="val" value="${resource.getValue('paragraphValue')"/>
<p><c:out value="${value}"/></p>
</div>
</a:component>
to have the variable in the local page context of the tag file. But instead they are in the context of the surrounding page. I'm looking for something like this
<% { %>
<div data-component-id="9">
<%
String componentId = 9;
String path = obj.getCurrentPath()+componentId;
Resource resource = otherObj.getResourceFromPath(path);
String value = resource.getValue("paragraphValue");
%>
<p><c:out value="<%=value%>"/></p>
</div>
<% } %>
which would create a code block in which variables have their own namespace. But of course for JSTL and JSTL-EL instead of scriptlet code.
I had a look at the JSTL specification but did not find out if there is a way to create such a local page scope. But I didn't check everything as it's huge and I'm not sure if it's possible with custom tags.
It is clear to me that bigger code blocks should not be in the JSP but with the framework I would like to provide simple solutions for smaller components.
++ Changing the JSP code ++
When components are initially placed on a JSP or moved around via drag 'n drop I actually move the JSP code of a component from one JSP to an other or within a JSP. This means I can also programmatically manipulate the JSP code of a component if it doesn't get too complex and it helps solving the problem.
As I thought that custom tag wrapping could be the ideal solution I created an other more specific question and I've got an answer here that solves the problem.
It's simply to remove all pageContext attributes before the evaluation of the body and adding them again at doEndTag().

simple way to transfer data from java class to javascript

I have a string String myString = "This is some text." I also have a getter getMyString()
I have a jsp page I want to bring it to and then store it in localStorage. since this isn't exactly my expertise I've tried doing it like...
var myJSString = "<%=myString%>";
var myJSString = <% getMyString(); %>
they both give me the same error
HTTP Status 500 - org.apache.jasper.JasperException: Unable to compile class for JSP
root cause
org.apache.jasper.JasperException: Unable to compile class for JSP
I've looked through numerous tutorials and I haven't been able to get this to work. What other ways are there to put a java variable into a javascript variable?
Why don't use Expression Language or JSTL? e.g.
Expression Language
var myJSString = "${myString}";
JSTL
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
...
var myJSString = '<c:out value="${myString}"/>';
You cant really access the variables created by JSP in javascript. What I used to do is , create a hidden element and assign the value to it via scriptlet. Once the page loads , access the hidden element's value via javascript.
<input type="hidden" id="accountName" value='<%= bean.getAccountName(); %>'/>
Now when the page is rendered you will get something like this.
<input type="hidden" id="accountName" value='Myaccountname'/>
You can access this value with javascript using document.getelementByID("accountName");
Note:
1.getAccountName() should be called from a bean
2.I havent checked the syntax of the code above.Just typed it fast , but this method will get your job done.

Variable refering in two different jsp pages

If i declare a variable in my A.jsp and i am trying to include A.jsp to B.jsp.So my question stands here whether the variable declared in A.jsp is acessable in B.jsp?
Please explain me for both the cases Dynamic include and static include.
When you include a jsp template using <%#page include=""> the source will actually be inserted and compiled into the including file. This is what makes you able to use variables declared in the parent file.
When doing a "dynamic" include it will use RequestDispatcher.include which will invoke the calling page as a new Servlet. This makes you unable to use declared variables.
I would recommend you to pass variables on the request scope using request.setAttribute("name", obj); when doing this
You can't pass server-side parameters using the <%# include %> directive. This directive does a static include. The contents of the included file are statically inserted into the including page. That is, during translation time from jsp to servlet.
Use the <jsp:include> tag instead, it is processed at runtime, and with it you can pass parameters using <jsp:param>.
For instance, if you have a.jsp with
<jsp:include page="b.jsp" />
<jsp:param name="param1" value="value1" />
<jsp:param name="param2" value="value2" />
</jsp:include>
You can get those parameters as request parameters in b.jsp
<% String v = request.getParameter("param1"); %>
Take into account you can still get request parameters available on a.jsp in b.jsp.

How can I reuse code in JSP?

For example, a user will be rendered throughout my application as
<div class="user">
<p class="username">${user.name}</p>
<p class="karma">${user.karma}</p>
<img src="/users/${user.id}"/>
</div>
How can I reuse this code block?
Note - my code is running within a tag, so I can't use tags for this (or any JSP) otherwise I get a Scripting elements are disallowed here error.
Edit
I'm trying to use a tag file, but getting PropertyNotFoundException.
This is my tag file called 'user.tag':
<%#tag description="User" pageEncoding="UTF-8" %>
<a href="../user/showUser.do?userId=${user.id}">
<p>${user.name}</p>
<img class='avatar' src='${user.avatarUrl}' alt=""/>
</a>
And usage inside a jsp:
Where job.poster is a java bean with id, name, and avatarUrl properties.
If I add
<%#attribute name="user" %>
to the tag file, then I get an exception
Property 'id' not found on type java.lang.String
Since JSP 2.0, there is yet another kind of tags: Tag files. Tag files are JSP custom tags written as a JSP template itself, which seems to be what you want.
http://fforw.de/post/creating-jsp-layouts-with-page-tags/ shows how to use such a tag file as general layout solution. Using them as component should be even easier.
You should be able to use tag files within tag files; this works for me in a JSP 2.2 container:
<%-- mytag.tag --%>
<%#tag description="demo code" pageEncoding="UTF-8"%>
<%#taglib prefix="cust" tagdir="/WEB-INF/tags" %>
<%#attribute name="message"%>
<cust:mytag2 message="${message}" /><%-- uses mytag2.tag --%>
If that fails, you can use the include directive: <%#include file="/WEB-INF/jspf/fragment.jspf" %>
Note that the spec says about tags:
Directive Available? Interpretation/Restrictions
======================================================================
page no A tag file is not a page. The tag directive must
be used instead. If this directive is used in a
tag file, a translation error must result.
So, fragment.jspf must not have a any elements that are not supported in tags, including a page directive.
For the example you have given it sounds like some templating framework is needed, to display the user badge on each screen. At its simplest level this may just be a jsp:include which always includes your "UserBadge.jsp".
If you are running on a web framework e.g. JSF you may use Facelet templates or write a custom component for this. So the answer depends on what framework you have. Breaking it down to just JSP and JSTL - the included JSP or a javax.servlet.jsp.tagext.Tag would certainly reduce the duplication.
Always be careful to follow the DRY Principle... Don't Repeat Yourself!
I feel sometimes creating a .tag file is overkill (especially if it's only for one page), and I've wanted what you describe for years, so I wrote my own, simple solution. See here:
https://stackoverflow.com/a/25575120/1607642
Why don't you use a custom tag or jsp functions.
Thanks,

JSP.13.8 Example Simple Tag Handler Scenario doesn't work?

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?

Categories