I just started to use JSTL for my project, but sorry to say it's really confusing to me.
I originally used Number.java
package com.mycompany
public class Number {
private int total;
public static int add (int x, int y) {
return total;
}
And in showNumber.jsp i could just use
<%#page import= "com.mycompany.Number" %>
and inline use <%= Number.add(5,6) %>
How can I rewrite this part in JSTL?
Is that also possible to import the class Number.java?
I tried so many different things, e.g. <c:out value="${Number}.add(5,6)" />, but still cannot find a solution. Thanks.
Edited:
I use #Victor's approach, and it does work. In my case, I need to reuse other's variable from spring framework, say NumberTwo.java and totalTwo as private variable inside. And added "100" to this totalTwo.
For the src where i need to use it is <spring:param name="secondNumber" value ="${NumberTwo.totalTwo}" />.
However, intutively i used (int) pageContext.getAttribute("NumberTwo.totalTwo"), it always returned me null.
The other workaround is
first <c:set var="result" value="${NumberTwo.totalTwo}" />
then <% String result = (String) pageContext.getAttribute("result"); %>
and then <%= Number.add(result, 100) %>
Unfortunately it's not possible to arbitrarily call methods with JSTL, the function capabilities of JSTL are very limited: http://docs.oracle.com/javaee/5/tutorial/doc/bnalg.html . But it's still possible to use your Number class. Here the workaround:
<%#page import= "com.mycompany.Number" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
pageContext.setAttribute("addResult", Number.add(7, 8));
%>
<html>
<body>
JSP 1.x: Result is: <c:out value="${addResult}" /><br/>
JSP 2.x: Result is: ${addResult}
</body>
</html>
With pageContext.setAttribute() the method result is stored in the page context, and the JSTL tags can access values (attributes) stored in that context.
Note: the second output line "Result is: ${result}" works only with JSP 2 afaik.
You can use the 'usebean' tag as in the following example:
<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">
<!-- UseBean.jsp
Copyright (c) 2002 by Dr. Herong Yang
-->
<html><body>
<jsp:directive.page import="CacheBean"/>
<jsp:useBean id="b" class="CacheBean"/>
<jsp:setProperty name="b" property="text" value="Hello world!"/>
Property from my Bean:
<jsp:getProperty name="b" property="text"/>
<br/>
Info from my Bean:
<jsp:expression>b.getInfo()</jsp:expression>
</body></html>
</jsp:root>
Where:
/**
* CacheBean.java
* Copyright (c) 2002 by Dr. Herong Yang. All rights reserved.
*/
public class CacheBean {
private String text = "null";
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getInfo() {
return "My JavaBean - Version 1.00"
}
}
CREDIT TO: http://www.herongyang.com/jsp/usebean.html
Please look at EL functions in BalusC's answer at
Hidden features of JSP/Servlet
also
look at "Using Custom Methods in EL" at
http://www.roseindia.net/jstl/jstl-el.shtml
look at Functions at
http://docs.oracle.com/javaee/5/tutorial/doc/bnahq.html
Related
I have this class:
public class Orders{
private Integer id;
private String name;
//getters/setters
}
In controller I pass a List<Orders> to jsp:
#RequestMapping(value = "/orders")
public ModelAndView orders(){
List<Orders> orders = ...//get list from db
//print list in console
orders.forEach(e -> System.out.println(e.getId() + " - " + e.getName()));
//print -> 1 - name1 ; 2 - name2
return new ModelAndView("orders", "orders", orders);
}
In jsp use it like this:
${orders.size()}
<c:forEach items="${orders}" var="order">
<c:out value="${order.getId()}"></c:out>
</c:forEach>
In browser at inspect(html code) looks like this:
"2"
<c:foreach items="[com.web.entity.Orders#21e16dd6,
com.web.entity.Orders#52a33913]" var="order">
<c:out value=""></c:out>
</c:foreach>
I tested in controller by printing list in console and everything is right.
Why in jsp is not printed?
Could you please provide more details (controller code, html page tags ...).
Still I've some point to share with you :
Use always a toString method in your Entity/POJO.
Use order.id instead of order.getId()
Make sure you have JSTL core tag in the top of your HTML page :
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Try to have a simple c:out tag:
<c:out value="${order.id}"/>
I have lots of JSPs containing code which have statements which could be reused like this select statements, inputs, etc.
Here is a sample of a JSP
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
(needed includes)
<%
ArrayList<Student> studentList = (from database)
%>
<html>
<head>
<title>Students</title>
</head>
<body>
<form>
(other inputs)
...
<select class="combobox">
<%for (Student studentObj:studentList) { %>
<option value="<%=studentObj.getId()">
<%=studentObj.getLastName() %>, <%=studentObj.getFirstName() %>
</option>
<%} %>
</select>
...
(other inputs)
</form>
</body>
</html>
What I did do is make a function as follows. This allows me to be able to pass an object parameter and get html code back.
public static getStudentSelect(ArrayList<Student> studentList) {
String htmlCode = "<select class=\"combobox\">";
for (Student studentObj:studentList) {
htmlCode += "<option value=\"" + studentObj.getId() + "\">" +
studentObj.getLastName() + ", " + studentObj.getFirstName() +
"</option>";
}
htmlCode += "</select>"
return htmlCode;
}
Is there a better way of doing this? Because escaping quotes can get messy.
I can't send objects through jsp includes.
I was thinking of using Gagawa
Please don't use scriptlets in JSP. You should use tag files, JSTL and EL to make your own tag library. This way you can easily pass variables as parameters into the reusable components, unlike with JSP fragments and these are much simpler than writing custom tags, when you're dealing with simple logic like looping or creating a table.
Below is an example based on your sample JSP code in the question.
/WEB-INF/tags/student/select.tag:
<%# taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core” %>
<%# attribute name="studentList" required="true" type="java.util.List" %>
<select class="combobox">
<c:forEach var="student" items="${studentList}">
<option value="${student.id}">
<c:out value="${student.lastName}" />,
<c:out value="${student.firstName}" />
</option>
</c:forEach>
</select>
sample.jsp:
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%# taglib prefix=”student” tagdir=”/WEB-INF/tags/student” %>
<!DOCTYPE html>
<html>
<head>
<title>Students</title>
</head>
<body>
<form>
(other inputs)
...
<student:select studentList="${sessionScope.studentList}" />
...
(other inputs)
</form>
</body>
</html>
To avoid escaping issues.
Better try using plain javascript to create html like
var el = document.createElement('select');
el.className = "combobox";
for (Student studentObj:studentList) {
var optel = document.createElement('option');
optel.value = studentObj.getId();
optel.text = studentObj.getLastName() + ", " + studentObj.getFirstName();
el.append(optel);
}
return el;
I use Spring MVC & jsp.
It's my homeController. return "test String";
#RequestMapping(value="/",method = RequestMethod.GET)
public String home(Locale locale,Model model){
model.addAttribute("test","test String");
return "home"; }
home.jsp
<html><head>
<% String test = ${test} %>
</head>
<body>
${test} //it shows "test String"
<%=test%> //but it doesn't show anything. error.
</body></html>
how to use dollar sign in <% %> ?
el expression isn't allowed inside script-lets, you should be able to just use EL
You should use either scriptlets or jstl.
It could be better to do like this:
<html>
<body>
<c:out value="${test}"/>
</body>
</html>
So I have jsp one that loads some request params as a session which I access in my second jsp .
My jsp 1 code is :
<jsp:useBean id="Emails" scope="request" class="java.lang.String" />
<%
String email = Emails;
session.setAttribute( "allEmail",email);
%>
<p style="display:block" ><%= session.getAttribute( "allEmail" )%></p>
My jsp 2 code is :
<p style="display:block" ><%= session.getAttribute( "allEmail" )%></p>
Now I can see the <p> in the first jsp populated properly with the data but the paragraph in my second jsp just blank
when I change session.setAttribute( "allEmail",email); to something like session.setAttribute( "allEmail","hello world); I can see the correct value reflected in both paragraphs .
What am I doing wrong ?
the servlet that populates jsp1 has the following request dispatcher
RequestDispatcher dispatch = request.getRequestDispatcher("jsp1");
I think the issue is both the jsp's are initialised at the same time so the session in the second jsp has no value .
As per the above scenario. Since request will hold the session object for sure.
You can try this :-
<p style="display:block" >
<%(String)request.getSession().getAttribute("allEmails"); %>
</p>
What you want to pass here is a String into session scope.
1) You don't require a jsp useBean for this. You can directly set in session scope with scriptlet you currently have.
To use jsp useBean tag, the component class should be of type JavaBean. You are using String class which is immutable.
And so you cannot set any property for String to be used in useBean.
Unfortunately scriptlet error was not captured/not thrown (don't know) when you are assigning with
String email = Emails;
Why it was working when you are setting?
session.setAttribute( "allEmail","hello world");
This is as good as setting:
<%
String email = "hello world";
session.setAttribute( "allEmail",email);
%>
If you want to pass some String property along with other properties if required, define like:
public class YourBean implements java.io.Serializable
{
private String propertyName = null;
public String getPropertyName(){
return propertyName;
}
public void setPropertyName(String propertyName){
this.propertyName = propertyName;
}
}
and then set property as:
<jsp:useBean id="yourBean" class="package.YourBean" scope="bean scope">
<jsp:setProperty name="yourBean" property="propertyName" value="value"/>
...........
</jsp:useBean>
Is there any way to call toString() on an object with the EL and JSTL? (I need the String representation of an enum as index in a map in a JSP EL expression.) I hoped something like ${''+object} would work like in java, but EL isn't that nice, and there does not seem to be any function that does it.
Clarification: I have a variable somemap that maps Strings to Strings, and I have a variable someenum that is an enumeration. I'd like to do something like ${somemap[someenum.toString()]}. (Of course .toString() does not work, but what does?)
You just do it like this:
${object}
And it'll toString it for you.
edit: Your nested expression can be resolved like this:
<c:set var="myValue">${someenum}</c:set>
${somemap[myValue]}
The first line stringifies (using toString()) the ${someenum} expression and stores it in the myValue variable. The second line uses myValue to index the map.
Couple things you can do.
One, you can use c:set -
<c:set var="nowAString">${yourVar}</c:set>
Another thing you can do is create your own EL function, call it toString, and then call that in JSTL. EL functions are basically static methods hooked up with a taglib file. Straightforward to do.
Edit:
Really? Did you actually, you know, try it?
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%#taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>Hello World!</h1>
<%
pageContext.setAttribute("testDate", new java.util.Date());
%>
<c:set var="myVar">${testDate}</c:set>
testDate = ${testDate}<br/>
myVar = ${myVar}<br/>
testDate Class = ${testDate.class}<br/>
myVar Class = ${myVar.class}<br/>
</body>
</html>
And JSP 2.0 tagfile and JSTL functions are trivial.
I think in new versions of JSP api you can call methods, even with parameters!
I just tried ${statusColorMap[jobExecution.exitStatus.toString()]} and it works fine!
The answer of Will Hartung should work. Here's a copy'n'paste'n'runnable SSCCE:
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!doctype html>
<%!
enum MyEnum {
FOO, BAR
}
%>
<%
request.setAttribute("myEnum", MyEnum.FOO);
java.util.Map<String, String> map = new java.util.HashMap<String, String>();
map.put("FOO", "value of key FOO");
map.put("BAR", "value of key BAR");
request.setAttribute("map", map);
%>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<p>Map: ${map}
<p>Enum: ${myEnum}
<c:set var="myEnumAsString">${myEnum}</c:set>
<p>Map value: ${map[myEnumAsString]}
</body>
</html>
This yields:
Map: {BAR=value of key BAR, FOO=value of key FOO}
Enum: FOO
Map value: value of key FOO
(scriptlets are just for quick prototyping, don't use them in real!)
//In java
public class Foo {
// Define properties and get/set methods
private int prop1;
private String prop2;
public String toString() {
String jsonString = ...; /// Convert this object to JSON string
return jsonString;
}
}
As skaffman said, EL syntax ${obj} will call toString().
So, if a object foo in JSTL is an instance of Foo.
Then,
// test.jsp
<script>
var a = ${foo}; // ${foo} will be {"prop1": ooo, "prop2": "xxx"}
console.log(a.prop1);
console.log(a.prop2);
</script>
Example
If toString() will output JSON format string, for example, Foo's toString() outputs JSON format string. then:
// .java codes
Foo a = ...// a Foo object. => { 'prop1': ooo }
List<Foo> b = ... //< Array. => [ {'prop1': ooo}, {prop1: xxx} ]
// Pass object to JSTL by HttpServletRequest or ..
request.setAttribute('a', a);
request.setAttribute('b', b);
// .jsp codes
<span>${a.prop1}</span>
<script>
var aa = ${a}; // ${a} => { 'prop1': ooo }
var bb = ${b}; // ${b} => [ {'prop1': ooo}, {prop1: xxx} ]
console.log(aa.prop1);
console.log(bb[0].prop1);
</script>
ugly but simple enough
<someTag someValue="${yourObject}${''}" ... />
for example, someValue only accept strings (but declare as java.lang.Object), this way enforce it with string concatenation