PropertyNotFoundException in JSP Page

Java Beginner picture Java Beginner · Feb 16, 2013 · Viewed 20.3k times · Source

I have a Java bean class as Below

public class Users extends dbConnect
{
   private int UserId;  

   public int getUserId() 
   {
    return UserId;
   }

   public void setUserId(int userId) 
   {
     UserId = userId;
   }
}

I have a doGet Method in My Servlet which get the value in javabean class and shows in JSP page.The ListUsers method is going to return a list from database.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    {
        List<Users> arrUserList = new ArrayList<Users>();

        Users objUser = new Users();
        arrUserList   = objUser.listUsers();

        for(Users Userobj : arrUserList)
        {
            System.out.println(Userobj.getUserId());
        }

        request.setAttribute("arrUserDetails", arrUserList);

        RequestDispatcher rst = request.getRequestDispatcher("ListUsers.jsp");
        rst.forward(request, response);
    }

When I print The value of UserId in for loop above its displaying the UserId.But Its not getting displayed in my JSP Page.

<%@ page  import="com.acme.users.Users"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<c:forEach items="${arrUserDetails}" var="account">
<tr>
      <td>
         <c:out value="${account.UserId}" />
      </td>
    </tr>
</c:forEach>

Its Displaying javax.el.PropertyNotFoundException. I checked stack for the exception and made sure that the bean name and getters method are same.But its still showing the error.

The Message in console is as below

Feb 16, 2013 2:44:19 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
javax.el.PropertyNotFoundException: Property 'UserId' not found on type com.acme.users.Users
    at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:223)
    at javax.el.BeanELResolver$BeanProperties.access$400(BeanELResolver.java:200)
    at javax.el.BeanELResolver.property(BeanELResolver.java:311)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:85)
    at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:67)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
    at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:985)
    at org.apache.jsp.ListUsers_jsp._jspx_meth_c_005fout_005f0(ListUsers_jsp.java:170)
    at org.apache.jsp.ListUsers_jsp._jspx_meth_c_005fforEach_005f0(ListUsers_jsp.java:124)
    at org.apache.jsp.ListUsers_jsp._jspService(ListUsers_jsp.java:84)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:391)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
    at com.acme.users.ListUsers.doGet(ListUsers.java:36)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

Why does this happen?

Answer

Jon Skeet picture Jon Skeet · Feb 16, 2013

You're using UserId which is the name of the field (and which violates Java naming conventions, by the way - as does dbConnect as a class name).

The JSP wants to use properties - getters and setters. The method you're trying to get it to call is getUserId, but the property name (in JavaBeans terms) is just userId. Therefore if you change your code to:

 <c:out value="${account.userId}" />

it should work. You should also change your class to use a field called just userId, or even id (given that it's already a user - that part is implicit).

It would be worth reviewing JSP/JSTL/JavaBeans tutorials - you'll notice that they all use property names starting with a lower case letter, e.g. ${foo.age} to call the getAge() method.

From the documentation for PropertyDescriptor constructor (which is also present in the JavaBeans specification):

Constructs a PropertyDescriptor for a property that follows the standard Java convention by having getFoo and setFoo accessor methods. Thus if the argument name is "fred", it will assume that the writer method is "setFred" and the reader method is "getFred" (or "isFred" for a boolean property). Note that the property name should start with a lower case character, which will be capitalized in the method names.

(Emphasis mine.)

It's not clear whether there's any method name that would let ${account.UserId} work - if there isn't, then I'd argue that the error message could be a lot clearer. (Or it could just be a bit more forgiving.)

Additional points:

  • It's not clear why your class is called Users when it appears to represent a single user
  • It's not clear that it should extend a class which has anything to do with database connections - a user is not a database connection, after all. I suspect you should be trying harder to make each class only responsible for one concept.