views:

726

answers:

1

Hey,

I want to print out the contents of a backing bean in an auto-generated way. So all the contents appear on a JSP. Is this possible anyhow?

Thanks in advance, Daniel

A: 

One way to do this would be using the JavaBean API and a custom tag function.

WEB-INF/tld/beans.tld:

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
    <description>Bean inspector.</description>
    <display-name>Bean inspector utils</display-name>
    <tlib-version>1.2</tlib-version>
    <short-name>beans</short-name>
    <uri>http://acme.demo&lt;/uri&gt;
    <function>
     <name>inspect</name>
     <function-class>props.Inspector</function-class>
     <function-signature>
      java.util.List inspect(java.lang.Object)
     </function-signature>
    </function>
</taglib>

Implementation:

public class Inspector {

  public static List<Map.Entry<String, Object>> inspect(
      Object bean) {
    Map<String, Object> props = new LinkedHashMap<String, Object>();

    try {
      BeanInfo info = Introspector.getBeanInfo(bean
          .getClass(), Object.class);
      for (PropertyDescriptor propertyDesc : info
          .getPropertyDescriptors()) {
        String name = propertyDesc.getDisplayName();
        Method reader = propertyDesc.getReadMethod();
        Object value = reader.invoke(bean);
        props.put(name, value == null ? "" : value);
      }
    } catch (IntrospectionException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }

    return new ArrayList<Map.Entry<String, Object>>(props
        .entrySet());
  }
}

This tag library is then imported in the JSP header:

<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core" xmlns:beans="http://acme.demo"&gt;

Sample dataTable using the function:

<h:dataTable border="1" value="#{beans:inspect(demoPropsBean)}" var="entry">
 <h:column id="column1">
  <f:facet name="header">
   <h:outputText value="property" />
  </f:facet>
  <h:outputText value="#{entry.key}" />
 </h:column>
 <h:column id="column2">
  <f:facet name="header">
   <h:outputText value="value" />
  </f:facet>
  <h:outputText value="#{entry.value}" />
 </h:column>
</h:dataTable>

See the JavaBean spec for info on how to provide localized property names, etc.

McDowell
Thanks for the answer!I've tried this out, and i get the error:javax.servlet.ServletException: Problems calling function 'beans:inspect' with a root cause of java.lang.NullPointerException.Probably i'm passing a wrong parameter.<jsp:useBean id="Calculation" class="classes.ECCalculation" scope="session"/>..<h:dataTable border="1" value="#{beans:inspect(Calculation)}" var="entry">Is this wrong?
wheelie
I've never used jsp:useBean with JSF, so I am not sure what the problem is. It would be better to define the managed bean in your WEB-INF/faces-config.xml file: http://java.sun.com/javaee/5/docs/tutorial/doc/bnapl.html#bnaqc
McDowell
Same error without the useBean:\Btw it's defined in faces-config too, the reason why i'm using jsp:useBean is that so I can pass it as parameter like this: <% method(myBean); %>, because this way the bean is "visible" from jsp's java code. I'm confused how else could i do that.Thanks, you are really helpful,Daniel
wheelie
It isn't possible for me to narrow down what's going wrong without seeing the stack trace for the NullPointerException.It sounds like you are mixing a great many JSP development techniques - which may make your app design fragile. At one end of the scale is the JSF model-view-presenter design that keeps code out of the view and at the other end is the old in-line-code-snippets <% %> of the original JSP API. <jsp:useBean/> came somewhere in the middle.
McDowell
stack trace: http://rafb.net/p/FpwJfo40.html
wheelie
Looks like Calculation in value="#{beans:inspect(Calculation)}" resolves to null, which is odd if it is specified as a managed bean in faces-config - that was how I tested the above code. I suspect a typo somewhere, but can't pin down where. ("classes" is an odd name for a package, but I would expect a ClassNotFoundException if that was it.)
McDowell