How to run into and resolve EL PropertyNotFound exception and propertyNotReadable in JSF with private inner class

The other day on one of the projects I am involved with, we ran into an unexpected exception, from an innocent looking EL expression:

javax.el.PropertyNotFoundException: … value=”Book #{book.title}”: Missing Resource in EL implementation: ???propertyNotReadable???

We did nothing very special, or so we thought: simple JSF page that contains an iterator component that retrieves a list of objects from a managed bean and stamps output text components for every object.

The initial page rendered fine:

Image

based on an EL expression that uses the elements from the list but not the actual properties from those elements

Image

however…

when we changed the page to actually display properties of the book objects found in the list:

Image

We ran into a fairly horrible and as I said unexpected exception:

Image

It seems that even though the list of books can be found (#{librarian.library} does not caase any problems), the book elements themselves are not accessible.

javax.el.PropertyNotFoundException: … value=”Book #{book.title}”: Missing Resource in EL implementation: ???propertyNotReadable???

And that gave the clue that explained the issue to us. The librarian bean was defined like this:

package nl.amis.jsf.view;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import nl.amis.jsf.PublicationI;

@ManagedBean (name="librarian")
@SessionScoped
public class Librarian {

    private List<Book>  library = new ArrayList<Book>();

    public Librarian() {
        library.add(new Book("The Help"," Kathryn Stockett",2010,"Penguin Group"));
        library.add(new Book("Hit List","Laurell K. Hamilton",2010,"Penguin Group"));
        library.add(new Book("WATER FOR ELEPHANTS","Sara Gruen",2009,"Algonquin"));
        library.add(new Book("Oracle SOA Suite 11g Handbook","Lucas Jellema",2010,"McGrawHill"));
        library.add(new Book("STATE OF WONDER","Ann Patchett",2011,"HarperCollins."));

    }

    public void setLibrary(List<Librarian.Book> library) {
        this.library = library;
    }

    public List<Librarian.Book> getLibrary() {
        return library;
    }

    private static class Book{
        private String title;
        private String author;
        private Integer    yearOfPublication;
        private String publisher;

        public Book(String title, String author, int yearOfPublication, String publisher) {
            super();
            this.title = title;
            this.author = author;
            this.yearOfPublication = yearOfPublication;
            this.publisher = publisher;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getTitle() {
            return title;
        }

        public void setAuthor(String author) {
            this.author = author;
        }

        public String getAuthor() {
            return author;
        }

        public void setYearOfPublication(Integer yearOfPublication) {
            this.yearOfPublication = yearOfPublication;
        }

        public Integer getYearOfPublication() {
            return yearOfPublication;
        }

        public void setPublisher(String publisher) {
            this.publisher = publisher;
        }

        public String getPublisher() {
            return publisher;
        }
    }
}

You can see that the Book class is a private inner class. This means apparently and not surprisingly that the EL resolution mechanism has no way of determining whether or not the book object it is inspecting while evaluating #{book.title} does indeed contain the title property. Whether it uses introspection or not – it simply cannot determine the class signature of the private inner class.

What did work – just to prove the point – was to create a public interface

package nl.amis.jsf;

public interface PublicationI {
    public String getTitle();
    public String getAuthor();
}

and have the private inner class implement that interface.

    private static class Book implements PublicationI{
        private String title;
        private String author;
...

That made the properties defined in the interface accessible to the EL resolution, even though it is still a private inner class implementing that interface.

Image

Of course if the page refers to a property on the book objects that has not been defined by a public interface, such as publisher or yearOfPublication, we are back to the originall exception.

Image

Resources

Download JSF 2.0 project (JDeveloper 11gR2) for this article ManagedBeanAndPrivateInnerClass.

Leave a Reply