i am learning JSTL and from tutorials point in this link
when i tried to execute that example in the page which is
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title><c:url> Tag Example</title>
</head>
<body>
TEST
</body>
</html>
i am getting following error.
but i could not understand why and what is the solution for that?
The validator is probably confused by the nested double quotes:
TEST
You can make the code cleaner by doing:
<c:url value="/jsp/index.htm" var="myUrl" />
TEST
which assigns the value of the processed URL to a var named 'myUrl' and then uses JSP Expression language to output the URL.
Change this line:
<title><c:url> Tag Example</title>
By:
<title><c:url> Tag Example</title>
Otherwise, the JSP engine will interpret this (<c:url>) as the beginning of a tag to be processed.
You need to escape your nested quotes as
TEST
Otherwise the HTML parser perceives "<c:url value=" as the href value and complains about the space in between. Alternatively, you can make use of single and double quotes as
<a href='<c:url value="/jsp/index.htm"/>'>TEST</a>
Or,
TEST
Related
I've read most of the online resources for building a simple "Hello World" app using Java and Struts 2. I understand the simple stuff. My problem is that I'm trying to expand that learning and build a large scale app, and I just don't see how to connect the dots.
Scenario:
I've got three views to begin with: Home.jsp, MyAccount.jsp, Contact.jsp. Each has the following HTML:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="js/common.js"></script>
...
</head>
<body>
<!-- If logged in, says "hello <s:property name="username">"
Else displays link to .show() #loginPane -->
<div id="accountHeader">...</div>
<!-- Displays <s:textfield> tags and <s:submit> tag to accept username and password -->
<div id="loginPane" style="display: none">...</div>
<header>...</header>
<nav>...</nav>
<!-- Displays view-specific content that includes Struts 2 tags -->
<div id="content">...</div>
<footer>...</footer>
</body>
</html>
So, obviously there is a lot of code common to each view (anything not in #content div).
How do I architect these views for code reuse?
What I've tried:
Placing common code in common.js and using jQuery .html() calls to populate <div>s. [Doesn't work because jQuery cannot generate code with <s:> tags.]
Using only one .jsp view file and placing view-specific code in common.js to be generated with jQuery .html() calls. [Doesn't work for the same reason -- jQuery cannot generate code with <s:> tags.]
Placing all view components in .jspf files and loading each with jQuery .load() calls from common.js. [Doesn't work -- I'm guessing the .jspf files need the Struts 2 <%taglib ...%> included in each, but jQuery .load() treats the <%taglib ...%> as text to be displayed in the <div>... and also fails to properly generate the <s:> tags.]
What is the proper way to do this? How do I architect my view(s) for code reuse?
My apologies if this isn't the proper forum to ask for architecture help, but I'm really struggling here... Perhaps point me to a more appropriate forum or an online tutorial that addresses this type of architecture?
Thanks in advance!
I've used several methods to accomplish this type of re-use of code including Tiles and tooling around with Sitemesh and other template frameworks. What I've found is that, much as Steven Benitez, in the end I preferred to use JSP taglibs, native Struts2 taglibs, and JSTL to essentially build out my own templating routines. The main reason I prefer this is that there tends to be less overhead and it's been a lot easier to maintain and extend in the long run.
Generally What I do is define my base template, index.jsp for example, and then in each independent Struts controller class I will define what page fragment is used. I try to split my controllers up in such a way that each page or function is handled by a single controller and I implement the Preparable interface. This way I can set a parameter for the page to reference. Sometimes I set it as a variable in the controller class, sometimes a sessions variable depending on what type of stating I need for the application.
Once I have a variable with the page to reference, I can just use a JSTL import or Struts include tag to load the page fragment.
The controller class would look something like this:
#Results({
#Result(name = "success", location = "/WEB-INF/content/index.jsp")
})
public class IndexController extends RestActionSupport implements Preparable{
private String page;
private String pageTitle;
#Override
public void prepare() throws Exception {
page = "home";
pageTitle= "My Home Page";
}
...
}
And then the JSP would look something like this:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title> ${pageTitle}</title>
</head>
<body>
<c:import url="${page}.jsp" />
</body>
</html>
EDIT: Fragment page example:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="s" uri="/struts-tags"%>
<div>
<h1>Welcome Home!</h1>
</div>
<script type='text/javascript'>
$(document).ready(function() {
// page specific scripting if needed
);
</script>
You can encapsulate common template code in JSP tag files, as explained in this answer or you can also use decorator frameworks such as Tiles or SiteMesh to do this.
Personally, I prefer JSP tag files. Do not attempt to write out HTML with jQuery or to put all of your code into a single JSP.
in my application I need to prepare a path for XML file inside JSP page. I'm doing someting like this:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<!DOCTYPE html>
<c:set var="abs_path" value='<%= getServletContext().getRealPath("").replace(" ", "%20").replace("\\", "/") %>' />
But there is a problem, I get the followind exception:
org.apache.jasper.JasperException: Unable to compile class for JSP:
An error occurred at line: 6 in the jsp file: /users.jsp
String literal is not properly closed by a double-quote
3: <%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
4: <%# taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
5: <!DOCTYPE html>
6: <c:set var="abs_path" value='<%= getServletContext().getRealPath("").replace(" ", "%20").replace("\\", "/") %>' />
Apparently it's about this part: .replace("\\", "/")
When I delete it, I don't get this exception.
What's that about? I will be very grateful for any clue.
EDIT:
I use this variable in the following way:
<c:import url="file:/${abs_path}/MyProject/xml/users.xml" var="inputDoc" charEncoding="UTF-8" />
<c:import url="xsl/users_list.xsl"
var="stylesheet" charEncoding="UTF-8" />
<x:transform
xml = "${inputDoc}"
xslt = "${stylesheet}">
</x:transform>
It is not about "\\" being a regular expression ... because that wouldn't result in a JSP compilation error. (And besides, the argument of String.replace(String) isn't interpreted as a regex.)
However, the compilation error does seem to be saying that you need double escaping, and I think that the reason is that the JSP syntax is "consuming" one level of escaping itself ... in this context.
This is from the JSP 2.1 spec:
JSP.1.6 Quoting and Escape Conventions
...
Quoting in Attributes
Quotation is done consistently regardless of whether the attribute value is a
literal or a request-time attribute expression. Quoting can be used in attribute
values regardless of whether they are delimited using single or double quotes. It is
only required as described below.
A ‘ is quoted as \’. This is required within a single quote-delimited attribute
value.
A “ is quoted as \”. This is required within a double quote-delimited attribute
value.
A \ is quoted as \\
Only when the EL is enabled for a page (see Section JSP.3.3.2, “Deactivating
EL Evaluation”), a literal $ can be quoted by \$. Similarly, a literal # can be
quoted by \#. This is not required but is useful for quoting EL expressions.
A %> is quoted as %\>
A <% is quoted as <\%
The entities ' and " are available to describe single and double
quotes.
Anyway, try writing the offending code fragment as replace("\\\\", "/").
How can I read/access a JSP variable from JavaScript?
alert("${variable}");
or
alert("<%=var%>");
or full example
<html>
<head>
<script language="javascript">
function access(){
<% String str="Hello World"; %>
var s="<%=str%>";
alert(s);
}
</script>
</head>
<body onload="access()">
</body>
</html>
Note: sanitize the input before rendering it, it may open whole lot of XSS possibilities
The cleanest way, as far as I know:
add your JSP variable to an HTML element's data-* attribute
then read this value via Javascript when required
My opinion regarding the current solutions on this SO page: reading "directly" JSP values using java scriplet inside actual javascript code is probably the most disgusting thing you could do. Makes me wanna puke. haha. Seriously, try to not do it.
The HTML part without JSP:
<body data-customvalueone="1st Interpreted Jsp Value" data-customvaluetwo="another Interpreted Jsp Value">
Here is your regular page main content
</body>
The HTML part when using JSP:
<body data-customvalueone="${beanName.attrName}" data-customvaluetwo="${beanName.scndAttrName}">
Here is your regular page main content
</body>
The javascript part (using jQuery for simplicity):
<script type="text/JavaScript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
<script type="text/javascript">
jQuery(function(){
var valuePassedFromJSP = $("body").attr("data-customvalueone");
var anotherValuePassedFromJSP = $("body").attr("data-customvaluetwo");
alert(valuePassedFromJSP + " and " + anotherValuePassedFromJSP + " are the values passed from your JSP page");
});
</script>
And here is the jsFiddle to see this in action http://jsfiddle.net/6wEYw/2/
Resources:
HTML 5 data-* attribute: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes
Include javascript into html file Include JavaScript file in HTML won't work as <script .... />
CSS selectors (also usable when selecting via jQuery) https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors
Get an HTML element attribute via jQuery http://api.jquery.com/attr/
Assuming you are talking about JavaScript in an HTML document.
You can't do this directly since, as far as the JSP is concerned, it is outputting text, and as far as the page is concerned, it is just getting an HTML document.
You have to generate JavaScript code to instantiate the variable, taking care to escape any characters with special meaning in JS. If you just dump the data (as proposed by some other answers) you will find it falling over when the data contains new lines, quote characters and so on.
The simplest way to do this is to use a JSON library (there are a bunch listed at the bottom of http://json.org/ ) and then have the JSP output:
<script type="text/javascript">
var myObject = <%= the string output by the JSON library %>;
</script>
This will give you an object that you can access like:
myObject.someProperty
in the JS.
<% String s="Hi"; %>
var v ="<%=s%>";
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
<title>JSP Page</title>
<script>
$(document).ready(function(){
<% String name = "phuongmychi.github.io" ;%> // jsp vari
var name = "<%=name %>" // call var to js
$("#id").html(name); //output to html
});
</script>
</head>
<body>
<h1 id='id'>!</h1>
</body>
I know this is an older post, but I have a cleaner solution that I think will solve the XSS issues and keep it simple:
<script>
let myJSVariable = <%= "`" + myJavaVariable.replace("`", "\\`") + "`" %>;
</script>
This makes use of the JS template string's escape functionality and prevents the string from being executed by escaping any backticks contained within the value in Java.
You could easily abstract this out to a utility method for re-use:
public static String escapeStringToJS(String value) {
if (value == null) return "``";
return "`" + value.replace("`", "\\`") + "`";
}
and then in the JSP JS block:
<script>
let myJSVariable = <%= Util.escapeStringToJS(myJavaVariable) %>;
</script>
The result:
<script>
let myJSVariable = `~\`!##$%^&*()-_=+'"|]{[?/>.,<:;`;
</script>
Note: This doesn't take separation of concerns into consideration, but if you're just looking for a simple and quick solution, this may work.
Also, if you can think of any risks to this approach, please let me know.
I am trying to figure out how to most effectively reuse JSP code.
I love the way Rails/erb works in that way ... with yield, layout, content_for
Example:
main_layout.erb.html
<html>
<head><%= yield :head %></head>
<body><%= yield %></body>
</html>
use
<% content_for :head do %>
<title>A simple page</title>
<% end %>
<p>Hello, Rails!</p>
in controller
layout "main_layout"
What is the closest I can get to this with JSP (without using extra frameworks)? I know about JSP include but that's not really the same as yield.
Any suggestions?
Thanks
I'm not familiar with what yield and content_for provide, but JSP tag files allow you a more robust way to template pages than JSP includes.
Example:
layout.tag
<%# tag body-content="scriptless" %>
<%# attribute name="pageTitle" required="true" type="java.lang.String" %>
<html>
<head>
<title>${pageTitle}</title>
</head>
<body>
<jsp:doBody/>
</body>
</html>
An individual JSP
<%# taglib prefix="z" tagdir="/WEB-INF/tags" %>
<z:layout pageTitle="A simple page">
<p>Hello, JSP!</p>
</z:layout>
Just place your layout.tag in the /WEB-INF/tags directory. You can use any available prefix you want, I just used "z" for the example.
While you mentioned wanting no frameworks on top of stock jsp, the Layout functionality of the Stripes Framework does pretty much exactly what you're asking for.
i have the following JSP:
<%# page contentType="text/html" pageEncoding="UTF-8"%>
<%# taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%# page isELIgnored="false"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><c:out value="${it.title}"/></title>
</head>
<body>
<c:forEach var="speaker" items="${it.speakers}" varStatus="stat">
<ul>
<li><c:out value="${speaker.person.firstName}" /> <c:out value="${speaker.person.lastName}" />, <c:out value="${speaker.person.address.city.zip}" /> <c:out value="${speaker.person.address.city.name}" /></li>
</ul>
</c:forEach>
</body>
</html>
Eclipse warns me about every instance of EL Expressions in my code:
Warning [line 10]: "value" does not support runtime expressions
Warning [line 13]: "items" does not support runtime expressions
...
this is however not true, EL gets evaluated correctly by the server.
Can anyone hint me in the right direction why eclipse is warning me about those EL expressions?
Your taglib directive imports a JSTL 1.0 taglib. It should be JSTL 1.1 instead (note the difference in URI):
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Possible solution (found here):
Twin Libraries
The JSTL tag libraries come in two
versions which differ only in the way
they support the use of runtime
expressions for attribute values.
In the JSTL-RT tag library,
expressions are specified in the
page's scripting language. This is
exactly how things currently work in
current tag libraries.
In the JSTL-EL tag library,
expressions are specified in the JSTL
expression language. An expression is
a String literal in the syntax of the
EL.
When using the EL tag library you
cannot pass a scripting language
expression for the value of an
attribute. This rule makes it possible
to validate the syntax of an
expression at translation time.
So maybe your eclipse and the server use different tag libraries.
try this:
change this:
<%#taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
to yes:
<%#taglib prefix="c" uri="http://java.sun.com/jstl/core_rt"%>
hope it works for you. I got this from www.csdn.net.