STRUTS-DATASOURCE

In this brief note on Struts DataSource, we will see how to use the declarative management of local DataSource in Struts. In the earlier tutorial (Jan 2005), we had used a helper class to access the database. The Action class does not do any business logic but simply passes on the query to the helper class and invokes the method of the helper class. This way, we are able to decouple the business logic from the struts action class. This is conducive to easy change-management, if required. In the simplest case, the helper bean itself may carry out the database operation and return the result to the action class. Or it may call a stateless-session ejb, which carries out the db operation. In a more advanced scenario, the session ejb may simply act as a facade for CMP or Hibernate. This is the recommended practice.

Strictly speaking, Struts does not deal with the business logic. It is more concerned with presentation and overall control of flow.

However, in some very simple cases, we can deviate from this norm and make use of the action class itself to carry out the db operation. It is for this purpose that there is provision for Data-Sources tags in the Struts-config.xml file. Normally, this would have been commented out. James Goodwill in his book 'Mastering Jakarta Struts' has made use of this method. It leaves out a very important step and leads to problems, if we strictly follow the book. The lesson tries to clarify this point.

If we are using this method, it will not be possible to use any helper class. The action class itself will carry out the db operation. The action class is actually based on Servlet API. Thus, we can skip the helper bean and even the result bean and just use two java classes (dbform and dbAction) and two JSP files (dbSubmit and dbOutput).

As usual, we begin by going to our project directory, which in our case is g:\examplestruts.

The package name is dbpack and so we create a subfolder under examplestruts, named 'dbpack'. We create the following four files there:
1) dbSubmit.jsp;
2) dbForm.java;
3) dbAction.java; and
4) dbOutput.jsp.

As the focus now is simply on the correct usage of DataSource tags, we will do away with any validation code and keep our example simple to follow. Refer code 1.

Code1

// g:\example-struts\dbpack\dbSubmit.jsp

<%@ taglib prefix="html" 
uri="/WEB-INF/struts-html.tld" %>

<%@ taglib prefix="bean" 
uri="/WEB-INF/struts-bean.tld" %>

<%@ taglib prefix="logic" 
uri="/WEB-INF/struts-logic.tld" %>



<html:html>
<body bgcolor=pink> 


<html:form action="/db"
name="dbForm"
type="dbpack.dbForm"> 

<html:text property="name"/> <br>
<html:text property="query"/> <br> 
<html:submit/>
</html:form>
</body>
</html:html>

===========================================


// g:\examplestruts\dbpack\dbForm.java

package dbpack;

import javax.servlet.http.*;
import org.apache.struts.action.*;

