Issue
Say I have class Person:
package com.example;
public class Person {
private String name;
public String getName() {
return name;
}
public Person(String name) {
this.name = name;
}
public Person() {
}
}
And I use Servlet called MyServlet
to create Person object inside request's scope as attribute:
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Person p1 = new Person("Evan");
req.setAttribute("person", p1);
RequestDispatcher view = req.getRequestDispatcher("/result.jsp");
view.forward(req, resp);
}
}
Finally, JSP gets forwarded request and tries to print attribute. Notice how I purposely set scope="application"
and not scope="request"
as opposed to where attribute is located:
<!DOCTYPE html>
<html><body>
<jsp:useBean id="person" class="com.example.Person" scope="application"/>
Welcome <jsp:getProperty name="person" property="name"/>
</body></html>
I expected that JSP wouldn't find attribute as I explicitly told it to "search" for attributes located in application's scope and my attribute is located at request's scope. To my surprise, I get printed message Hello Evan
, meaning it somehow found it. Can someone explain me how?
I was also reading Head First Servlets and JSP, where I came across this (page 350). This picture (line 3) shows how it searches for attribute at REQUEST_SCOPE:
So can someone really help me figure out how did it find my attribute when it is searching for "person" just inside request's scope?
Solution
The documentation of <jsp:getProperty>
says:
The value of the
name
attribute injsp:setProperty
andjsp:getProperty
will refer to an object that is obtained from thepageContext
object through itsfindAttribute
method.
The javadoc of findAttribute(String name)
says:
Searches for the named attribute in page, request, session (if valid), and application scope(s) in order and returns the value associated or null.
Your <jsp:useBean>
likely created a new instance using the default constructor, and assigned it to the application scope, but <jsp:getProperty>
retrieved the value from the instance found a request scope, because it looked there first.
I'd recommend not using <jsp:getProperty>
, and instead just use EL.
With EL you would write ${person.name}
. To force a specific scope, you can prefix with:
pageScope.
requestScope.
sessionScope.
applicationScope.
E.g. ${applicationScope.person.name}
should be null
, since the application-scope instance was created with the default constructor.
Note: When writing text into an HTML document, and the text originated from a user, you should always escape it. Use <c:out value="${person.name}"/>
to do that, after correctly adding the JavaServer Pages Standard Tag Library (JSTL) to your project.
Answered By - Andreas
Answer Checked By - Mary Flores (JavaFixing Volunteer)