Miscellan – Web Technologies

Q# How do you configure maven? What are the advantages of maven over ant build?

Maven is just a framework of plugins that uses Ant underneath. It stores jar files in a remote repository for easy sharing. Maven is easier to use; there is no need to write large build.xml files since most common tasks are available as plugins.
You have a settings.xml and one or several pom.xml.
settings.xml
The settings.xml is optional and is used to specify the repository location, security and deployment settings. If it is absent default values are used. It may also contain repository authentication informatio and username and passoword for the server on which the generated package is deployed.
Maven Repository
Maven will automatically download artifacts from the online maven repository if the dependencies are not locally available in the repository. The jars are placed in a local maven repository(relative path=.m2/repo).
pom.xml
It contains the following information:

  • the type of packaging,
  • information about the project dependencies(artifacts or dependencies of those artifacts),
  • artifact name
  • artifact version,
  • artifact scope(default scope means the generated package will include this artifact while “provided” means they will be provided by the deployment container),
  • maven plugins that are to be used during the build process(certain plugins such as mvn:clean, mvn:compile, mvn:package are included by default within the maven distribution),
  • dependencies on third party maven repositories

When executing a task or goal, Maven looks for the POM in the current directory. It reads the POM, gets the needed configuration information such as project dependencies, then executes the goal. The goal may be a custom goal or one that is available in a maven plugin or inbuilt into maven.
Maven commands
mvn-test
mvn compile
mvn package
mvn install
are common maven commands.
Advantages
Maven has plugins for all “common” tasks so that all you have to do is add some information to configuration files. These are built over Ant tasks.

Q# Java Messaging Service – here we go again

Two useful links from cuppajava site that proves handy:
http://cuppajavamattiz.com/2007/10/01/jms-and-message-driven-beans-i/
http://cuppajavamattiz.com/2007/10/01/jms-and-message-driven-beans-ii/

Q# For what functionality did you use JMX in any of your applications?

customizing JBoss JMX console to change the state of custom beans at runtime

Q# Have you performed any tomcat or jboss administration?

For the most part developers do very little with jboss and tomcat administration – mainly deployment, datasource configuration. I’m sure jboss and tomcat have a lot of proprietary features that are powerful but normally we don’t use them and instead we stick to standard J2EE techniques and third party frameworks etc. In a production environment the jboss/tomcat administrator may do some tuning like change the # of connections in jdbc pool, JVM args, etc. but normally a developer doesn’t care about this stuff. jboss has a UI for configuration:
see http://docs.jboss.org/jbossas/6/Admin_Console_Guide/en-US/pdf/Admin_Console_Guide.pdf
For tomcat
http://tomcat.apache.org/tomcat-6.0-doc/introduction.html

Q# How does inter-portlet communication take place in liferay?

Q# Describe the JSF life cycle
http://docs.oracle.com/javaee/1.4/tutorial/doc/JSFIntro10.html
Request Processing Scenarios:
1. Faces request: A servlet request that was sent from a previously generated Faces response. i.e. from a jsf page. eg a JSF form submission
2. Non Faces request: A servlet request that was sent from a non JSF page such as a JSP page without JSF tags.
3. Faces response: A servlet response rendered by the RENDER RESPONSE PHASE
4. Non Faces response: A servlet response not rendered by the RENDER RESPONSE PHASE
eg. a jsp page which does not incorporate JSF tags is rendered.

Scenario 1: Non Faces Request generates Faces Response
eg. When a hyperlink is clicked which invokes a JSF page. The non Faces request is mapped to the FacesServlet which generates a Faces response by generating a view which is basically a tree of UI componenents. It then goes to the RENDER RESPONSE PHASE.
Scenario 2: Faces Request generates Non Faces Response
A JSF page rendered through the RENDER RESPONSE PHASE when submitted may render a non JSF page without JSF tags. The RENDER RESPONSE PHASE is skipped and so are all the intermediate steps in the life cycle.
Scenario 3: Faces Request generates Faces Response
This is the most common scenario in a JSF life cycle. A JSF page rendered by a RENDER RESPONSE PHASE generates a Faces request mapped ot the Faces Servlet. All convertors, validators and listeners are invoked as part of the JSF life cycle and a Faces Response is rendered. This process is described below:
The following shows the complete steps from Faces Request to Faces Response.
RESTORE VIEW PHASE
When a request is made from a JSF page i.e. Faces Request postback- such as submission of a JSF page, the JSF implementation restores the view(tree of JSF UI components) by using state information saved on the server or client.
If this is a fresh request for a JSF page, an empty view comprising of JSF UI components is created and moves to the RENDER RESPONSE PHASE bypassing intermediate steps.
APPLY REQUEST VALUES PHASE
After the view is restored, the component tree extracts the request values and stores it, after conversion. If the conversion fails, validation errors are generated. If any listeners are registered, the JSF implementation broadcasts events to these listeners. In short components are set new values, messages and events are queued.
PROCESS VALIDATION PHASE
The JSF implementation processes all validator registred with the UI components and applies these rules to the stored value in the JSF UI componenets. If values are invalid, error messages are generated, and the cycle moves to RENDER RESPONSE PHASE and displays all error message queue up. If events have been queued up at this stage, the JSF implementation broadcasts tehm tho these liseteners.
UPDATE MODEL VALUES PHASE
The JSF implementation updates the model (JSF backing beans) with values from the UI componenets. If the conversion from UI component data types to model data types fails, errors are generated and queued up and the cycle moves to the RENDER RESPONSE PHASE Where these error messages are displayed. If events are queued up at this stage the JSF implementation broadcasts them to interested listeners.
INVOKE APPLICATION PHASE
The JSF implementation consults the application configuration and processes the request by handlers after which the navigation rules are looked up to find which view is to be shown. The cycle then moves to the RENDER RESPONSE PHASE. If events are fired these broadcast to interested listeners.
RENDER RESPONSE PHASE
The JSF implementation hands delegates the remaining steps to the JSP container to render the Faces view.
If the request is postback the errors that were encountered in the above steps will be displayed on the original page.
The state of the response is saved to make it available to the next RESTORE VIEW PHASE.
If this is a fresh request the components are already added to the tree creating an empty view, and this will be rendered by the JSP container.