public class dbForm extends ActionForm
{

String name=null;
String query=null;

//----------------------------

public String getName()
{ return name; } 


public void setName(String s)
{ name=s; }

//-------------------------------
public String getQuery()
{ return query; } 


public void setQuery(String s)
{ query=s; }


public void reset
(ActionMapping mapping,
HttpServletRequest request)
{
name=null;
query=null;
}


public ActionErrors validate(ActionMapping mapping, HttpServletRequest request)
{
ActionErrors errors 
= new ActionErrors();

if( name.length()==0)
{
errors.add("name", new ActionError("errors.nullname"));


return errors;



}

========================================

// g:\examplestruts\dbpack\dbAction.java

package dbpack;

import javax.sql.*;

import java.sql.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class dbAction extends Action
{
public ActionForward execute
(ActionMapping mapping,
ActionForm form, 
HttpServletRequest request,
HttpServletResponse response)throws IOException,ServletException
{

dbForm dbform = (dbForm) form;

String a = dbform.getName();
String b = dbform.getQuery();

if(a.equals("ADMIN"))
{
String r = "ok";
try
{
ServletContext context=servlet.getServletContext();
DataSource datasource=
(DataSource)context.getAttribute
(Action.DATA_SOURCE_KEY);
Connection con=datasource.getConnection();

Statement st = con.createStatement();
ResultSet rs=st.executeQuery(b);

while(rs.next())
{
r=r+rs.getString(1)+"..."+rs.getString(2);
}
}
catch(Exception e1)
{ r=" "+e1; }


HttpSession session = request.getSession();
session.setAttribute("result",r);

return(mapping.findForward("success"));
}


else

return(mapping.findForward("failure")); 
}

}

}

=========================================


// g:\examplestruts\dbpack\dbOutput.jsp


<html>
<body bgcolor=lightgreen>

<%
String r =
(String) session.getAttribute("result");
out.println(r);
%>

</body>
</html>

========================================

After creating the four files, we set the path and classpath as follows:
set path=c:\windows\command;d:\jdk1.4.2\bin
-----------------
set classpath=g:\examplestruts;
c:\quick\struts.jar;
d:\tomcat41\common\lib\servlet.jar

(To be typed in a single line. We have placed struts.jar from the lib folder of struts distribution in C drive for easily memorization of the classpath).
==========================================
Compile dbForm and dbAction. Copy the two class files to: d:\tomcat41\webapps\dbapp\WEB-INF\classes\dbpack.

Next, copy dbSubmit.jsp and dbOutput.jsp to: d:\tomcat41\webapps\dbapp

Now we have to make the following entries in d:\tommcat41\webapps\dbapp\WEB-INF\struts-config.xml. See code 2.

Code 2

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">


<!--
-->
<struts-config>
<!--==== Data Source Configuration -->
<data-sources>
<data-source>
<set-property property="autoCommit" value="false"/>
<set-property property="description" value="Configuration"/>

<set-property property="driverClass" value="sun.jdbc.odbc.JdbcOdbcDriver"/>
<set-property property="maxCount" value="4"/>
<set-property property="minCount" value="2"/>
<set-property property="password" value=""/>
<set-property property="url" value="jdbc:odbc:dbdemo"/>
<set-property property="user" value=""/>
</data-source> 
</data-sources> 


<!-- ======================================== Form Bean Definitions -->

<form-beans>
<form-bean 
name="dbForm" type="dbpack.dbForm" />
</form-beans>
<!-- Global Exception Definitions -->
<global-exceptions>
<!-- sample exception handler
<exception
key="expired.password"
type="app.ExpiredPasswordException"
path="/changePassword.jsp"/>
end sample -->
</global-exceptions>

<!-- ===== Global Forward Definitions -->
<global-forwards>
<!-- Default forward to "Welcome" action -->
<!-- Demonstrates using index.jsp to forward -->
<forward
name="welcome"
path="/Welcome.do"/>
</global-forwards>

<!-- Action Mapping Definitions -->
<action-mappings>
<!-- Default "Welcome" action -->
<!-- Forwards to Welcome.jsp -->
<action
path="/Welcome"
type="org.apache.struts.actions.ForwardAction"
parameter="/pages/Welcome.jsp"/>

<action path="/db"
input="/dbSubmit.jsp"
name="dbForm"
type="dbpack.dbAction"
scope="session"
validate="true" >

<forward name="success" 
path="/dbOutput.jsp" />

<forward name="failure" 
path="/dbSubmit.jsp" />

</action>
</action-mappings>
</struts-config>

--
(Only relevant portions of the struts-config.xml file have been shown above. We must be very careful not to corrupt this file, especially the opening and closing tags for each section. We must not change the order in which the definitions occur.)

The most important step is to copy struts-legacy.jar from the lib folder of the jakarta-struts distribution into lib folder of tomcat41\webapps\dbapp\WEB-INF\lib folder.

Another important step is to copy jdbc2_0-stdext.jar from tomcat41\common\lib into webapps\dbapp\WEB-INF\lib.

Unless the above two steps are carried out, our code will not work. 

DataSource is a connection-pool. We use the Struts datasource just for testing. For production environment, we can use Tomcat's connection pool (Details of which have been given further down the article).

Now, we cd to d:\tomcat41\bin
set JAVA_HOME=D:\JDK1.4.2
>startup

In the browser, we type the URL as: 'http://localhost:8080/dbapp/dbSubmit.jsp (We should be careful about the 'case'. Tomcat is very much case-sensitive!).

We can now enter the user name as 'ADMIN', type the query in text2 and submit. We get the correct result.




Added on November 7, 2005 Comment

Comments

Post a comment

Your name:

Comment: