Must beans be part of a package to be found?

I have bean class named User. It’s not in a named package so I try to use this bean in a JSP page like this:

   <jsp:useBean id="user" class="User" />

This doesn’t work. I get a message about class User not being found. Just to test, I replaced my class name with “java.util.Date”, and then the page was accepted.

Do I have to put the class in a package?

Answer:
JDK 1.4 update: In Sun’s JDK 1.4 compiler, you can no longer import any type from the unnamed package into a class in a named package. In other words, your beans really must be part of a package. For details, see Sun’s Bug Parade. The rest of this answer is valid for previous versions of Sun JDKs and possibly for other compilers such as Jikes.The reason the JSP container can not find your bean when it’s not part of a package has to do with how Java in general resolves references to classes references through their short name. I describe this in an article at the O’Reilly site:

http://java.oreilly.com/news/jsptips_1100.html

6. Using Packages for Bean Classes

When you develop a bean to be used in a JSP page, I recommend that you make it part of a named package. A Java class that does not use a package statement ends up in the so-called unnamed package. The servlet class generated from the JSP page is, however, typically assigned to a named package. If you try to refer to a class in the unnamed package from a class in a named package, Java cannot find the class unless you use an import statement to import it. In a JSP page that means you must use both a page directive to import the class, and the <jsp:useBean> action to make it available:

   <%@ page import="UserInfoBean" %>
   <jsp:useBean id="userInfo" class="UserInfoBean" />

If the bean is part of a named packed, the action is all you need:

   <jsp:useBean id="userInfo"
     class="com.mycompany.UserInfoBean" />

There are other tips in this article that you may find useful, so please read it when you get a chance.

Why are my bean properties not recognized by the JSP container?

I have created a simple bean that looks like this:

package com.mycomp;
public class TestBean {
  private String firstName;
  private String lastName;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String v) {
    firstName = v;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String v) {
    lastName = v;
  }
}

I have compiled it and placed the class file in the WEB-INF/classes/com/mycomp directory for the application, as described in the book.

Still, when I use a <jsp:setProperty> or <jsp:getProperty> action and specify the property names FirstName or LastName, I get a compilation error for the page like this:

Error: 500 Location: /test/jsp/test.jsp 
Internal Servlet Error: org.apache.jasper.JasperException: 
Cannot find any information on property 'FirstName' 
  in a bean of type 'com.mycomp.TestBean'.

What’s going on here?

Answer:
Java is a case-sensitive language, and all bean property names are required to start with a lowercase letter. So the access methods in your bean:

getFirstName()/setFirstName()
getLastName()/setLastName()

correspond to properties named “firstName” and “lastName”. The property name is the method name minus the get/set prefix, with the first character changed from upper to lower case.

That’s why the container can’t find a property named “FirstName”, since it starts with an uppercase “F” instead of a lowercase “f”.

This naming rule is followed in all examples in the book, but it’s not explicitely described anywhere. I’ll put it on my list of things to be improved in the next edition of the book.

Can I define default values in the TLD?

Is it possible to specify a default value for an attribute via the Tag Library Descriptor (TLD)?Some attributes are optional and I need a flexible way to define the value to use in case the page author doesn’t specify a value.
Answer:
You can’t set defaults via the TLD. If you can live with a hard coded default, just make the attribute optional and use a default value defined in the tag handler class if it’s not set by the page author.

If you need to be able to use different default values per application, I suggest you use a servlet context init parameter, defined in the web.xml file, and read it in the tag handler.

Example web.xml:

<web-app>
  ...
  <context-param>
    <param-name>
      com.mycompany.taglib.foo
    </param-name>
    <param-value>
      bar
    </param-value>
  </context-param>
  ...
</web-app>

Example tag handler class:

...
String optAttribute = getOptionalAttribute();
if (optAttribute == null) {
  ServletContext sc = pageContext.getServletContext();
  optAttribute = sc.getInitParameter("com.mycompany.taglib.foo");
}
...

I recommend that you use a parameter name that is guaranteed to be unique by following the naming convention used in this example (“com.mycompany.taglib.foo”) if you use this approach, so that you avoid possible name clashes with other tag libraries that may be used in the same application.

