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:
based on an EL expression that uses the elements from the list but not the actual properties from those elements
however…
when we changed the page to actually display properties of the book objects found in the list:
We ran into a fairly horrible and as I said unexpected exception:
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.
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.
Resources
Download JSF 2.0 project (JDeveloper 11gR2) for this article ManagedBeanAndPrivateInnerClass.
Thanks.. this helped