Instance Variable Declaration in a Servlet vs Instance Variables Declaration in Handler classes

There is a common misunderstanding of how servlet instance variables work.
Let’s consider a Servlet, say the Controller Servlet in Struts(Action Servlet). At any given time there is only one instance of this Servlet. This Servlet is multi-threaded so it does not have state. State in the sense it has no instance variables with values. Many requests can be serviced by this Servlet by running multiple threads on the same instance.
Instance variables can be declared in a servlet but these variables are shared by all threads. No single thread can rely on using the variable for itself, so threads can never depend on the value of an instance variable of a Servlet.
This Servlet passes control to handlers say Action classes in Struts. There are multiple instances of these action classes with their own state and these action classes are not multi-threaded in that sense.
There is one multi-threaded Servlet and multiple handler classes running on different threads. One multi-threaded Servlet can create new action-class instances which are dedicated instances.

Questions, Questions, Questions

Q. Give a tabular definition of common Collection classes.

Q. How would you classify exceptions?

Q Can we call ordinary methods from a synchronized method?

It is good programming advice not to call methods from inside a synchronized method because you may lose track of methods being called and end up in a deadlock because of bad programming. Don’t call any methods within a synchronized block except the class Object methods (wait, notify,).

Q What are the types of validation in Struts?

Validations in Struts are server side.
1. Server side using validation.xml without using javascript and
2. Validation using ValidatorForm with validate() method
In both cases the Form Bean needs to extend ValidatorForm. What you write in validation.xml is invoked by super.validate().
Struts framework reads validation.xml and puts some request attributes as error messages which gets passed on to the tag class behind

<action:errors../>

, which then creates html and sends it to the client.
If you are overriding the validate() method and plan to use both validation.xml as well as handcode the validate() method then you need to use super.validate().
validation.xml will still work if you don’t override the validate() method in your Form Bean extending ValidatorForm because it will inherit super’s validate() method.

Q How would you compare statement, prepared statement and callable statement in SQL?

Callable statement is a different animal, comparing it to queries is like apples and oranges.
Prepared statement is the faster of the two- statement and prepared statement. You write a query “select * from blah where foo=’a’” and next time it is “select * from blah where foo=’b’”, there is a slight change in passed parameter, but the database doesn’t know the difference. It will parse the second query without any memory of the first.
If you use the prepared statement with “?” as placeholder, then the database knows that the query does NOT need to be reparsed. It is cached internally, only the parameter value is changed.

Q Compare SAX and DOM parsers.

A DOM parser processes XML data and creates a tree representation of the document that you can navigate at run-time. The tree representation occupies memory and can be a major resource overhead.
The SAX parser on the other hand raises events that you can handle as you see fit.
Because of this design, the SAX implementation is generally faster and requires fewer resources. On the other hand, SAX code is frequently complex. A SAX parser is suitable for sequential and infrequent access while a DOM parser is more useful for frequent and random access.

Q Name some xsl:fo tags.

A snippet demonstrating use of some xsl:fo tags follows:

<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
	<xsl:template>
		<fo:block>
			<fo:table>
				<fo:table-body>
					<fo:table-row>
						<fo:table-cell>
							<xsl:apply-templates select="category" />
						</fo:table-cell>
					</fo:table-row>
				</fo:table-body>
			</fo:table>
		</fo:block>
	</xsl:template>

	<xsl:template match="category">
		<fo:block>
			<xsl:value-of select="." />
		</fo:block>
	</xsl:template>
</xsl:stylesheet>

XML:

<category>
An asset to our company
</category>

Q Name some xsl tags.

A snippet demonstrating use of xsl tags follows:

Xsl:

<xsl:for-each select="ENTRY">
	<xsl:for-each select="ENGLISH">
		<td width="25%">
			<xsl:if test="string(.)!='null'">
				<i>
					<xsl:value-of select="." />
				</i>
			</xsl:if>
		</td>
	</xsl:for-each>
</xsl:for-each>

Xml:

<entry>
	<english>20</english>
	<german>A+</german>
</entry>
<entry>
	<english>10</english>
	<german>C++</german>
</entry>
<entry>
	<english>10</english>
	<german>A</german>
</entry>

Q Name some JSF tags:

A snippet demonstrating JSF tags follows:

<f:view>
	<h:form>
		<h:panelGrid id="grid1" columns="2" border="0" width="100%">
			<h:outputText id="text1" style="color: #000099;" value="Enter ISBN Code :" />
			<h:inputText value="#{authorBean.isbnCode}" />
		</h:panelGrid>
	</h:form>
</f:view>

A similar snippet using ADF faces would look like this:

<ui:define name="body">
	<div id="MyForm" class="HeaderBlock">
		<h:panelGrid columns="2">
			<af:outputLabel for="userName" value="Enter UserName " />
			<af:inputText id=" userName " columns="30"
				value="#{MyBean.userName}" maximumLength="40" />
		</h:panelGrid>
	</div>
</ui:define>

Q What are the implicit variables in JSP, and what are their servlet equivalents?

Implicit vars in JSP       Scope           Servlet-Equivalent

pageContext
application      application       ServletContext
request          request           HttpServletRequest
session          session           HttpSession
response                         HttpServletResponse
out                              PrintWriter
config                           ServletConfig
exception                        Throwable
page                             Object

Q Name some Ant tags.

<target name="war" depends="compile">
	<war warfile="${war}" webxml="${conf.dir}/web.xml">
		<classes dir="${build.classes.dir}">
			<include name="**/**" />
		</classes><!--All files included in this fileset will end up in the WEB-INF/classes
			directory of the war file -->
		<fileset dir="${css.dir}">
			<include name="**/**" />
		</fileset><!--places files from css dir(build) into root of the war -->
		<webinf dir="${conf.dir}">
			<include name="**/**" />
		</webinf><!--places files from conf dir(build) into WEB-INF of war -->
		<zipfileset dir="${images.dir}" prefix="images" />
		<!--places folder of images dir(build and places it in folder called "images"
			in root of war) > <lib dir="${jsf.lib.dir}"/><!--places files from lib(build
			into WEB-INF/lib folder of war) -->
	</war>
</target>

Q what are inner and outer joins in SQL?

Inner joins will return all rows from multiple tables where the join condition(in the “where” clause) is met.
An outer join returns all rows from one table and only those rows from a secondary table where the joined fields are equal (join condition is met).

Q. Name some Struts tags:

Some Struts tags:

Struts html tags: <html:text../> <html:form../> <html:errors/> <html:submit../> <html:reset../>
Struts bean tags: <bean:write.../> <bean:message.../>
Struts logic tags: <logic:iterate../> <logic:empty.../>
Struts nested tags: <nested:write... /> <nested:iterate.../>
Struts tiles tags: <tiles:insert../> <tiles:put../>

What is connection pooling?

A connection pool is a cache of open connections that can be used and reused, thus cutting down on the overhead of creating and destroying database connections.

Q. Briefly describe Servlet and JSP life cycles.

Servlet Life Cycle

When the Servlet Container starts up, it looks for web.xml, which includes an entry for each of the servlet the application uses. The servlet creates an instance of the compiled class and loads it. Next the servlet is initialized with initialization parameters in the ServletConfig object. The servlet is initialized after init() method returns. (Lazy loading – The servlet container does not initialize the servlet as soon as it starts up but rather when it receives a specific request for that servlet for the first time).
After the servlet instance is initialized, it is ready to service client requests. When the servlet container no longer needs the servlet instance(such as when the container is shutting down, or it is running low on resources, or no request has arrived for that servlet for a long itme), the servlet instance again goes to the unloaded state and cannot service any requests. Once destroyed, the servlet instance is garbage collected.

JSP life cycle

For each client request, the jsp container checks if the JSP page is new or has already been converted to a class file. If so, page translation occurs where the jsp code is converted to a regular java file, after checking for translation time errors. This java file is then compiled into a class file after compile time errors are checked. Once an instance of the class file is loaded it follows the same life cycle pattern as a regular servlet except that the following methods are involved
jspInit() instead of init()
jspDestroy() instead of destroy()
The container calls _jspService(), which was created during translation time by the jsp container, for each request.

Common Interview Questions On Struts:

Q. What are the methods in a Struts Action Form?

An action form defines properties that have a one to one mapping with the html form elements in the JSP page. The Action Form needs to implement public getters and setters for these properties. Later versions of Struts do not require both a getter and setter for html form elements
Optional methods:
1. public ActionErrors validate(ActionMapping, HttpServletRequest req):
This method can be implemented when the ActionForm extends ValidatorForm. It is usually used with Java based validation and when complex validations that cannot be handled by validation.xml are involved. If a form extends ValidatorForm and does not provide the validate() method, the superclass validate() is inherited from the parent ValidatorForm that allows validation using validation.xml to be implemented. For validation involving both validation.xml and code within validate() one needs to implement the validate() method and configure validation.xml as well.
2. The reset() method:
The reset method allows one to set the values of all properties in the ActionForm to default values. It also allows one to initialize ActionForm properties within the body of the method. However with DynaActionForms reset() sets all properties to default values and does not allow one to initialize ActionForm properties.

Q What is the sequence of calls when an ActionForm is called by the ActionServlet?

The reset() method is called before the ActionForm is populated. Following this the setter methods are called to populate the ActionForm. Validate() is called if the ActionForm extends ValidatorForm.

Q. Describe the control flow when a request is submitted to a Struts application.

1. When the ActionServlet receives a request, the first thing it does is to check the ActionMappings defined in struts-config.xml to check for a matching path. ActionMappings are JavaBeans that Struts creates when reading the struts-config.xml at application startup.
2. Next the ActionServlet checks for the name attribute in the ActionMapping for the FormBean mapped to this ActionMapping. The corresponding ActionForm is instantiated and its setter methods are called to populate the ActionForm.
3. The type attribute is checked to instantiate the Action class and the perform()/execute() method is called on it. A reference to the ActionForm is passed as a parameter to the perform()/execute() method.
4. Depending on the outcome of perform()/execute() ActionMapping.findForward() is called which uses a single String attribute that matches one of the “name” attributes of the nested “forward” tags within the ActionMapping described in struts-config.xml. The “path” attribute of the “forward” tag determines the url to which the flow of control is altered to generate the response. An ActionForward can also be created dynamically within the Action class to specify the url to which the flow of control needs to be passed.

Q. Can an ActionMapping in struts-config.xml not have an Action class associated with it at all?

Yes. When an ActionMapping needs to directly transfer the flow of control to a JSP page without any processing to be done, the ActionForm need not be specified. In that case the “forward” attribute of the ActionMapping is used. “type” (which associates an Action class to the Action Mapping) and “forward” elements of an ActionMapping are mutually exclusive.

Q. Can a Struts application have multiple ActionServlets?

No. A single Struts application can have only a single ActionServlet associated with it. This is the Front Controller pattern. When the ActionServlet that acts as the FrontController in the Struts framework, receives a request it routes it to a handler class that performs business operations, usually using helper classes. The ActionServlet determines which business operations are related to which request by looking up the ActionMappings in the struts-config.xml. The multi-threaded handler class (Action class) handles business operations by calling helper classes. The handler class is passed the specifics of each request used in the operation.
When the Action class returns, the ActionServlet may have to lookup an ActionForward associated with the related mapping and pass the response to the url specified in it.

Q. What are the changes to be made to web.xml to configure Struts? Compare this with how the web.xml is modified to configure JSF.

A snippet in web.xml to configure the ActionServlet looks like this:

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.matty</url-pattern>
    <!--Could also be <url-pattern>/matty/*</url-pattern -->
</servlet-mapping>

When the parameter 1 is specified in the load-on-startup tag, the ActionServlet is the first servlet to be loaded on application startup. When 2 is specified other servlets with a values of 1 are loaded initially. Such servlets may perform initialization operations needed to be done before the ActionServlet is invoked by the container.

web.xml also has to define taglibs used by your Struts application. A snippet follows:

<taglib>
    <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
    <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
    <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>

Additional configuration for nested taglib, tiles taglib may also be defined in web.xml when needed.

A typical configuration in web.xml for JSF looks like this:

<context-param>
    <param-name>javax.faces.CONFIG_FILES</param-name>
    <param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>

Q. Can a Struts application have multiple struts-config.xml files?

Yes. The following is an example of how separate struts-config.xml may be configured in web.xml for “matt” and “tizz” modules in addition to the default module.

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
    <param-name>config</param-name>
    <param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
 
<init-param>
    <param-name>config/matt</param-name>
    <param-value>/WEB-INF/struts-config-matt.xml</param-value>
</init-param>
<init-param>
    <param-name>config/tizz</param-name>
    <param-value>/WEB-INF/struts-config-tizz.xml</param-value>
</init-param>
……
</servlet-mapping>

Q How do you handle errors in Struts?

The validate() method of the ActionForm returns an ActionErrors object.
A snippet:

ActionErrors errors = new ActionErrors();
errors add(ActionErrors.GLOBAL_ERROR), new ActionError(my.error));
return errors;

An Action class can also generate ActionErrors.
A snippet:

ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR), new ActionError(my.error));
saveErrors(request, errors);
return new ActionForward(mappings.getInput());

The errors in the ActionErrors object are displayed using the html:errors tag in the forwarded JSP.

Q What are DynaActionForms and DynaValidatorForms?

DynaActionForms allow FormBean creation by specifying them directly in the struts-config.xml. They cannot have reset() or validate() methods. All FormBean properties are set to default values before the FormBean is populated, without allowing initialization of FormBean properties.
DynaValidatorForms are similar to DynaActionForms but they use the validator framework by allowing properties to be validated using validation.xml settings.

Q Describe some common methods used to populate custom JavaBeans (Value Objects) from ActionForms.

1. The BeanUtils calss has a describe() method that returns a Map of a JavaBean’s public properties. It also offers a corresponding populate() method that will set the public properties of a JavaBean from a Map.

public class TestVO
{
private Map map;
//getters and setters for map
}

When we go from FormBean form to VO testVO

Map map = BeanUtils.describe(form);
testVO.setMap(map);

When we go from VO testVO to FormBean form

Map map = testVO.getMap();
BeanUtils.populate(form, map);

2. You can use copyProperties() of BeanUtils class to populate your FormBean from any other bean using the Reflection API:

BeanUtils.copyProperties(myBean,myForm);
myOperation(myBean);
BeanUtils.copyProperties(myForm, MyBean);

The code in this snippet transfers the String properties in myForm to native types in myBean. It then transfers the native types in myBean back to the all String properties in myForm after business logic processing.
Converting non-native types such as Dates may requires a bit more effort.

3. Maps can be used as ActionForm properties. But a values from a Map is treated differently from a regular JavaBean property.

public class MyForm extends ActionForm {
	private Map map = null;

	// setters and getters for map
	public void setValue(String key, Object value) {
		getMap().put(key, value);
	}

	public void getValue(String key) {
		return getMap().get(key);
	}
}

One can access the elements of the map in the jsp page thus:

<html:text property=”value(someProperty)”/>

OR

<bean:write name=”myForm” property= “value(someProperty)”/>

Web Design Patterns at Work with Pagination

This example demonstrates the use of common web design patterns and gives a solution for pagination. I am using JSF as the MVC framework for this example.
I am using the authors database on mySQL which I have used in the previous examples. Refer the simple entity bean example on details of creation of the authors database and setting up of the mySQL datasource.
You need to set JBOSS_HOME and ANT_HOME before you can get on with this example.
You would also need to download the jsf jars listed under lib/jsfJars from the relevant website.

My work folder has the following structure:
build.xml

<build>
     <classes>
     <dist>
<webRoot>
     <web-INF>
         faces-config.xml
         web.xml
         html_basic.tld
         jsf_core.tld
<lib>
     <jsfJars>
         commons-beanutils.jar
         commons-collections.jar
         commons-digester.jar
         commons-logging.jar
         jsf-api.jar
         jsf-impl.jar
<src>
     <web>
         <mattiz>
              <pages>
                       author.jsp
                       authorAdded.jsp
                       authorPage.jsp
     <java>
         <com>
              <mattiz>
                       <beans>
                           AuthorDTO.java
                       <businessDelegates>
                           MattizDelegate.java
                       <dao>
                           MattizDAO.java
                       <exception>
                           MattizException.java
                       <web>
                           <managedBeans>
                                 AuthorBean.java

Let me list the web pages first:
author.jsp :


<%@page contentType="text/html"%>
<%@ taglib uri="/WEB-INF/html_basic.tld" prefix="h"%>
<%@ taglib uri="/WEB-INF/jsf_core.tld" prefix="f"%>
<html>
<head>
<title>author.jsp</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
	<f:view>
		<h:form>
			<h:panelGrid id="grid1" columns="2" border="0" width="100%">
				<h:outputText id="text1"
					style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;"
					value="Enter ISBN Code    :" />
				<h:inputText style="color: automatic; background: iceblue;"
					value="#{authorBean.isbnCode}" />
				<h:outputText id="text2"
					style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;"
					value="Enter Author Name:" />
				<h:inputText style="color: automatic; background: iceblue;"
					value="#{authorBean.author}" />
			</h:panelGrid>
			<h:panelGrid id="grid3" columns="2" border="0" width="100%">
				<h:commandButton value="Add" type="submit"
					action="#{authorBean.addAuthor}" />
			</h:panelGrid>
			<hr />
			<h:panelGrid id="grid5" columns="2" border="0" width="100%">
				<h:outputText id="text3"
					style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;"
					value="Paginate Author Details " />
			</h:panelGrid>
			<h:panelGrid id="grid6" columns="2" border="0" width="100%">
				<h:commandButton value="Paginate" type="submit"
					action="#{authorBean.displayAuthors}" />
			</h:panelGrid>
		</h:form>
	</f:view>
</body>
</html>

authorPage.jsp:

<%@page contentType="text/html"%>
<%@ taglib uri="/WEB-INF/html_basic.tld" prefix="h"%>
<%@ taglib uri="/WEB-INF/jsf_core.tld" prefix="f"%>
<html>
<head>
<title>authorPage.jsp</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
	<f:view>
		<h:form>
			<%
				if (request.getAttribute("count") != null) {
							int count = Integer.parseInt(request.getAttribute(
									"count").toString());
							int start = Integer.parseInt(request.getAttribute(
									"start").toString());
							int end = Integer.parseInt(request.getAttribute("end")
									.toString());
							int totRows = Integer.parseInt(request.getAttribute(
									"totRows").toString());
			%>
			<h:dataTable width="100%" border="0" id="values"
				value="#{authorBean.authorsList}" var="authorDTO"
				style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px;font-weight: bold; color: #000000">
				<h:column>
					<h:outputText value="#{authorDTO.isbnCode}"
						style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;" />
				</h:column>
				<h:column>
					<h:outputText value="#{authorDTO.author}"
						style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;" />
				</h:column>
			</h:dataTable>
			<%
				if (!(start == 1)) {
			%>
			<h:commandLink action="#{authorBean.displayAuthors}">
				<h:outputText value="PREV"
					style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;" />
				<f:param name="begin" value="#{start-10}" />
				<f:param name="finish" value="#{end-10}" />
				<f:param name="no" value="#{count}" />
				<f:param name="change" value="decr" />
			</h:commandLink>
			<%
				}
							if (!(count == totRows)) {
			%>
			<h:commandLink action="#{authorBean.displayAuthors}">
				<h:outputText value="NEXT"
					style="color: #000099;font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 10px;font-weight: bold;" />
				<f:param name="begin" value="#{start+10}" />
				<f:param name="finish" value="#{end+10}" />
				<f:param name="no" value="#{count}" />
				<f:param name="change" value="incr" />
			</h:commandLink>
			<%
				}
						}
			%>
		</h:form>
	</f:view>
</body>
</html>

authorAdded.jsp :

<%@page contentType="text/html"%>
<%@ taglib uri="/WEB-INF/html_basic.tld" prefix="h"%>
<%@ taglib uri="/WEB-INF/jsf_core.tld" prefix="f"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>Author Added Page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
	<f:view>
Author added successfully to database
<h:form>
			<h:commandButton value="Back" type="submit" action="back" />
		</h:form>
	</f:view>
</body>
</html>

Next I list the java classes:

AuthorBean.java is the backing bean for all the jsp pages:

package com.mattiz.web.managedBeans;

import java.util.ArrayList;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.mattiz.Exception.MattizException;
import com.mattiz.beans.AuthorDTO;
import com.mattiz.businessDelegates.MattizDelegate;

public class AuthorBean {
	private String isbnCode;
	private String author;
	private HttpServletRequest request;
	private HttpSession session;
	ArrayList authorsList;

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIsbnCode() {
		return isbnCode;
	}

	public void setIsbnCode(String isbnCode) {
		this.isbnCode = isbnCode;
	}

	public String addAuthor() {
		AuthorDTO authorDTO = new AuthorDTO(getIsbnCode());
		authorDTO.setAuthor(getAuthor());
		MattizDelegate mattizDelegate = new MattizDelegate();
		try {
			mattizDelegate.addAuthor(authorDTO);
		} catch (MattizException me) {

		}
		return "authorAdded";
	}

	public String displayAuthors() {
		FacesContext context = FacesContext.getCurrentInstance();
		request = (HttpServletRequest) context.getExternalContext()
				.getRequest();
		session = request.getSession();
		MattizDelegate mattizDelegate = new MattizDelegate();
		try {
			int start = 1;
			int end = 10;
			if (request.getParameter("begin") != null) {
				start = Integer.parseInt(request.getParameter("begin"));
			}
			if (request.getParameter("finish") != null) {
				end = Integer.parseInt(request.getParameter("finish"));
			}
			authorsList = mattizDelegate.getAuthors(start, end);
			int count = 0;
			String change = "incr";
			if (request.getParameter("no") != null) {
				count = Integer.parseInt(request.getParameter("no"));
			}
			int totalRows = mattizDelegate.getNumberOfRows();
			if (request.getParameter("change") != null) {
				change = request.getParameter("change").toString();
			}
			if (change.equals("incr")) {
				request.setAttribute("count",
						new Integer(count + authorsList.size()));
			} else if (change.equals("decr")) {
				request.setAttribute("count", new Integer(end));
			}
			request.setAttribute("start", new Integer(start));
			request.setAttribute("end", new Integer(end));
			request.setAttribute("totRows", new Integer(totalRows));
		} catch (MattizException me) {

		}
		return "paginateAuthors";
	}

	public ArrayList getAuthorsList() {
		return authorsList;
	}

	public void setAuthorsList(ArrayList authorsList) {
		this.authorsList = authorsList;
	}
}

MattizDelegate.java is the business delegate class:

package com.mattiz.businessDelegates;

import java.util.ArrayList;
import com.mattiz.Exception.MattizException;
import com.mattiz.beans.AuthorDTO;
import com.mattiz.dao.MattizDAO;

public class MattizDelegate {
	MattizDAO mattizDAO;

	public MattizDelegate() {
		mattizDAO = new MattizDAO();
	}

	public void addAuthor(AuthorDTO author) throws MattizException {
		mattizDAO.addAuthor(author);
	}

	public ArrayList getAuthors(int start, int end) throws MattizException {
		ArrayList authorArray = mattizDAO.getAuthors(start, end);
		return authorArray;
	}

	public int getNumberOfRows() throws MattizException {
		int rowCount = mattizDAO.getNumberOfRows();
		return rowCount;
	}
}

MattizDAO.java is the Data Access Object class. Note helper method closeStatements(ResultSet rs, PreparedStatement ps, Connection conn) which adds elegance to how connections are created, statements initialized and later disposed off.

package com.mattiz.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import com.mattiz.Exception.MattizException;
import com.mattiz.beans.AuthorDTO;

public class MattizDAO {
	private static DataSource ds;
	public static final String DATASOURCE_LOOKUP_NAME = "java:dbpool";

	public MattizDAO() {
		try {
			InitialContext ctx = null;
			ctx = new InitialContext();
			ds = (DataSource) ctx.lookup(DATASOURCE_LOOKUP_NAME);
		} catch (javax.naming.NamingException jnx) {
			// log an error declaring connection could not be created
			// object MattizDAO could not be initialized
		}
	}

	public void addAuthor(AuthorDTO author) throws MattizException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = ds.getConnection();
			String qry = "insert into authors values(?,?);";
			ps = conn.prepareStatement(qry);
			ps.setString(1, author.getIsbnCode());
			ps.setString(2, author.getAuthor());
			// other examples of setters for prepared statement below:
			// ps.setInt(3, 0);
			// ps.setDate(4, new java.sql.Date(1 - 1 - 2007));
			// ps.setTime(5, new java.sql.Time(1 - 1 - 2007));
			// ps.setDouble(6, 1);
			ps.execute();// in case this is an insert/ update
			// PreparedStatement ps, ResultSet rs, Connection conn can be reused
			// with new values for another query
		} catch (SQLException e) {
			throw new MattizException();
		} finally {
			closeStatements(rs, ps, conn);
		}
	}

	public ArrayList getAuthors(int start, int end) throws MattizException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		ArrayList authorsList;
		try {
			conn = ds.getConnection();
			String qry = "select * from authors;";
			ps = conn.prepareStatement(qry);
			rs = ps.executeQuery();// in case this is a select
			authorsList = new ArrayList();
			int counter = 0;
			while (rs.next()) {
				counter++;// loop till counter>=start
				if (counter >= start && counter <= end) {
					AuthorDTO authorDTO = new AuthorDTO(
							rs.getString("isbn_code"));
					authorDTO.setAuthor(rs.getString("author"));
					authorsList.add(authorDTO);
				} else if (counter > end) {// break out of loop when
				// counter>end
					break;
				}
			}
			// PreparedStatement ps, ResultSet rs, Connection conn can be reused
			// for another query
		} catch (SQLException e) {
			throw new MattizException();
		} finally {
			closeStatements(rs, ps, conn);
		}
		return authorsList;
	}

	public int getNumberOfRows() throws MattizException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		int rowCount = 0;
		try {
			conn = ds.getConnection();
			String qry = "select count(*) from authors;";
			ps = conn.prepareStatement(qry);
			rs = ps.executeQuery();
			if (rs.next()) {
				rowCount = rs.getInt(1);
			}
		} catch (SQLException e) {
			throw new MattizException();
		} finally {
			closeStatements(rs, ps, conn);
		}
		return rowCount;
	}

	private void closeStatements(ResultSet rs, PreparedStatement ps,
			Connection conn) throws MattizException {
		if (rs != null) {
			try {
				rs.close();
			} catch (Exception e) {
				throw new MattizException();
			}
			rs = null;
		}
		if (ps != null) {
			try {
				ps.close();
			} catch (Exception e) {
				throw new MattizException();
			}
			ps = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				throw new MattizException();
			}
			conn = null;
		}
	}
}

AuthorDTO.java is the Data Transfer Object (Value Object):

package com.mattiz.beans;

public class AuthorDTO {
	private String isbnCode;
	private String author;

	public AuthorDTO(String isbnCode) {
		this.isbnCode = isbnCode;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getIsbnCode() {
		return isbnCode;
	}
}

I use one exception class in the example and MattizException.java :

package com.mattiz.Exception;

public class MattizException extends Exception {
	public MattizException() {
		super();
	}

	public MattizException(String msg) {
		super(msg);
	}
}

web.xml configure the Faces Servlet which is the controller for the JSF framework, and the location of the faces-config.xml file which is the configuration file for JSF:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	version="2.4"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<context-param>
		<param-name>javax.faces.CONFIG_FILES</param-name>
		<param-value>/WEB-INF/faces-config.xml</param-value>
	</context-param>
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.faces</url-pattern>
	</servlet-mapping>
</web-app>

faces-config.xml defines the navigation rules for the JSF framework and defines the managed beans (backing beans) for the jsp pages:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
	<navigation-rule>
		<navigation-case>
			<from-outcome>authorAdded</from-outcome>
			<to-view-id>/pages/authorAdded.jsp</to-view-id>
		</navigation-case>
	</navigation-rule>
	<navigation-rule>
		<navigation-case>
			<from-outcome>paginateAuthors</from-outcome>
			<to-view-id>/pages/authorPage</to-view-id>
		</navigation-case>
	</navigation-rule>
	<navigation-rule>
		<navigation-case>
			<from-outcome>back</from-outcome>
			<to-view-id>/pages/author.jsp</to-view-id>
		</navigation-case>
	</navigation-rule>
	<managed-bean>
		<description>JSF Backing Bean for adding/paginating author
		</description>
		<managed-bean-name>authorBean</managed-bean-name>
		<managed-bean-class>com.mattiz.web.managedBeans.AuthorBean</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
	</managed-bean>
</faces-config>

build.xml automates the build process. The compiled classes are placed under build/classes folder of root, later zipped as a jar, the jar included within lib of the war (the jar and war files are placed temporarily in build/dist). The war file is finally deployed to jboss deploy folder.

Run build.xml from the command prompt with the following command:
ant install

<?xml version="1.0" encoding="UTF-8"?>
<project name="Mattiz" default="install" basedir=".">
	<property environment="env" />
	<property name="build.dir" location="build" />
	<property name="build.classes.dir" location="${build.dir}/classes" />
	<property name="build.dist.dir" location="${build.dir}/dist" />
	<property name="java.src.dir" location="src/java" />
	<property name="web.src.dir" location="src/web/mattiz" />
	<property name="JBOSS_HOME" location="${env.JBOSS_HOME}" />
	<property name="install.jboss.deploy.dir" location="${JBOSS_HOME}/server/default/deploy" />
	<property name="jsfJars.dir" location="lib/jsfJars" />
	<path id="build.path">
		<pathelement location="${JBOSS_HOME}/server/default/lib/jboss-j2ee.jar" />
		<pathelement location="${JBOSS_HOME}/client/javax.servlet.jar" />
		<pathelement location="${jsfJars.dir}/jsf-api.jar" />
	</path>
	<target name="clean">
		<delete file="${build.dist.dir}/mattiz.jar" />
		<delete file="${build.dist.dir}/mattiz.war" />
		<delete file="${install.jboss.deploy.dir}/mattiz.war" />
		<delete dir="${build.classes.dir}" />
	</target>
	<target name="init">
		<mkdir dir="${build.dir}" />
		<mkdir dir="${build.classes.dir}" />
		<mkdir dir="${build.dist.dir}" />
	</target>
	<target name="compile" depends="init">
		<javac srcdir="${java.src.dir}" destdir="${build.classes.dir}"
			debug="on" deprecation="on" classpathref="build.path" optimize="off" />
	</target>
	<target name="jar" depends="compile">
		<jar destfile="${build.dist.dir}/mattiz.jar">
			<fileset dir="${build.classes.dir}" includes="**/*" excludes="**/*.java" />
		</jar>
		<copy todir="${build.classes.dir}">
			<fileset dir="${java.src.dir}" />
		</copy>
		<war destfile="${build.dist.dir}/mattiz.war" webxml="WebRoot/WEB-INF/web.xml">
			<webinf dir="WebRoot/WEB-INF" />
			<lib dir="${jsfJars.dir}" />
			<lib dir="${build.dist.dir}" includes="mattiz.jar" />
			<zipfileset dir="${web.src.dir}/pages" prefix="pages" />
		</war>
	</target>
	<target name="install" depends="jar">
		<copy overwrite="${FORCE}" todir="${install.jboss.deploy.dir}">
			<fileset dir="${build.dist.dir}">
				<include name="mattiz.war" />
			</fileset>
		</copy>
	</target>
</project>

The war file created has the following structure:

<meta-INF>
<pages>
     author.jsp
     authorAdded.jsp
     authorPage.jsp
<web-INF>
     web.xml
     faces-config.xml
     html_basic.tld
     jsf_core.tld
     <lib>
          commnons-collections.jar
          commons-beanutils.jar
          commons-digester.jar
          jsf-impl.jar
          jsf-api.jar
          {mattiz.jar}
               <meta-INF>
               <com>
                   <mattiz>
                          <beans>
                               AuthorDTO.class
                          <businessDelegates>
                               MattizDelegate.class
                          <dao>
                               MattizDAO.class
                          <exception>
                               MattizException.class
                          <web>
                               <managedBeans>
                                         AuthorBean.class

Start the application with the following URL:

http://localhost:8080/mattiz/pages/author.faces

You are provided with an option to add entries to the database, so that you have enough entries in the database to see pagination work.

Putting it all together:

The Faces Servlet configured in web.xml acts as the Front Controller. It is not manually coded as it is part of the JSF MVC architecture (implied). The request from the client reaches the Front Controller, usually implemented as a servlet. It may use JavaBeans to access the information from the database that is required to authenticate the request. Then, depending on the state of the client’s session, the Front Controller determines to which other worker objects the request will be forwarded for processing. Finally, after the request has been processed, the last worker servlet will forward the request to one of the JSP pages for presenting the data to the client.
During the processing of the request, multiple servlets or JSP pages may be involved, each one optionally creating and updating JavaBeans. In this case, the beans act as the model, the servlets are the controller, and the JSP pages are the view. The beans work closely with the Business Delegate objects to send and receive business data in the form of Value Objects to the business tier, where these data objects are processed and
transactions are performed.
All business objects then make use of Data Access Objects, to fetch and update data from the data store. The DAO shields the business objects from the management chores of the data stores.
Winding it up, in this example we have given examples of four design patterns — Value Object, MVC, Data Access Object, and Business Delegate—and the Front Controller.

Code can be downloaded here

Issues with Integrity of Instance Variables in jsp/servlets

When isThreadSafe is true, then the page does not implement SingleThreadModel, but rather implements the MultiThreadedModel. The default handling for this servlet, as defined by the servlet spec is to create ONE instance of the servlet, which handles all requests. Thus there can be multiple threads going through a JSP/servlet service method. By default a page is threadsafe, that is it does not implement SingleThreadModel but rather the MUltiThreadedModel. So with MultiThreadedModel, session and request are still separate as they are not instance variables and they are just input to the method of the servlet, they don’t belong to the servlet instance. They are sent in when service(httprequest etc…) method is invoked, so they are like local variables. This is not true for instance variables defined in the servlet. Different threads are manipulating a single instance variable.
One way to retain data integrity of local variables is to use the SingleThreadModel(isThreadSafe=”false”).
Normally servlets (or jsps) are kept as a single instance. The service() method is run on separate threads. Now when we explicitly say isThreadSafe =”false” (SingleThreadModel in servlets) the service() method becomes single-threaded, that is the servlet instance is accessed by only one thread at a time. Normally only one instance is still available and this can be a bottleneck for performance. However if you make it single threaded, some servlet engine implementations keep a pool of instances to avoid performance bottlenecks. In such cases, this causes data integrity problems. So the suggestion is don’t make it single threaded – let the isThreadSafe=true which is default.
Then you are assured of having a single instance and multiple threads, but make the instance variables synchronized to manage the conflict between threads. why synchronize? You are trying to keep the integrity of the values stored as instance variables in the servlet. The instance variable is shared by multiple threads. Different threads are manipulating a single instance variable and so you need to synchronize the instance to keep the integrity of instance variable.
This only applies for instance variables outside the service method. Local variables are stored on the stack – each thread has its own stack, they are never shared.

How does a DTD look like?

Consider this xml file:

<document>
	<database>
		<authors>
			<authors-ROW>
				<isbn_CODE>abc123</isbn_CODE>
				<author-NAME>Karl Peter</author-NAME>
			</authors-ROW>
			<authors-ROW>
				<isbn_CODE>xyz123</isbn_CODE>
				<author_NAME>John Smith</author_NAME>
			</authors-ROW>
		</authors>
		<publishers>
			<publishers-ROW>
				<pub_CODE>aaa123</pub_CODE>
				<pub_NAME>Martin Hall</pub_NAME>
			</publishers-ROW>
			<publishers-ROW>
				<pub_CODE>bbb123</pub_CODE>
				<pub_NAME>Mark Robinson</pub_NAME>
			</publishers-ROW>
		</publishers>
	</database>
</document>

It is perfectly legal to have XML documents without DTDs.Think of them as XML files without a pre-defined format.XML Documents that do not have DTDs are called well-formed XML documents.XML Documents that do have DTDs are called well-formed and valid XML documents.
To see how a DTD looks like, let’s create a DTD for out XML document above-

<?xml version = "1.0" standalone="no"?>
<doctype DOCUMENT [<!ELEMENT DOCUMENT(DATABASE)>
<!ELEMENT DATABASE(AUTHORS, PUBLISHERS)>
<!ELEMENT AUTHORS(AUTHORS-ROW)*>
<!ELEMENT AUTHORS-ROW(ISBN_CODE, AUTHOR_NAME)>
<!ELEMENT ISBN_CODE(#PCDATA)>
<!ELEMENT AUTHOR_NAME(#PCDATA)>
<!ELEMENT PUBLISHERS(PUBLISHERS-ROW)*>
<!ELEMENT PUBLISHERS-ROW(PUB_CODE, PUB_NAME)>
<!ELEMENT PUB_CODE(#PCDATA)>
<!ELEMENT PUB_NAME(#PCDATA)>

Explanation for this DTD –

<!ELEMENT DOCUMENT(DATABASE)>

This means that the “DOCUMENT” element should have only one “DATABASE” element inside it.

<!ELEMENT DATABASE(AUTHORS, PUBLISHER)>

This means that the “DATABASE” element should have two elements inside it “AUTHORS” and “PUBLISHERS” – in that order.

<!ELEMENT AUTHORS(AUTHORS-ROW)*>

This means that the “AUTHORS” element should have zero or more “AUTHORS_ROW” elements inside it.
(The * signifies the “zero or more” relationship).

<!ELEMENT AUTHORS-ROW(ISBN_CODE, AUTHOR_NAME)>

This means that the “AUTHORS-ROW” element should have two elements inside it “ISBN_CODE” and “AUTHOR_NAME” – in that order.

<!ELEMENT ISBN_CODE(#PCDATA)>

this means that the ISBN_CODE element has some data in it (PCDATA stands for Parsed Character DATA).

<!ELEMENT AUTHOR_NAME(#PCDATA)>

this means that the AUTHOR_NAME element has some data in it (PCDATA stands for Parsed Character DATA).

<!ELEMENT PUBLlSHERS(PUBLlSHERS-ROW)*>

This means that the “PUBLISHERS” element should have zero or more “PUBLISHERS-ROW” elements inside
it. (The * signifies the “zero or more” relationship).

<!ELEMENT PUBLISHERS-ROW(PUB_CODE, PUB_NAME)>

This means that the “PUBLISHERS-ROW” element should have two elements inside it “PUB_CODE” and “PUB_NAME” – in that order.

<!ELEMENT PUB_CODE(#PCDATA)>

this means that the PUB_CODE element has some data in it (PCDATA stands for Parsed Character DATA).

<!ELEMENT PUB_NAME(#PCDATA)>

this means that the PUB_NAME element has some data in it (PCDATA stands for Parsed Character DATA).

What data can the Request and Session objects hold?

In the case of request dispatcher – forward or include methods, the request object is transferred as well, along with all parameters that it holds.
sendRedirect, fresh doPost/ doGet result in fresh request objects, hence data contained in the request object is not universally available in the session, and in fact, is temporary to the extent of transmitting from client-to-servlet and between servlet-chains.
Hence session-tracking comes into the picture. Session-tracking internally uses cookies to implement its functioning and is alive until it times-out or is invalidated, so the data stored in a session is in fact serialized and written on the client side in the form of cookies (in small files)…
Hence session objects can hold data across multiple screens of an application that will not be lost unless the session is explicitly invalidated by the code or the browser is closed.
Another point to be considered is that the request object can only hold small string values (parameters) that are generated by the client and cannot be manipulated between servlet chains.
In contrast, sessions can be loaded with entire objects that can be modified (and accessed) by any participating servlet/ jsp of the application.