Should be direct HTML printing in a JSP declaration tag function legal?
<%! void recursivePaintLevels(List<String> things, int deepLevel){ %>
<ul class="level-<%=deepLevel%>">
<% for (int i=0; i<things.size(); i++){ %>
<li class="whatever">
//(...)
</li>
<% } %>
</ul>
<% } %>
And then call it like this in normal JSP body flow:
//(...)
<% recursivePaintLevels(things, 1); %>
I mean would be like using same normal JSP logic of implicit out.println() but in a method.
For me it is not working (Eclipse says 'Syntax error, insert "Finally" to complete TryStatement') but I am not sure if my error has something to do with it.
I also know I should use JSLT and EL, but this is my choice.
No, it's not legal. The JSP page is effectively implemented as one big method that executes all of the code within the page. In java, you can't simply insert other methods nested within a method.
You code would generate something like this:
public void _jspService(...) {
...
void recursivePaintLevels(...) {
...
}
}
And that's simply not legal java.
Instead you should defer the code to a utility library class bundled with your web app.
You MIGHT be able to create a recursive tag file, I have not tried that.
I believe this is pretty much legal and valid though a bad practice.I think the problem here is because of the double quotes "level-<%=deepLevel%>"
Try separating that using
<% String str= "level-"+deepLevel; %>
and then use
<ul class="<%=str%>"> .
or simply replace the whole line with out.println
EDIT:
It appears that the body of the methods in jsp should not have any scriptlets. I have tried to embed one scriptlet with no content and observed that the generated java file adds the first part (from delcaration to the content before scriptlet )at the begging and the remaining part of the method at the end (and all member variables and other method declarations become part of this method). Apologies for providing wrong answer (as i have noticed that behavior with the cached jsp).
Looks like out.prinltn is the only solution for this problem
Related
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().
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;
}
%>
Inside a jsp I have a small header :
<%# page import="java.util.*"%>
<% HttpSession CurrentSession =
request.getSession();
...
%>
...and a big html
<html>
...
</html>
If I try to read it as is I get an error of "...is exceeding the 65535 bytes limit".I have to break it up.Since I am new to java I cannot figure it out how to do it.Could you please indicate me the way?
The JSP is converted into a normal Servlet java source, and some generated method is too large, as there is a 64 KB limit (on the byte code) on method lengths.
If possible change static includes (really embedding an other JSP source) with dynamic includes.
The solution (and probably good style) is too introduce a couple of methods into which pieces of the general code is moved. For instance to generate a HTML table row with <tr>:
<%#
void tableRow(String... cellValues) {
%><tr><%
for (String cellValue : cellValues) {
%> <td><%= cellValue %></td>
<%
}
%></tr>
<%
}
%>
...
<%
tableRow("one", "unu", "un");
tableRow("two", "du", "deux");
tableRow("three", "tri", "trois");
%>
P.S.
The above method is too small scale to save much, taking a large piece and create a method
like createResultsTable is more effective.
JSPs get compiled into servlet code, which are then compiled into actual java .class files. JSP code will be put into one big doGet() method, and if your JSP file is really big, it will hit the method size limit of 65535. The limit is coming from JVM specification ("The value of the code_length item must be less than 65536").
You should split the file into several files. I wouldn't split it into different methods as proposed in this thread, since it can make the code logic even more complex in this case, but do a jsp:include for the HTML part(s) like proposed by McDowell.
The <jsp:include page="foo.html" %> standard action can be used to include content at runtime - see some random documentation.
<%# page import="java.util.*" %>
<html>
<body>
<h1 align="center">blablalblalblab</h1>
<p>
<%
List styles = (List)request.getAttribute("styles");
Iterator it = styles.iterator();
while(it.hasNext()) {
out.print("<br>try: " + it.next());
}
%>
</p>
</body>
</html>
after executing my servlet request i'm getting error
org.apache.jasper.JasperException: /result.jsp (line: 1, column: 18) quote symbol expected
org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:42)
can't find any quotes that are not on right place.
Make sure all your quotes are straight quotes, not curvy ones.
Don't use Java in JSPs, please. That's what the standard tag library is for.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<h1 align="center">blablalblalblab</h1>
<p>
<c:forEach items="${styles}" var="style">
<br>try: ${style}
</c:forEach>
</p>
</body>
</html>
In more detail:
Embedding Java code in a JSP makes the page difficult to read (JSP is a tag-oriented language), difficult to maintain, and difficult to debug.
The standard tag libraries are already debugged, have plentiful documentation and examples, and probably already Do What You Want To Do.
If you truly have some logic that needs to be performed in Java and no pre-existing tags exist, you can either a) put the logic in a bean and call it via JSTL or b) write your own tag using tagfiles.
Why is Java code better in a bean or tag library than in a JSP?
Testing is a big factor: beans and tag libraries can be tested
outside of a running servlet environment with ease.
Tag libraries are reusable and significantly cleaner than JSP includes.
I guess you have copy pasted it from somewhere, make sure the double quotes are proper. I had the same issue when I copied it from a PDF, it was resolved once I corrected my double quotes.
Your JSP works just fine with Tomcat 6. So, it's probably either some include-related issue or some previously compiled classes are not getting recompiled.
Try to clean up your Tomcat work directory and try again.
Check " if you copied it from somewhere. I had the same error because of ".
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page isELIgnored=”false” %>
double quotes around the false are the wrong ones. Change it to " and it will work.
While I agree with Scott A's admonition to use JSTL instead of putting Java directly into the JSP the question deserves being explored a little further. I just encountered this myself for the first time and had to dig a bit ot answer it.
Technically the error means what it says. You're missing some quotes somewhere. The simplest would be something like in your h1 tag if it read:
<h1 align=center>
instead of what you have.
<h1 align="center">
Obviously there is nothing in the code snippet that you pasted which is missing quotes so I would explore a couple of things.
First, what does the output of your it.next() look like? Since you're pulling in a list called styles I wonder if something in there is making jasper think it's a style tag instead of text you are trying to render.
Second, I would explore Pradeep's answer and see what if there is some subtle issue pasting that was resolved when you pasted it here on stackoverflow. Specifically I would look for 'smart quotes' IE many text editors (including outlook and most of office) like to use different quotes on the front and back of quoted text.
IE
'this is quoted text'
becomes
`this is quoted text'
which can be difficult to notice.
I have a JSP which composes a List of Objects, then renders JSP fragments depending on the Class of each of the objects in the List.
At the moment, this is done with a huge chain of if statements inside the 'parent' JSP:
if( bean.getFilterChildByType( Level.class ) != null )
{
%> <jsp:include page="filters/level.jsp"/> <%
}
if( bean.getFilterChildByType( Sources.class ) != null )
{
%> <jsp:include page="filters/sources.jsp"/> <%
}
...
So, my question is, in JSP (Tomcat) is it possible to achieve this same functionality without an if chain, just by iterating the Objects in the list and perhaps taking advantage of the naming convention "Class name".jsp ? I've played with:
<%# include file="filename" %>
but this doesn't seem to allow variables in the file-name either.
Something like this should work
<jsp:include page="filters/<%=filename%>.jsp"/>
Resolve the appropriate jsp to be included (based on bean.getFilterChildByType) at the controller side and then just pass the name of the jsp to the container jsp. Now this can be easily included.
This is a tough one!
If the included jsp files (level.jsp, source.jsp, etc) are not too complex, what about shifting the HTML from those files over to a function call of the objects you are calling bean.getFilterChildByType(...) on?
That way, instead of a large if/else tree, you could then just call:
String html = bean.getHtmlForType();
...would likely work out much cleaner in a loop too.