Search code examples
javajspservletsattributesjavabeans

How does JavaBean search for attribute? Does it look at just name or scope as well?


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: enter image description here

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 in jsp:setProperty and jsp:getProperty will refer to an object that is obtained from the pageContext object through its findAttribute 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.