Java Servlet Programming, 2nd Edition > 18. JavaServer Pages > 18.5 JSP and JavaBeans |
18.5 JSP and JavaBeansOne of the most interesting and powerful ways to use JavaServer Pages is in cooperation with JavaBeans components. JavaBeans are reusable Java classes whose methods and variables follow specific naming conventions to give them added abilities. They can be embedded directly in a JSP page using the <jsp:useBean> tag, or what JSP calls an action. A JavaBean component can perform a well-defined task (execute database queries, connect to a mail server, maintain information about the client, etc.) and make its resulting information available to the JSP page through simple accessor methods. For more information on JavaBeans, see http://java.sun.com/bean and the book Developing Java Beans by Robert Englander (O'Reilly). The difference between a JavaBeans component embedded in a JSP page and a normal third-party class used by the generated servlet is that the web server can give JavaBeans embedded in a page special treatment. For example, a server can automatically set a bean's properties (essentially instance variables) using the parameter values in the client's request. In other words, if the request includes a name parameter and the server detects through introspection (a technique in which the methods and variables of a Java class can be programmatically determined at runtime) that the bean has a name property and a setName(String name) method, the server can automatically call setName( ) with the value of the name parameter. There's no need for getParameter( ). A bean can also have its scope managed automatically by the server. A bean can be assigned to a specific page (where it is used once and destroyed), a specific request (similar to page scope except the bean persists between internal include and forward calls), to a client session (where the bean is automatically made available every time the same client reconnects), or to an application scope (where the same bean is available to the entire web application). 18.5.1 Embedding a BeanBeans are embedded in a JSP page using the <jsp:useBean> action. It has the following syntax (case sensitive, and the quotes are mandatory): <jsp:useBean scope="page|request|session|application" type="typeName"> </jsp:useBean> You can set the following attributes of the <jsp:useBean> action:
18.5.2 Controlling Bean PropertiesThe <jsp:setProperty> action provides the ability for request parameters to automatically (via introspection) set properties on the beans embedded within a page. This gives beans automatic access to the parameters of the request without having to call getParameter( ). This feature can be used in several ways. First: <jsp:setProperty name="beanName" property="*" /> This says that any request parameter with the same name and type as a property on the given bean should be used to set that property on the bean. For example, if a bean has a setSize(int size) method and the request has a parameter size with a value of 12, the server will automatically call bean.setSize(12) at the beginning of the request handling. If the parameter value can't be converted to the proper type, the parameter is ignored. (Note that an empty string parameter value is treated as if the parameter does not exist and will not assign an empty string value to a String property.) Notice that the action uses the XML shorthand for an empty tag. This is very important. The JSP specification requires all JSP actions to be well-formed XML, even when placed in HTML files. Here's the second <jsp:setProperty> usage: <jsp:setProperty name="beanName" property="propertyName" /> This says that the given property should be set, if there's a request parameter with the same name and type. For example, to set the size property but no other property, use this action: <jsp:setProperty name="prefs" property="size" /> Here's a third <jsp:setProperty> usage: <jsp:setProperty name="beanName" property="propertyName" param="paramName" /> This says that the given property should be set, if there's a request parameter with the given name and the same type. This lets a parameter with one name set a property with another name. For example, to set the size property from the fontSize parameter: <jsp:setProperty name="prefs" property="size" param="fontSize" /> This is the final usage: <jsp:setProperty name="beanName" property="propertyName" value="constant" /> This says that the given property should be set to the given value, which will be converted to the appropriate type if necessary. For example, to set the default size to 18 with a parameter override: <jsp:setProperty name="prefs" property="size" value="18" /> <jsp:setProperty name="prefs" property="size" param="fontSize" /> For advanced users, the value attribute does not need to be a constant; it can be specified using an expression with what's called a request-time attribute expression . For example, to ensure the size never drops below 6: <jsp:setProperty name="prefs" property="size" param="fontSize" /> <jsp:setProperty name="prefs" property="size" value="<%= Math.max(6, prefs.getSize()) %>" /> Finally, the <jsp:getProperty> action provides a mechanism for retrieving property values without using Java code in the page. Its usage looks much like that of <jsp:setProperty>: <jsp:getProperty name="beanName" property="propertyName" /> This says to include at this location the value of the given property on the given bean. It's longer to type than an expression but eliminates the need to place Java code in the page. Whether to use <jsp:getProperty> or an expression is a matter of personal taste. Note that <jsp:getProperty> embeds the property value directly, so if it contains characters that HTML treats as special, that will cause problems. The Apache Struts project has a solution using a custom <property> tag, as we'll discuss later. 18.5.3 Saying "Hello" Using a BeanExample 18-6 demonstrates the use of a JavaBeans component with a JSP page; it says "Hello" with the help of a HelloBean. Example 18-6. Saying "Hello" Using a JavaBean<%-- hello3.jsp --%> <%@ page import="HelloBean" %> <jsp:useBean > <jsp:setProperty name="hello" property="*" /> </jsp:useBean> <HTML> <HEAD><TITLE>Hello</TITLE></HEAD> <BODY> <H1> Hello, <jsp:getProperty name="hello" property="name" /> </H1> </BODY> </HTML> As you can see, using a JavaBeans component with JavaServer Pages can reduce the amount of code placed into the page. The HelloBean class contains the business logic for determining a user's name, while the JSP page acts only as a template. The code for HelloBean is shown in Example 18-7. Its class file should be placed in the standard directory for support classes (WEB-INF/classes). Example 18-7. The HelloBean Classpublic class HelloBean { private String name = "World"; public void setName(String name) { this.name = name; } public String getName() { return name; } } This is about as simple a bean as you'll ever see. It has a single name property that is set using setName( ) and retrieved using getName( ). The default value of name is World, but when a request comes in that includes a name parameter, the property is set automatically by the server with a call to setName( ). To test the mechanism, try browsing to http://server:port/hello3.jsp. You should see something similar to the screen shot in Figure 18-4. Figure 18-4. Saying "Hello" using JavaServer pages in cooperation with a JavaBeans componentOne thing to watch out for: on some servers (including Tomcat 3.2) if you have a bean with a scope of session or application and you change the bean class implementation, you may get a ClassCastException on a later request. This exception occurs because the generated servlet code has to do a cast on the bean instance as it's retrieved from the session or application, and the old bean type stored in the session or application doesn't match the new bean type expected. The simplest solution is to restart the server.
|