简体   繁体   中英

JSP,EL property not found

I am creating a simple guest book in JSP in order to learn this technology. Currently I have two classes: guestbook/GuestBook.class and guestbook/Entry.class (I haven't finished the app yet, so I have only these classes) which are added into WEB-INF/libs/ and they're included properly. In my file index.jsp I am using guestbook.GuestBook class; its method returns Vector. When I iterate over entries and I'd like to print an author of the entry, I can see:

javax.el.PropertyNotFoundException: Property 'author' not found on type guestbook.Entry

I must add that Entry class is public and author attribute is declared in such way:

public String author;

So it is public, too. This is my code when I iterate over the entries:

<c:forEach items="${entries}" varStatus="i">
  <c:set var="entry" value="${entries[i.index]}" />
  <li><c:out value="${entry.author}" /></li>
</c:forEach>

and

entry.class.name

returns guestbook.Entry

The classes are in package guestbook (as you can guess), entries vector is passed to pageContext.

I do not know what is wrong with my way of doing it. Can anybody help me please with that? (Thanks in advance!)

JSP EL will not recognise public fields in your classes, it only works with getter methods (which is good practice anyway - never expose your classes' state as public fields like this).

So use

private String author;

public String getAuthor() {
   return author;
}

instead of

public String author;

As a side note, your JSTL is overly complicated, it can be simplified to:

<c:forEach items="${entries}" var="entry">
  <li><c:out value="${entry.author}" /></li>
</c:forEach>

or even

<c:forEach items="${entries}" var="entry">
  <li>${entry.author}</li>
</c:forEach>

although the latter form will not XML-escape the author name, so isn't advised.

Lastly, the Vector class is obsolete, you should use ArrayList instead.

You can also modify the EL-resolver to access public fields if a getter is not found. To do this, you first need to create your special ELResolver:

public class PublicFieldSupportingELResolver extends ELResolver {

    @Override
    public Class<?> getCommonPropertyType(ELContext context, Object base) {
        return null;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
        return null;
    }

    @Override
    public Class<?> getType(ELContext context, Object base, Object property) {
        return null;
    }

    @Override
    public Object getValue(ELContext context, Object base, Object property) {
        try {
            return context.getELResolver().getValue(
                    context, base, property);
        } catch(RuntimeException ex) {
            if(property instanceof String && base != null) {
                try {
                    Field field = base.getClass().getDeclaredField((String) property);
                    Object value = field.get(base);
                    context.setPropertyResolved(true);
                    return value;
                } catch (Exception e) {
                    throw new PropertyNotFoundException(e);
                }
            } else {
                throw ex;
            }
        }
    }

    @Override
    public boolean isReadOnly(ELContext context, Object base, Object property) {
        return false;
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object value) {
    }
}

Then you need a class to help you configure it:

public class PublicFieldSupportingELResolverConfigurer implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        JspFactory.getDefaultFactory()
                .getJspApplicationContext(event.getServletContext())
                .addELResolver(new PublicFieldSupportingELResolver());
    }

    public void contextDestroyed(ServletContextEvent event) {
    }
}

At last you need to run this configurer-class when the servlet starts up. Do this by adding this class as a servlet listener in your web.xml:

  <listener>
    <listener-class>your.package.PublicFieldSupportingELResolverConfigurer</listener-class>
  </listener>

Now you can refer to public fields in your JSPs.

I had a problem in Build Path. javax.servlet.jsp.jstl-1.2.1.jar was deleted but not removed from Build Path. After removing it from Build Path Property 'xxx' not found issue disappeared.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM