0

I was making a pretty basic web app with servlet and jsp and I had the following setup:

public class DataManager {
    //some method implementations omitted since they are not important
    public DataManager(){}

    public class Author{
        public int id;
        public String name;
        public String born;
        public String died;
    }

    public Author getAuthor(int authorId){} 
    public ArrayList<Author> getAuthors(){}
}

public class AuthorsServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        ServletContext context = getServletContext();
        DataManager dm = (DataManager) context.getAttribute("datamanager");
        ArrayList<DataManager.Author> authors = dm.getAuthors();

        request.setAttribute("authors", authors);
        request.getRequestDispatcher("/authors.jsp").forward(request, response);

    }
}

In my jsp file I had:

<c:forEach var="author" items="${authors}">
    <tr>
        <td>${author.id}</td>
        <td><a href="author.jsp">${author.name}</a></td>
        <td>${author.born}</td>
        <td>${author.died}</td>
    </tr>
</c:forEach>

However I kept getting an error that says Property 'id' not found on type db.DataManager$Author until I put in getters in the inner Author class of my DataManager class:

public class Author{
    public int id;
    public String name;
    public String born;
    public String died;
    public int getId(){ return id; }
    public String getName(){ return name;}
    public String getBorn(){return born; }
    public String getDied(){ return died;}
}

I have two (kind of basic) questions:

  1. Why do I have to add getters to access a public inner class's variables?

  2. Even after I put in the getters, I didn't directly called them (i.e. author.id instead of author.getId()) is there a naming convention where the compiler follows, so I have to define getFoo to get the value of a foo variable?

Liumx31
  • 1,190
  • 1
  • 16
  • 33
  • JSP is following the java bean patterns please see [https://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html](https://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html) [http://www.java-samples.com/showtutorial.php?tutorialid=552](http://www.java-samples.com/showtutorial.php?tutorialid=552) – daotan Aug 25 '16 at 08:43

3 Answers3

1

The runtime environment calls author.getId() automatically in order to evaluate${author.id}. This is why you need to define the getters (explicitly, because Java does not define them implicitly) even though the fields are public.

There is a naming convention: if the name of the filed is fooFieldExample, the name of the getter should be getFooFieldExample (notice the big F of foo)

AhmadWabbi
  • 2,253
  • 1
  • 20
  • 35
  • 1
    It's not the compiler. That happens at runtime, using reflection. – JB Nizet Aug 25 '16 at 08:38
  • @JBNizet how does this use reflection? Sorry I'm only generally familiar with the concept. – Liumx31 Aug 25 '16 at 08:42
  • At runtime, when the JSP is executed, the EL expression author.id is interpreted, and the server thus finds an attribute named "author", which could be anything, and then looks for a public instance method named "getId()" in this object, and calls it. Whether the getter returns a field, and whether the field is named "id", is completely irrelevant. The JSP EL works with JavaBean properties, not with fields. – JB Nizet Aug 25 '16 at 08:56
0

Why do I have to add getters to access a public inner class's variables?

Because that is what jsp specification expects it to be, $author.id statement converts author.getId() where id should have a public accessor method getId();

Even after I put in the getters, I didn't directly called them (i.e. author.id instead of author.getId()) is there a naming convention where the compiler follows, so I have to define getFoo to get the value of a foo variable?

Yes, it is naming convention. Remember that JSPs are meant for design purpose and developed by page designers.JSps are not designed by java programmers. So $author.id is more convenient to non-programmers.

Expression $author.id is an Expression Language syntax which is used to access variables those are available in JSP pages. Expression Language $author.id is translated into author.getId();

Prasad Kharkar
  • 13,410
  • 5
  • 37
  • 56
  • So does this also apply to non-JSP situations? Say if I have something like `ArrayList authors = dm.getAuthors();` and `then I do `authors.get(1).name` would this work without the getters in `Author` class, in a scope outside of `DataManager`? – Liumx31 Aug 25 '16 at 08:40
  • @Liumx31 no. Accessing a public field in Java code accesses the public field. It uses the getter is you call the getter. But, in general, fields should never be public. – JB Nizet Aug 25 '16 at 08:57
  • @PrasadKharkar what you're saying is completely wrong. – JB Nizet Aug 25 '16 at 08:58
  • @JBNizet, could you please guide me? – Prasad Kharkar Aug 25 '16 at 09:00
  • Well, your answer says that id must be publicly accessible, and it's wrong. The getId() getter must be, but not the field. And then in your last comment, you say that public getters are required to access public fields in Java, which is wrong too. – JB Nizet Aug 25 '16 at 09:02
  • @JBNizet I really made mistakes in typing the answer :) It wasn't what I meant. I've corrected now. Thanks for pointing out – Prasad Kharkar Aug 25 '16 at 09:08
0

Declaring a class fields as private and define Getters and setters for them are usual java best practices (almost imperative). They are so usual in Java that most frameworks and even standards rely on them, for example: JSP EL langauage transforms this author.id in author.getId().

You should declare your fields private and use getters and setters.

Ricardo Vila
  • 1,626
  • 1
  • 18
  • 34