The first edition of the book describes how to use an MS Access database for all examples. How can I use another database? |
Answer: You can use any database you like, as long as there’s a JDBC driver for it. Just put the JDBC driver classes in the WEB-INF/lib or WEB-INF/classes directory and change the JDBC URL in the example JSP pages to point to your database. Mike Braden has been kind enough to contribute instructions for how to run the examples with Oracle. Lucy Newman has done the same for PostgreSQL, and Masako Onishi has contributed inststructions for InstantDB. The second edition of the book uses the JSP Standard Tag Library (JSTL) actions for all database access. The data source used by the JSTL actions is configured in the web.xmlfile for the application, to make it easier to switch between databases. I have also included a script with all SQL statements needed to create the example tables, located in WEB-INF/examples.sql. You can use this script to create the tables in a MySQL database, and it should work fine for most other database engines as well. |
Author Archives: hans
Why is there both a PBController and a PBDispatcher in the sample code?
I have downloaded the example code. In the directory src/com/ora/jsp/servlets, there are a PBControllerServlet class and a PBDispatcherServlet class.
I want to implement your Action Object design and get confused as to what files I need to look at. Where do I find what files belong to what example? |
Answer: Sorry about the confusion. The PBControllerServlet class corresponds to examples 14-1 through 14-3. It contains the logic for all actions as private methods. The PBDispatcherServlet class, the Action interface, all XXXAction classes and the ActionUtils class correspond to the example described in “A More Modular Design Using Action Objects”. |
How can I use Tomcat behind IIS?
How can I configure Tomcat 3.2 with my IIS server so I don’t have to use http://localhost:8080? |
Answer:The documents under Tomcat’s doc directory describe how you can configure Tomcat the way you want, but here’s a brief answer.If all you want is to avoid specifying the port number, you can just tell Tomcat to use port 80 instead of port 8080. You can change this in the conf/server.xml file:
<!-- Normal HTTP --> <Connector className="org.apache.tomcat.service.PoolTcpConnector"> <Parameter name="handler" value="org.apache.tomcat.service.http.HttpConnectionHandler"/> <Parameter name="port" value="80"/> </Connector> After you make this change and restart Tomcat, you can use a URL like http://localhost/ instead. Note that if you try this on a Unix/Linux system, you must start Tomcat as “root”, which may be a security risk. On Windows, however, you can use port 80 from any login account. The only reason for running Tomcat behind IIS that I can think of is if you need to serve both JSP pages and dynamic content based on other non-Java technologies (ASP, CGI, etc). You can read more about how to use Tomcat with IIS in doc/tomcat-iis-howto.html. |
How can I use a different JSP directory than webapps for Tomcat?
How can I put JSP files in a directory other than /webapps/ when I use the Tomcat 3.2 container? |
Answer: The documents under Tomcat’s doc directory describe how you can configure Tomcat the way you want, but here’s a brief answer.Edit the conf/server.xml file and add an element like this for top level directory you want to store the JSP files in: <Context path="/myapp" docBase="C:/websites/myapp" crossContext="false" debug="0" reloadable="true" > </Context> Note, however, that the directory you specify as docBase must contain the complete web application directory structure, i.e. the WEB-INF directories as well as the JSP pages (see Chapter 2, 4 and Appendix D in the book for more info). You need to restart Tomcat for this change to take effect. |
How can I access a session scope bean in a servlet?
I create a java bean in the session scope using <jsp:useBean> in a JSP page. I then need to access the information held by the bean in a servlet. How can I get hold of the bean in the servlet? |
Answer: The JSP session scope corresponds to the javax.servlet.http.HttpSession class in the Servlet API. The session scope objects are saved as attributes for the current instance of this class, so you can get them with code like this in a servlet: HttpSession session = request.getSession(); String foo = (String) session.getAttribute("foo"); For more information about how to share objects between JSP pages and servlets, see Chapter 14 in the book. |
When do I need to call clearBody()?
In another JSP book, they make the point of clearing the body content after using it, so the same instance can be reused for another tag handler.In JavaServer Pages (O’Reilly), you do not say anything about calling the clearBody() method. When do I really have to call this method? |
Answer: Typically, you do not need to call the clearBody() method, and it has nothing to do with the container’s ability to reuse the BodyContent instance.According to the JSP 1.1 spec, the container is supposed to get an instance of the BodyContent class for each BodyTag by calling PageContext.pushBody(). The spec says that this method must return a “new” instance, but the language will likely be relaxed in JSP 1.2 to allow a container to use pooled instances instead. Anyway, the BodyContent instance it returns must be empty, so there’s no need to clear it for reuse reasons. This is also clarified in the description of setBodyContent() in the JSP 1.2 Proposed Final Draft. A scenario when you do need to call clearBody() is in an iterating tag handler class, if you push the processed body content to the parent’s “out” in doAfterBody(), i.e. for each pass through the body. In the iteration example in my book (Chapter 16), it’s not needed since I let the evaluation of the body for each pass accumulate and process all of it after the last pass in the doEndTag() method. |
Why do I get “socket write error” messages from Tomcat?
Right after installing the ‘ora’ example application for Tomcat, I surfed to http://localhost:8080/ora no problem, then clicked on Chapter 5, Current Date/Time example. Long delay, then finally the date and time are displayed. But in my Tomcat startup console window, I see:
2000-12-29 10:18:37 - Ctx( ): IOException in: R( + /tomcat-power.gif + null) socket write error (code=10053) 2000-12-29 10:18:37 - Ctx( ): IOException in: R( + /index.html + null) socket write error (code=10053) Do I have an install problem? |
Answer: First, the delay you see the first time you access a JSP page is the time it takes to convert the JSP page into a servlet class file. It only happens the first time, and when you change the JSP page.The error message means that Tomcat could not send the complete response to the browser, because the browser has already closed its connection.As far as I know, this only happen with Internet Explorer (IE). IE seems to close the connection before it has received the complete response when it asks for a resource it already has in its cache. So the first time you load the Tomcat index page, everything is fine. But from then on, both the index.html and the image file are in IE’s cache, and you see this message. It doesn’t cause any problems though, so you can just ignore it. Rumor has it that this problem can be fixed with the latest patches for IE, at least on some Windows platforms. You can also reduce the log level for the Tomcat server so it doesn’t print these error messages. See the Tomcat configuration documents for details. If you use Netscape instead, you’ll notice that it behaves according to the HTTP spec, so you don’t get this message. |
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:
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 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. |