If you have many default values you need to define, you may consider using a special servlet (marked as “load-at-startup”) to initialize all defaults and use servlet init parameters instead of context init parameters. The servlet can then set context attributes for all default values, and the tag handlers can retrieve them exactly as above. One advantage with this approach is that the servlet can verify that all default values have been set to okay values when the application starts, so you don’t have to do that in all tag handlers. It also allows you to use short init param value names without risking name clashes with other parts of the application (you should still use the unique names for the context attributes though).

Another benefit of using a servlet to initialize the tag library like this is that it can also create other resources used by multiple tag handlers. In the book, I describe in detail an example of a servlet that makes a JDBC connection pool available to a set of tag handlers.

When should I use a bean vs. a custom action?

In a complex JSP/Servlet application, would you use both JavaBeans and custom actions or one or the other? It seems like their functionality overlaps quite a bit.
Answer:
Yes, it does and there’s no clear cut answer for when one component type is the “right” choice. Often you end up using both types.I touch on this in the book in a couple of places. In Chapter 8, I say:

“As is often the case in software development, it’s hard to say exactly whether a bean or a custom action is the preferred component type. My rule of thumb is that a bean is a great carrier of information, and a custom action is great for processing information. Custom actions can use beans as input and output. For instance, an action can be used to save the properties of a bean in a database, or get information from a database and make it available to the page as a bean.”

An example of what I mean here is a bean with customer information properties and custom actions that process that information. You can use a <jsp:useBean> action to capture the input from a form, and custom actions to validate the captured data and to store it in a database:

<jsp:useBean id="custInfo" class="com.mycompany.CustomerInfoBean">
  <jsp:setProperty name="custInfo" property="*" />
</jsp:useBean>

<mytags:validateCustomerInfo name="custInfo"
  forwardOnInvalid="input.jsp"
/>
<mytags:storeCustomerInfo name="custInfo"
  nextPage="confirm.jsp"
/>

In Chapter 16 I say:

“Custom actions know about their environment. They automatically get access to all information about the request, the response, and all the variables in the JSP scopes. Another common use for a custom action is therefore as an HTTP-specific adapter to a bean. JavaBeans components are frequently used in a JSP application, and a bean is easier to reuse if it doesn’t know about the environment where it’s used.”

Hence, a bean that does something (such as the validation and storing above) can be wrapped in a custom action for use in a JSP page, and at the same time be used as is in a servlet or some other Java class. The counter bean and custom actions in Chapter 8 are examples of that. Instead of a bean, a custom action can of course wrap a regular utility class, such as the cookie and string utility classes used in the custom action examples in Chapter 16.

How can I set a property value of a different type than String?

I have bean with properties that are of other types than String. How can I set these properties using <jsp:setProperty>? How about a non-String attribute value for a custom action?
Answer:
If you use a literal string as the attribute value, such as

<jsp:setProperty name="foo" property="bar" value="value1" />

the JSP container looks at the type of the corresponding property in the bean class to see if the value needs to be converted. If the property is of type boolean, Boolean, byte, Byte, char, Character, double, Double, int, Integer, float, Float, long or Long, it will try to convert the string value to the correct type for the property. If the property is a String, the value is of course used as is. If it’s something else, you get a translation-time error.

If you need to set a property that is not one of the types listed above, for instance a java.util.Date, you must to use a request-time attribute value in JSP 1.1, such as

<jsp:setProperty name="foo" property="bar"
  value="<%= new java.util.Date() %>" />

When you use a request-time attribute value, the JSP container does not attempt to do any type conversion. In other words, the type of the expression must match the type of the corresponding bean property. In JSP 1.2, it’s possible to associate a so called “JavaBeans property editor” with the bean to convert string values to complex types like Date. I describe this approach in the second edition of the book.

The bean conversion rules apply to attribute values in custom actions: literal String values are converted to the type of the corresponding property in the tag handler class if it’s one of the types listed above, and for other types you can use a request-time attribute value, or in JSP 1.2, create a property editor that knows how to convert strings to complex data types.