Вы находитесь на странице: 1из 113

Beginners Stuts tutorial

Sound knowledge of Struts Framework with hands-on experience in developing applications based on Struts , is a skill that is very much in demand now. Struts Framework was developed by Craig McLanahan in 2002 and subsequently handed over to Apache Jakarta project group. As Sun Micro Systems, works in close collaboration with Jakarta-Tomcat group, Struts has acquired semi-official status, though , it is not officially endorsed by JCP, yet. Craig McLanahan is also the architect of Tomcat4, which is the 'Reference implementation' of Servlet & JSP API by Sun. And the recently introduced JSF (Java Server Faces) also is the contribution of Craig McLanahan. What is more, Craig is also the Implementation Architect for Sun's Java Web Services Development Pack (JWSDP). That is sufficient enough list of credentials, to indicate the backing from Sun. There have been dissenting voices too, against Struts , partly because , it is somewhat difficult to learn and implement. And even an acknowledged spokesman & member of Struts Development Team and author of Struts Tutorial , Ted Husted, had to admit that the Struts naming of its classes leaves much to be desired. (for instance, instead of 'ActionServlet', it could have been called 'Controller' . Adding 'action' to everything in Struts like 'ActionForm', 'ActionServlet', 'Action', 'ActionForward' and even 'ActionErrors' etc tends to make the beginners grudge that' there is too much action here !' to their liking!). And it appears that, of late, some leading Architects feel that Struts is likely to give way to other Open-Source technologies from the same Apache group ,like Turbine and Torque( which are even more obscure and less documented).Judging by the number of latest job-advertisements calling for Struts skills, it is a bit difficult to concur with that perception. Struts appears to have become 'defacto' standard, like SAX, though one wishes that everything had been done within JCP ,so that developers will always be dealing with officially approved standards, rather than maverick standards, however good they might be. ( by the way, the correct term is 'struts' and not 'structs', as is mis-spelt often). ---------------------------------------------Here are some of the points listed by Author John Carnell ('Professional Struts Applications'Wrox press-2003) in favour of adopting Struts. To paraphrase....

**i)Senior developers and Architects in large software houses are extremely over-worked and the main job of in-house senior programmers is developing business-logic and not application-framework! ii) Struts framework was built by some of the finest developers in the Industry, and is opensourceand free. iii)It has been tested and debugged by hundreds of expert volunteers, thus giving it a high degree ofQuality Assurance. If a company tries to build a similar framework by itself, it will take thousands ofexpert man-hours and millions of dollars! ---------------------------------------------A good understanding and practical knowledge of Servlets, JSP, JavaBeans, Tag Library, MVC Architecture ,XML conifig files and Tomcat server , is required before a learner could even attempt understanding Struts.(It is for this reason, that we covered our own MVC implementation in the last edition). And it has to be supplemented with real practical work, to get it going. Without sufficient labexperience, a hundred things can go wrong! Just a bit of careless 'casing' and package names and we are confronted with stubborn compile errors. Remembering the fact that xml files also are 'case-conscious', would save us a lot of frustrating delay. And it is so easy to get lost in the paths and class paths of Java, especially with 'Struts'! Struts is a framework for building really complex Enterprise-level web applications. Note the emphasis on 'Enterprise-level'. Such applications are by necessity, multi-tier. Carnell makes a neat distinction between Enterprise-services like Transaction management, Resource pooling, Load Balancing and Security and Application-services like Data-validation , error-handling, Application navigation and screen-layout and personalization. While EJB takes care of Enterprise-services, the task of developing easily alterable and maintainableApplication-services in a really large web-application, could be a maddeningly

chaotic and tangled 'web'( literally) and such problems are NOT tackled by EJB. Enterpriselevel projects are developed by teams and unless there is a well-known and standard framework, the teams? work would fail to dovetail. The business-tier, Data-tier and presentationtier,all have to be co-ordinate seamlessly. This requires that all the teams and team-members know and practice a given standard. This point has been forcefully stressed in web-forums. As Struts has acquired wide awareness & acceptance, it fulfils this need admirably. Carnell lists the challenges of Web Development as : 1. Stateless nature of HTTP. 2. Limited User Interface of HTML. ( this is addressed effectively by WebForms in ASP.net and JSF). 3. 4. thousands of concurrent users huge number of inter-related navigation options.

Many companies have web-based applications where the number of screens that the user can navigate to, is in thousands! (SAP user-interface is composed of over 1,50,000 screens, reports and dialog boxes!--- and they were reported to be converting them into java-GUI .to provide platform independence.) (p.376 of Java Web Services by Hendricks..WROX). For all these reasons and more, Application-services are important and daunting to develop! -----------------In the true spirit of MVC, the Struts framework separates the View, Controller and Model. It does notconcern itself with the implementation details of business-logic and data-access tiers. ---------------------------That said, the very fact that it is an Enterprise-level framework, presumes( or it should) that we are using some form of EJB and some type of well-proven method of separation of Data-tier and business-logic tier. Though, Struts has provision for local data access, it is not advisable to use

that facility for Enterprise-level work, nor does it recommend it. At present, the recommended method is to use a stateless EJB for data access directly or as a facade for CMP or JDO. The advantage of CMP and JDO , is that details of the actual database product used , do not find a place in code. This enables us to use Object Databases too(JDO), as well as RDBMS. As Carnell rightly points out, the moment we speak of products like Oracle/SqlServer/MySql in our code , we get locked with vendor-specific details, which preclude changes. According to a number of authors, BMP seems to have been less of a success, if the yardstick is 'avoidance of SQL & vendor specific features of SQL.' and JDO is the recommended method. Oracle/PL-SQL if used in EJB code, ties our application , inextricably with Oracle .This is undesirable. The EJB3.0 version ,to be released shortly ,is said to favor JDO strongly.(BMP introduces SQL in java code while CMP & JDO adopt declarative management for database and query.). ( bmp persistence code need not necessarily be sql but in most cases, it is sql). Some authorities from BEA-WebLogic, are even, advocating the use of stateless-bean for simplicity and speed.(Java Server Programming by Allama Raju of WebLogic-WROX press), though it may involve sql in code itself. And a design based on such stateless-session bean can easily be exposed as XML-WebService by simple drop-in deployment in Axis.( see DeveloperIQ...April & May -2004). Thus, unless we are careful in implementing separation ,not merely between View , Control and Model, but going further in separation of Model into delegation, service-location, business logic , data access and data itself, even a Struts applications may become brittle.(We can easily imagine, how dangerous a brittle struts is, to a strut-walker!).In a well-designed system, each of these tiers should be pluggable (ie) any change in one tier should not affect other tiers.(ie) The layers should be de-coupled from each other, as much as possible. Standard Design Patterns, such as a. Business Delegate Pattern b. Service Locator Pattern c. Session Facade Pattern

are some of the patterns recommended in the 'model' region of Struts work!. In an earlier part of this J2EE tutorial , we had used a simple utility bean, for carrying out a specific function. That would be a case of 'Business Delegation'. If such a bean is used as a client for an EJB, typically, it would be an example of 'Service Locator'. And if that ejb happened to be a stateless bean connecting with a CMP , it would illustrate 'Facade Pattern'. Ideally, in an Enterprise application ,based on Struts, we should provide for all the above three patterns and implement them, though , in this lesson, we are using 'business delegation' alone, to keep the example simple. J2EE students are expected by the Industry, to have read two famous and essential books on Design Patterns. a. Design Patterns.: Elements of Reusable Object-Oriented Software" by -ERICH GAMMA

& three others ( known as GoF.'Gang of Four') b. CORE J2EE PATTERNS ( J2EE BLUEPRINTS) by SUN MICROSYSTEMS

(Some Struts authors are intent in showing that the Struts design follows some standard design patterns, while Carnell is concerned with suggestions for implementing Design patterns in the Model stages of Struts application. It is well to bear this in mind while reading books).

Developing Struts Application


If we are asked to give a very brief outline of Struts, we can enumerate the following points. I. All requests are passed through a controller servlet, known as Action-servlet. This is achieved by suitable 'url-mapping' in web.xml file. We have been doing 'URL-pattern' in Tomcat4,when using servlets. And in j2ee webserver like Tomcat, this facilitates 'centralized-declarative change management', by editing the concerned XML files, without touching the source or class files of the servlets or Struts Actions...

II.

All data submitted by user are sent to corresponding ActionForm. There are many actionforms but only one ActionServlet(because, it is the controller).

III.

The ActionServlet, examines the source of request and extracts the data from specified actionform and sends it to a specified instance of Action class.(as specified in strutsconfig.xml).

IV.

The action object carries out the business logic either directly or through helper classes , creates an instance of valuebean, populates this bean with data and sends the bean to the View JSP.( an instance of ActionForward).

V.

The important and distinctive feature of this arrangement is that the entire thing is done by'Declarative-Management'.(and hence ActionMapping)

VI.

Sometimes, the data submitted has to be validated and error messages , generated. (ActionErrors).

VII.

We use tags in input side and also for output view.(The input form also belongs to 'view' category in MVC.)( Struts-tags)

VIII.

The details about the ActionServlet and other servlets if any ,in our application are given inweb.xml

IX.

Details about various action classes,forms, action-forwards etc are given in strutsconfig.xml

--------------------------------------------It is now the right time ( & 'high time' at that!)to take up a simple and practical example. Our focus in this tutorial is actual implementation. In an illustration,we should not introduce more than one 'unfamiliar' tool or concept. Many tutorials, bring in tools like 'Ant', 'Eclipse' etc, which have their own learning curve! Our aim is to avoid such things and yet develop a useful lesson. -------------------------------------------We use the following six files, in this demo, in that sequence too. i. ii. iii. query.jsp QueryForm.java(derived from ActionForm) QueryAction.java(derived from Action)

iv. v. vi.

sqlbean.java ( a utility bean) resultbean.java ( a value bean) result.jsp

( besides the web.xml & struts-config.xml files) Where is the much-spoken-about ActionServlet? That is provided by Struts Framework itself.

We do not subclass it, except for advanced work. It remains unobtrusively in the background , silently supervising things. As Ted Husted says, many developers leave it alone. The truth is that , we need hardly set our eyes on web.xml in this demo..or on the source code of ActionServlet.

------------------------------------In our example, the starting point is ' query.jsp', which is invoked by the URL,'http://localhost:8080/sam/query.jsp'.The user fills up a form giving password and also an sql query.If the password is 'ADMINISTRATOR', the query is executed. Otherwise, the form is presented back to the user with the values already entered by him intact, so that he need not fill up the form again but needs to make only the required corrections. This is achieved by the FormBean. It is a Struts-specific class known as 'ActionForm'. We provide, getter and setter methods for each of the controls in the form. In our example, these are 'password' and 'query'. We are also using struts-tags named as 'html' tags. (for simplicity, we are using simple text rather than password control).Note the taglib directive. This is not JSTL but Struts Tag Library. We should note the following very carefully. The name of the form is given as 'queryForm' & action is 'Query'. (the case is extremely important!).There is automatic conversion of action from 'Query' to 'Query.do'. =================================

// query.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <html> <body bgcolor=yellow> This is query page <br> <html:form action="Query" name="queryForm" type="demo1.QueryForm"> Are you the Administrator?<br> Your password please!<br> <html:text property="password" /> <br> query <br> <html:text property="query" size="60" /> <br> <html:submit /> </html:form> </body> </html>

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

Usually, in normal html forms, the control has a 'name' attribute. But in html:text, it is known as 'property'. The corresponding formbean is given below.

========================================= All actions with extensions of '*.do', are automatically directed to the StrutsServlet(ie) ActionServlet. In the default web.xml file provided by the Struts application, the actionservlet is given 'URL-pattern' as '*.do'.( see web.xml)as given below.)

------------------------------(We need not type even a single line of web.xml. It is already available in the Struts application.) If the full file is printed here, it will only look forbidding. So, the relevant portion alone is shown here.ActionServlet configuration mentions the name of the servlet as 'action' and gives the fully qualified class-name of servlet. This is followed by init-parameters section.where the 'config' param is indicated as 'strutsconfig.xml in WEB-INF folder of the application.(shown in bold).This is followed by servletmapping, as already mentioned.Finally, we have tag-library descriptors for struts custom-tag-libs like 'html','logic', 'bean' etc. It is worth mentioning again that we do not have to type this file. It is equally important that we should not corrupt this file carelessly! It is best left alone. ------------------------------web.xml ===========================================
<?xml version="1.0" ....."?> ....... ....... ........ <!-- Action Servlet Configuration --> <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> ........ ........ ........

<!-- Standard Action Servlet Mapping -->

<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> ........ ........ ........

<!-- Struts Tag Library Descriptors -->

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

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

<taglib> <taglib-uri>/tags/struts-logic</taglib-uri>

<taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> .... ..... </web-app>

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

When the user submits the query.jsp, the formbean is automatically filled up with the values from the jsp-page and the flow goes to the ActionServlet. // QueryForm.java
package demo1; import javax.servlet.http.*; import org.apache.struts.action.*;

public class QueryForm extends ActionForm { String password =null; String query =null;

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

public String getPassword() { return password; }

public void setPassword(String b) { password=b; }

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

public String getQuery()

{return query;} public void setQuery(String a) {query=a;}

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

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

============================================== In the struts-config.xml file, we make two entries. One entry is for the instance of QueryForm bean and the other entry is for the instance of QueryAction class.As the entry for 'query action' makes a reference to 'query form', let us first see the details of the entry for 'query form'.The struts-config.xml file in WEB-INF folder is created by us and is the nerve-center of customized functionality. -----------------------------------------( this is the part dealing with the formbean)
<form-beans> <form-bean </formbeans> name="queryForm" type="demo1.QueryForm" />

-----------------------------------This means that our formbean is named 'queryForm' and is available in demo1 subfolder of classes folder.(WEB-INF\classes\demo1\QueryForm.class)

Carefully note the name of the bean. It is the same name given in the instance of QueryForm class, as it appears in QueryAction.java, given separately.(all the authors follow uniform pattern of naming the bean. The class name begins with capital letter and the instance begins with lowercase).Since all these are inter-dependent, unless we are careful, we can never even get started with invoking the form! ----------------------------------The next segment of mapping in struts-config.xml deals with the action mapping for the instance of Action class, (ie) QueryAction.
<action-mappings>

<action path="/Query"

type="demo1.QueryAction"

name="queryForm"

scope="session"

input="/query.jsp" > <forward name="success"

path="/result1.jsp" />

<forward name="failure"

path="/query.jsp" />

</action>

</action-mappings>

----------------------------------------------------It means that the request comes from the path "/Query.do", the corresponding action class is QueryAction class in demo1 subfolder of classes folder of webserver.The input is coming from query.jsp. Finally, it says that the matching form to be used is 'queryForm'.

Therefore, the action class extracts the properties from queryForm and does some validation according to our code. If the user had correctly entered the password as 'ADMINISTRATOR', processing goes on. (the code snippet from QueryAction.javais as given below). ------------------------------------------------QueryForm queryForm =(QueryForm) form;

String a = queryForm.getPassword();

String b = queryForm.getQuery();

if(a.equals("ADMINISTRATOR")) {

--------------------------------------------( Though, at first, the Struts code looks unfamiliar and frightening, on repeated reading and familiarity, it sounds like a song! Perhaps, the reason, why, users get addicted!) Otherwise, the returned ActionForward in the action class is "failure" and we have mapped this string to query.jsp (ie) going back to the opening form itself! We must admit that , this declarative manipulation , is a really clever and inspired innovation, in flow management. By

simply changing the entry in this struts-config file, the behaviour of the program can be easily changed. RequestDispatcher class instances are NOT explicitly mentioned anywhere, but the same effect is obtained. The full code for QueryAction has been given below.. ----------------------------------------// QueryAction.java
package demo1; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.struts.action.*;

public class QueryAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { QueryForm queryForm =(QueryForm) form; String a = queryForm.getPassword(); String b = queryForm.getQuery(); if(a.equals("ADMINISTRATOR")) { System.out.println (" now in QueryAction ========"); sqlbean bean1 = new sqlbean(); // business delegation System.out.println("bean1 ready"); String r= bean1.getresult(b);

System.out.println ("function invoked on bean1"); System.out.println("value is..."+r); resultbean mathew = new resultbean(); System.out.println("mathew bean created"); mathew.setValue(r); System.out.println ("value set for mathew"); String m = mathew.getValue(); System.out.println("verifying the value"); System.out.println(m); System.out.println ("--------ok -------------"); HttpSession session=request.getSession(); session.setAttribute("result",mathew); System.out.println("attribute for 'result' set as mathew"); resultbean bean=(resultbean)session.getAttribute("result"); System.out.println(bean.toString()); String v=bean.getValue(); System.out.println("verifying...."+v); System.out.println ("now sending mathew to result.jsp"); return (mapping.findForward("success")); }else{ return (mapping.findForward("failure")); } } }

====================================== If the password is correct, the processing proceeds to create an instance of 'sqlbean'.

This type of delegating the work to a functionbean is the recommended practice. We are advised not to let the Action class itself do any business-processing directly. Instead we create an instance of functionbean and just invoke a method on it by passing the parameter and

getting the return value. We illustrated the same method in the tutorial on MVC in the last edition too and so it should not be difficult to follow. // sqlbean.java
package demo1; import java.io.*; import java.sql.*;

public class sqlbean { public String getresult(String sql) { String r = ""; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); String url = "jdbc:odbc:dbdemo"; Connection connection=DriverManager.getConnection(url); Statement statement=connection.createStatement(); ResultSet rs = statement.executeQuery(sql); while(rs.next()) { String a = rs.getString(1); String b = rs.getString(2); r=r+a+"<br>"+b+"<br>"+"---------"+"<br>"; } } catch(Exception e1) {System.out.println(""+e1); } return r; } }

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

After getting the result from the utilitybean, the code creates an instance of valuebean known as 'resultbean'. This has just one property (ie) value. The name of this bean has been given as 'mathew'., just to make it standout from the crowd.And mathew's value is set as 'r'. -------------------------------------------------------------// resultbean.java
package demo1; public class resultbean { String value; public resultbean(){ value=" "; }

public String getValue(){ return value; } public void setValue(String v){ value=v; } }

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

We now create a session context( though, some authors frown upon it ), and set the sessionattribute of "result" as mathew! Thus, we are passing the bean itself to the destination (ie) result.jsp In result.jsp, we have used just jsp-tags like <jsp:useBean....> and <jsp:getProperty..> Carefully note the syntax. especially the 'id' and 'name'. The 'id' is NOT 'mathew' but 'result'!. We just extract the value and automatically display it.Thus, we have met the stringent

requirement that our view pages should be absolutely free from 'scriptlets'.

-----------------------------------------// result.jsp
<html> <body bgcolor=orange> <jsp:useBean id="result" scope="session" class="demo1.resultbean" />

<jsp:getProperty name="result" property="value" /> <br> ok here </body> </html>

Testing Struts Application


It will be noticed that there are a lot of 'system.out.println's in the action class code.Intentionally so! The step by step progress gets printed in the Tomcat console and is very instructive. When trouble occurs, it aids in diagnosis greatly.It also gives us a clear understanding.

------------------------------------------

But, understanding the code is one thing ( and the easier thing at that) and actually executing the program ,is quite a different thing altogether! We must do each step with maximum care, to avoid a lot of problems.

-----------------------------------------We begin by creating a folder( say)

g:\examplestruts>

Our proposed package name is demo1;

So create a subfolder named 'demo1'.

cd to g:\examplestruts\demo1

--------------------------Create the following six files in demo1 folder. i. ii. iii. iv. v. vi. query.jsp QueryForm.java QueryAction.java sqlbean.java resultbean.java result.jsp

----------------------------------We cannot compile QueryForm.java & QueryAction.java , unless we first install Struts in our system. ---------------------------------

How do we instal Struts in our system?

----------------steps.

------------1. transfer jakarta-struts1.1 zip file from DeveloperIQ CD to g:drive.

2. unzip it into c:\unzipped. 3. It got unzipped as jakarta-struts1.1 folder. ---------------------------------------------We get three folders and 3 files

4. The 3 folders are a) contrib b) lib c) webapps

============ The 3 files are: 5. a) readme.txt b) license.txt c) instal.txt ----------------------------------------------6. open webapps folder.

7. we will find the following war files there.( web-application-archives) a )struts-blank b)struts-documentation c) struts-example d) struts-exercise-taglib e) struts-template f) struts-upload g) struts-validator

----------------------------------------------

8. copy struts-blank.war into:

g:\tomcat41\webapps folder. ----------------------------------------------

9. In a DOS window, cd to g:\tomcat41\bin 10. >set JAVA_HOME=D:\JDK1.4 11. startup

--------------------------------------------

12. tomcat server gets started . 13. Now in another dos window , check up that struts-blank.war has automatically expanded by the server and we get a folder named struts-blank. 14. If you expand struts-blank folder, there are 3 subfolders there. i) META-INF ii) WEB-INF iii) pages There is also an index.jsp

-----------------------------------------------

15. start the browser and type the url as : http://localhost:8080/struts-blank/index.jsp

----------------------------------------------

16. You will get the corresponding display as follows: Welcome!

To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent), and let

your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container, and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.

-----------------------------------------------

Thus, we have correctly installed struts in our tomcat server.

========================================== Inside the WEB-INF folder, we have the following subfolders and files. sub-folders i)classes ii) lib iii) src ----------------------files =============== tld files ( 6 files) =============== 1) struts-bean.tld 2) struts-html.tld 3) struts-logic.tld 4) struts-template.tld 5) struts-tiles.tld 6) struts-nested.tld

-------------------

xml files ( 5 files).

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

i) web.xml ii) struts-config.xml iii) tiles-defs.xml iv) validation.xml v) validator-rules.xml

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

There are a number of jar files available in lib folder.

i) commons-beanutils.jar ii) commons-collections.jar iii) commons-digester.jar iv) commons-fileupload.jar v) commons-lang.jar vi) commons-logging.jar vii) commons-validator.jar viii) jakarta-oro.jar ix) struts.jar

-------------------------------------

All this is just for information.

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

When we want to build our own application, we first copy struts-blank folder in the webapps folder of tomcat & Rename the folder .(say) sam. And restart the Tomcat server. struts.jar was copied to c:\quick folder for easily remembering the classpath.

============================================== Now, we are ready to begin compiling. We are now in g:\examplestruts\demo1 >set path=c:\windows\command;d:\jdk1.4\bin >set classpath=g:\examplestruts;c:\quick\struts.jar;d:\tomcat41\common\lib\servlet.jar ..demo1>javac QueryForm.java ..demo1>javac sqlbean.java ..demo1>javac resultbean.java ..demo1>javac QueryAction.java ( if we compile the files one after the other, in this sequence, we will be able to compile easily. After compiling, copy all the class files in this folder to:

g:\tomcat41\webapps\sam\WEB-INF\classes\demo1 copy query.jsp & result.jsp to: 'g:\tomcat41\webapps\sam' now in another dos window, cd to: g:\tomcat41\webapps\ sam\WEB-INF\struts-config.xml

edit the struts-config.xml as follows:

==========================================
<?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> <form-beans> <form-bean

name="query path ty scope=&q

name="que path="/Query"

<action

type="demo1.QueryAction name="queryForm" scope="session"

input="/query.jsp" <forward name="success" path="/result.jsp" /> <forward name="failure" path="/query.jsp" />sp;</struts-config> </struts-config>

After all these steps, restart the Tomcat server, so that the settings become effective. Type the URL in browser as:

'http://localhost:8080/sam/query.jsp'

You should get a form with orange background, etc. If we type the password as 'ADMINISTRATOR' and the sql as 'select * from table1', we will get the query result. ( Ofcourse, the example presumes the usual creation of a simple Access database named 'dbdemo' with just table1 having two fields ( name, place) and registering it in ODBC. If the password is wrong, the page appears to be not responding just showing whatever we typed. So, our adventure with Struts has had a happy ending.

If we get, this far, we can and must build up further by in-depth study of books.& articles. In the forthcoming installments, we will see advanced Struts topics like : DynaForm Validator Framework Tiles RequestProcessor Scaffold Struts-Tags ------------------------

This tutorial cannot be a substitute for hundreds of articles and dozens of books on Struts .It is but a simple introduction . Respectful Acknowledgements to: 1. 'Struts your Applications' by Piyush SriVasthava ( DeveloperIQ---November-2002) 2. 'Understanding Struts Framework' by Manoj Kothale ( DeveloperIQ.....August-2003) ==================================

Suggested Reading: 1. Struts in Action . by Ted Husted ( Manning press/ DreamTech publication) 2. Mastering Jakarata Struts by James Goodwill (Wiley/DreamTexh) 3. Professional Struts Applications by John Carnell ( Wrox ) ==============================================

Struts Validator Framework - lab oriented lesson


Struts & validation Validation is an essential feature in any web-application and to make it easier, the Validation Framework has been bundled with Struts1.1 version. In this hands-on tutorial , the author explains how we can use this readymade framework.In this first part, a simple struts demo with non-framework based validation , is developed. We had seen an introduction to Struts in Jan-2005 issue of DeveloperIQ. We will now have a brief and practical recapitulation of a typical Struts-based application and then proceed to illustrate the use of Validator framework, with a lab-oriented lesson. Since its introduction in 2001, Struts has been widely adopted and despite the emergence of more 'official' JSF last year (2004), Struts is still holding its ground and only recently, companies seem to be exploring JSF.As a large number of applications have already been built using Struts, it may be that only a combination of Struts and JSF, rather than pure JSF, will be adopted by developers and software houses, right now.It may take some time before JSF completely replaces Struts. Java webserver technology has progressed through Servlets, plain JSP, JSP using beans, Taglibrary, MVC, JSTL,STRUTS and JSF. As Struts involves every one of the preceding technologies, a good knowledge of Struts is equivalent to competence in J2EE Web-Tier.Thus, Struts is still very important for developers and students. Most learners find getting started with Struts , very difficult and confusing, partly because of the books and articles in circulation. The exception is the tutorial by Marty Hall ( 'www.coreservlets.com' & 'www.moreservlets.com'), because, rather than beginning with a lengthy theoretical treatment of Struts, it gives more importance to hands-on procedure.Another book is 'Mastering Jakarta Struts' by James Goodwill with some modifications. We will adopt the same method .

HOW TO INSTAL STRUTS? Unzip Jakarta-Struts1.1 into C:\unzipped. We get a folder by the same name.When we expand the folder, we find a folder named 'webapps'. Expand this folder and we find a number of '*.war' files ( web-archive files).One such file is 'struts-blank.war'. We copy struts-blank.war and paste it in 'e:\tomcat41\webapps' folder. We are using d:\JDK1.4.2 and we cd to e:\tomcat41\bin and set JAVA_HOME=D:\JDK1.4.2 and then startup This will automatically expand the war file to create a folder in e:\tomcat41\webapps named as 'struts-blank'. To shutdown the Tomcat server, we give the command, e:\tomcat41\bin>shutdown. After shutting down the tomcat server, we rename the struts-blank folder as (say) modelapp.If we open modelapp folder, we will find the standard j2ee directory structure and all the necessary framework files in-place.This is the quickest and best method to develop a strutsbased application. We can cd to e:\tomcat41\webapps\modelapp\WEB-INF\classes folder.We will find a 'resources' folder already there.We should create a subfolder under 'classes' folder and name it as 'modelpack' (for package). With these preliminaries over, we can turn our attention to the files in our modelapp. Any typical struts-based application, will have the following six files . 1) modelSubmit.jsp 2) modelForm.java

3) modelHelper.java 4) modelResult.java 5) modelAction.java 6) modelOutput.jsp Our project folder is g:\mydir. cd to g:\mydir and md modelpack. (this is the package name ). cd to modelpack. We create all the above six files in this folder. We have to set path & classpath for this command window as follows: >set path=c:\windows\command; d:\jdk1.4.2\bin >set classpath=g:\mydir; c:\quick\struts.jar; e:\tomcat41\common\lib\servlet.jar ( we have copied struts.jar from modelapp\WEB-INF\lib folder into c:\quick for ease.) modelSubmit.jsp is the opening page invoked by the user. When he submits this page ,the ActionServlet(controller) is invoked. It looks into the struts-config.xml file where action-mapping has been mentioned by us. This mapping specifies that if the path began with '/model', the controller should collect the data from modelSubmit.jsp, populate the modelForm bean with these data and then pass the bean to modelAction class. It also says that if any validation logic succeeds, the forward path should be to modelOutput.jsp("success") and otherwise, it should be modelSubmit.jsp ("failure"). The modelAction class collects the data from modelForm instance and invokes the modelHelper to carry out the business-logic.

The helper carries out the job and returns the value to the modelAction. The modelAction then creates an instance of modelResult ( a value bean) and sets its value. It then creates a session context and passes this bean as its 'result' attribute. Finally, the modelOutput.jsp collects this result and displays it without using any scriptlet. Therefore, the ActionServlet simply controls the flow depending on the settings entered by us in the struts-config.xml file .The Action class does not do anything except invoking the helper and setting the value for result bean. The business logic , is preferably executed by a helper class ( a function bean).So, we have effectively implemented MVC pattern where M,(model..helper) V(view ..the jsp) and C(controller..Action servlet) do their respective jobs. The entire thing allows Declarative change management through the struts-config.xml file. For smooth work, it is advisable not to tamper with the web.xml file. We will now create the required files, as follows, in the correct order. We are now in g:\mydir\modelpack folder.
set path=c:\windows\command;

d:\jdk1.4.2\bin set classpath=g:\mydir;


c:\quick\struts.jar;

e:\tomcat41\common\lib\servlet.jar

---------------------------------We are using Struts-specific tag library. The Tag-library-descriptor files (tld) are already in place in our WEB-INF folder. So, no special steps are necessary. If we had been following the earlier tutorial on Struts, we need give particular attention to <html:errors /> tag now.

This is for displaying any error messages. There are two fields, namely, 'name' and 'code'. ---------------------------------// g:\mydir\modelpack\modelSubmit.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:errors /> <html:form action="/model" name="modelForm" type="modelpack.modelForm"> <html:text property="name"/> <br> <html:text property="code"/> <br> <html:submit/> </html:form> </body> </html:html> =========================================== After creating this input file, we have to create a javabean, in our case, named as 'modelForm.java'. This is an attribute bean and sometimes known as formbean.Following the standard javabean naming convention, we provide setter and getter methods for all the fields in the modelSubmit.jsp. However, this is not just the usual javabean , but Struts-specific bean.For this reason, we have to derive it from Strut's ActionForm class.( Shortly , when we use the validator framework, we

will be deriving our modelForm not from ActionForm but from ValidatorForm. This may be kept in mind). In order to derive it from Struts ActionForm, we have to import 'org.apache.struts.action.*'. Moreover, all the Struts classes are based on Servlet API and we need to import 'javax.servlet.http.*' also. Special attention can be given to the validate method.( when we base our modelForm on ValidatorForm, we won't be providing this method).We have written some rudimentary validation check to see if the field is empty and if so an error instance is created with the 'key' (errors.nullname). Similarly (errors.nullcode). There is a file known as 'Application.properties' in 'WEBINF\classes\resources' and at the end of that file we will add the following lines. ===================================== errors.nullname=<li> ENTER YOUR NAME</li> errors.nullcode=<li>ENTER YOUR CODE</li> errors.nomatch=<li>DOES NOT MATCH</li> Therefore, we will get the specified error messages. ******************************************* //g:\mydir\modelpack\modelForm.java
package modelpack;

import javax.servlet.http.*; import org.apache.struts.action.*; public class modelForm extends ActionForm

{ String String name code = = null; null;

public String getName() { return } public void setName(String { name=s; } //------------------------------public String getCode() { return } public void setCode(String { code=s; } public request) { name code } public ActionErrors validate (ActionMapping request) = = null; null; void reset (ActionMapping mapping, HttpServletRequest s) code; s) name;

mapping, HttpServletRequest { ActionErrors errors

= new ActionErrors();

if( name.length()==0)

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

=========================================== The modelAction class is derived from Action class of Struts. This is not to be confused with the ActionServlet class of the Struts framework. The ActionServlet is the controller and works in the background. It simply collects data from modelSubmit.jsp , populates the modelForm with those values and then sends the form to the modelAction. Sometimes, in simple demo applications, the action class itself may carry out the business logic and directly send the result to the output.jsp. But, the preferred method is to use a function bean ( a helper class) such as modelHelper. This enables 'de-coupling' of various stages. The modelAction class collects the data from the modelform bean. Just for a very simple illustration, we compare the name and code and if they match, the helper class bean is asked to 'inform' and the resulting string returned by this helper bean is set as value for the valuebean instance 'tom'. The 'tom' bean is set as the session-attribute "result".With this note, we can easily understand the code, given below. As the 'modelAction' class makes use of 'modelHelper' and 'modelResult' beans, they are given ahead of modelAction class.

------------------------------------// g:\mydir\modelpack\modelHelper.java
package modelpack;

public class modelHelper { public { return "Correct } } Code!...."; String inform()

------------------------------------// g:\mydir\modelpack\modelResult.java
package modelpack;

public class modelResult { String value;

public {

modelResult()

value = " "; } public String { return } public void { value = v; setValue(String v) value; getValue()

} }

******************************************* // g:\mydir\modelpack\modelAction.java
package modelpack;

import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.struts.action.*; public class modelAction extends Action { public ActionForward execute mapping, form, request, response)

(ActionMapping ActionForm HttpServletRequest HttpServletResponse

throws IOException, ServletException { modelForm String String modelform = (modelForm) form; a = modelform.getName(); b = modelform.getCode();

if(a.equals(b)) { modelHelper helper = new modelHelper(); String r = helper.inform();

modelResult

tom

= new modelResult();

tom.setValue(r);

HttpSession session = request.getSession(); session.setAttribute("result", tom); return(mapping.findForward("success")); } else { ActionErrors errors = new ActionErrors(); errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("errors.nomatch")); saveErrors(request,errors); return(mapping.findForward("failure")); } } }

======================================= Finally, we takeup the modelOutput.jsp. which simply collects the data from the bean and display it. --------------------------------------// g:\mydir\modelpack\modelOutput.jsp ******************************************* ( We can also write the modelOutput.jsp as given below. In this method, we are using Strutsspecific tags , whereas in the previous method, we used JSP tags only). -------------------------------------// g:\\mydir\modelpack\modelOutput.jsp // ( second version)

<%@ 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=yellow> <bean:write name="result" property="value" /> </body> </html:html> ====================================== After creating all the above files, compile the four java classes >javac *.java -------------------------------------If we had followed the steps carefully, we can compile without any difficulty. Next, we copy the four class files to: 'e:\tomcat41\webapps\modelapp\WEB-INF\classes\modelpack' folder. We copy modelSubmit.jsp and modelOutput.jsp to: 'e:\tomcat41\webapps\modelapp' folder. Are we ready to test our program? NOT YET!

We have to make entries in : a) struts-config.xml & b) application.properties file. The required entries have been given below.A -----------------------------------//e:\tomcat41\webapps\modelapp\web-inf\struts-config.xml

<struts-config> <!-- ======== Form Bean Definitions --> <form-beans> <!-- sample end sample --> <form-bean name="modelForm" type="modelpack.modelForm"/> </form-beans> <action

path = "/model"

type = "modelpack.modelAction"

name = "modelForm"

input = "/modelSubmit.jsp"

scope = ?session?

validate="true" >

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

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

</action>

</action-mappings>

/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/>

<!-- ================================ Message Resources Definitions --> ****************************************** // e:\tomcat41\webapps\modelapp\web-inf\classes\resources\ application.properties


# -- standard errors -# -- validator -errors.invalid={0} is invalid. errors.maxlength={0} can not be greater than {1} characters.

# -- myerror-messages -errors.nullname=<li> ENTER YOUR NAME</li> errors.nullcode=<li>ENTER YOUR CODE</li> errors.nomatch=<li>DOES NOT MATCH</li>

******************************************* We are now ready to test our application. First, start the tomcat4 server e:\tomcat41\bin>SET JAVA_HOME=D:\JDK1.4.2 e:\tomcat41\bin>startup This will start the tomcat server. Now, we type the Url as : 'http://localhost:8080/modelapp/modelSubmit.jsp' We will get the entry form with two fields. If we click the submit button, without entering name or code, we are taken back to modelSubmit.jsp with the message 'ENTER YOUR NAME' /'ENTER YOUR CODE'. If we enter SAM for name and TOM for code, we get the error message 'DOES NOT MATCH'.but if same values are given for name and code, we get the output jsp which says that 'code is correct!'. Thus, we have developed a simple struts demo with validation. With this background, it is now very easy to understand the next example which makes use of Validator framework. This, we take up in part-2.

USING THE VALIDATOR FRAMEWORK


Validator framework requires two XML files, namely, 1. alidator-rules.xml & 2. validation.xml

( we are using struts1.1)

These files are already available in WEB-INF folder , along with web.xml and strutsconfig.xml. So, no special installation is necessary, to use the Validator framework. The validator-rules.xml file provides the rules for the ready-made validations available in the framework. The validation.xml file is meant for specifying our requirements. It is advisable not to tamper with the validator-rules.xml( just as we need not meddle with web.xml file). The Validator framework provides ready-made facility for the following: 1. RequiredField validation

2. Regular-Expression validation(mask) 3. email validation 4. credit-card validation 5. date validation 6. minvalue validation

7. maxvalue validation 8. range validation 9. byte, short, int, long validation 10. float, double validation. ---------------------------------When we use the Validator Framework, we get the bonus of client-side Javascript validation also,automatically, with messagebox and all! Otherwise, we will have to write very laborious and clumsy javascript functions for routine validations. Client-side validation, though not very reliable, saves the round-trip time and so is better appreciated by clients. However, the framework gives server-side validation always. ------------------------------Let us now take up a comprehensive demo for illustration. We shall name this as 'validsapp'! The example will be easy to follow, since we have already covered the usual pattern in our previous lesson.

There are just a few changes required. i. ii. iii. The validsForm.java is derived from ValidatorForm and not from ActionForm. Therefore we have to import ' 'org.apache.struts.validator.*;'. Since the framework takes care of form-validation, as per the requirements specified by us in thevalidation.xml file, there is no need to provide validate method in the validsForm class file. iv. v. We have to make suitable entries in 'validation.xml' file available in WEB-INF\ folder. We should not forget to make entries for form-bean and action-mapping in strutsconfig.xmlfile. vi. Finally, we have to add a few key-value pairs for the error messages in application.propertiesfile in WEB-INF\classes\resources folder, as before. Apart from these, the other files follow the usual pattern.As the focus of this second part of the tutorial is on the method of using the Validator framework, let us skip the helperbean and resultbean. Thus, this demo requires just two jsp files, 1. validsSubmit.jsp & 2. validsOutput.jsp and two java classes, 1. validsForm.java & 2. validsAction.java ----- ----------------------As before, we rename 'struts-blank' as 'validsapp' and create 'validspack' folder in validsapp\WEB-INF\classes\' folder.

Readers may refer to part-1 for exact procedure.

We now create a folder 'validspack' in

'g:\mydir'. cd to g:\mydir\validspack'

set path=c:\windows\command; d:\jdk1.4.2\bin set classpath=g:\mydir; c:\quick\struts; e:\tomcat41\common\lib\servlet.jar

--------------------------

We create the following files in : 'g:\mydir\validspack' folder. ------------------------1. validsSubmit.jsp 2. validsForm.java 3. validsAction.java 4. validsOutput.jsp ------------------------------------------

The files have been given below, in that order. Carefully note that the two following lines in validsSubmit.jsp:

onsubmit="return validateValidsForm(this);"> <html:javascript formName="validsForm" />

(The above two lines enable the javascript validation in client-side, when we use the Validator framework)

*************************************** // code-1

// g:\mydir\validspack\validsSubmit.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:errors /> <html:form action="/valids" name="validsForm" type="validspack.validsForm" onsubmit="return validateValidsForm(this);"> NAME: <html:text property="name"/> <br> PASSWORD:<html:text property="password"/> <br> MAIL-ID <html:text property="mail_id" /> <br> DATE: <html:text property="date"/> <br> PINCODE:<html:text property="pincode"/> <br> <html:submit/> </html:form> <html:javascript formName="validsForm" /> </body> </html:html>

// code-2

// g:\mydir\validspack\validsForm.java
package validspack; import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.validator.*;

public class validsForm extends ValidatorForm { String name = null; String password = null; String mail_id = null; String date = null; String pincode = null; public String getName() { return name; } public void setName(String a) { name=a; }

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

public String getPassword() { return password; } public void setPassword(String b) { password=b; }

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

public String getMail_id()

{ return mail_id; } public void setMail_id(String c) { mail_id=c; }

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

public String getDate() { return date; } public void setDate(String d) { date=d; }

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

public String getPincode() { return pincode; } public void setPincode(String e) { pincode=e; }

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

public void reset(ActionMapping mapping, HttpServletRequest request) { name = null; password = null; mail_id = null; date = null; pincode = null; } }

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

// code-3

// g:\mydir\validspack\validsAction.java
package validspack; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.struts.action.*;

public class validsAction extends Action { public ActionForward execute (ActionMapping mapping, ActionForm form, HttpServletResponse response)

HttpServletRequest request,

throws IOException, ServletException { validsForm validsform =(validsForm) form; String s1 = validsform.getName(); String s2 = validsform.getPassword(); String s3 = validsform.getMail_id(); String s4 = validsform.getDate(); String s5 = validsform.getPincode(); if(s1.length()!=0) { String r =s1+"<br>"+ s2+"<br>"+s3+"<br>"+ s4+"<br>"+s5; HttpSession session = request.getSession();

session.setAttribute("result",r); return(mapping.findForward("success")); } else { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("errors.global")); saveErrors(request,errors); return(mapping.findForward("failure")); } } }

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

// code-4

// g:\mydir\validspack\validsOutput.jsp
<html> <body bgcolor=lightgreen> <% String r= (String)session.getAttribute("result");

out.println(r); %> </body> </html>

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

We are now ready to compile and deploy.

We are in g:\mydir\validspack

Checkup the path.

( c:\windows\command;d:\jdk1.4.2\bin) Checkup classpath

(g:\mydir;c:\quick\struts.jar; e:\tomcat41\common\lib\servlet.jar) ------------------------------

>javac *.java

We now copy validsForm.class and validsAction.class to:

'e:\tomcat41\webapps\validsapp\WEB-INF\classes\validpack' folder.

We copy validsSubmit.jsp and validsOutput.jsp to :

'e:\tomcat41\webapps\validsapp' folder. ------------------------We have to make the following entries in:

e:\tomcat41\weebapps\validsapp\WEB-INF\struts-config.xml file.

******************************************* // code-5-- end sample -->


<form-bean name="validsForm" type="validspack.validsForm" > </form-bean> </form-beans> <!------ end samples -->

<action path="/valids" input="/validsSubmit.jsp" name="validsForm" type="validspack.validsAction" scope="session" validate="true"> <forward name="success" path="/validsOutput.jsp" /> <forward name="failure" path="/validsSubmit.jsp" /> </action> </action-mappings>

*****************************************

As these are exactly the same pattern as in part-1, we can skip detailed explanation. and devote more attention to the crucial entries in validation.xml in :

'e:\tomcat41\webapps\validsapp\WEB-INF' folder

--// code-6 end example form -->


<form name="validsForm"> <field property="name" depends="required"> <arg0 key="validsForm.name" /> </field> <field property="password" depends="required,minlength,mask"> <arg0 key="validsForm.password" /> <var> <var-name>minlength</var-name> <var-value>6</var-value> </var> <var> <var-name>mask</var-name>

<var-value>^[0-9a-zA-Z]*$</var-value> </var> </field> <field property="mail_id" depends="required,email"> <arg0 key="validsForm.mail_id" /> </field> <field property="date" depends="required,date"> <arg0 key="validsForm.date" /> <var> <var-name>datePattern</var-name> <var-value>MM/dd/yyyy</var-value> </var> </field> <field property="pincode" depends="required,maxlength,mask"> <arg0 key="allvalidsForm.pincode" /> <var> <var-name>maxlength</var-name> <var-value>6</var-value> </var> <var> <var-name>mask</var-name> <var-value>^\d{5}\d*$</var-value> </var> </field> </form> </formset> </form-validation>

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

And finally, we add the following lines in:

e:\tomcat41\webapps\validsapp\WEB-INF\classes\

resources\application.properties.

*******************************************

// code-7
# -- standard errors --

errors.header=<UL>

errors.prefix=<LI>

errors.suffix=</LI>

errors.footer=</UL>

# -- validator -errors.invalid={0} is invalid. errors.maxlength=pincode can not be greater than 6 characters. errors.minlength=password can not be less than 6 characters. errors.range={0} is not in the range {1} through {2}. errors.required={0} is required. errors.byte={0} must be an byte. errors.date={0} is not a date. errors.double={0} must be an double. errors.float={0} must be an float. errors.integer={0} must be an integer. errors.long={0} must be an long.

errors.short={0} must be an short. errors.creditcard={0} is not a valid credit card number. errors.email={0} is an invalid e-mail address.

# -- other --

errors.cancel=Operation cancelled. errors.detail={0} errors.general=The process did not complete. Details should follow. errors.token=Request could not be completed. Operation is not in sequence.

# -- welcome --

welcome.title=Struts Blank Application welcome.heading=Welcome!

welcome.message=To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent), and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container, and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.) #----------------------------------------errors.global="NO NAME HAS BEEN GIVEN" validsForm.name=NAME validsForm.password=PASSWORD validsForm.mail_id=MAIL_ID validsForm.date=DATE validsForm.pincode=PINCODE

************************************************

We shall first run the demo and then have some explanation for the entries in the validation.xml file. We open another command window and cd to: e:\tomcat41\bin Then set JAVA_HOME=D:\JDK1.4.2 >startup ----------------------Start the browser and type the Url as : 'http://localhost:8080/validsapp/validsSubmit.jsp' If all goes well, we will get the submit form. ( If we get a lot of javascript along with the controls, it means that we have made some mistakes in the xml files.) If we submit the form, without making any entries, we will get a messagebox as shown. This is the client-side Required-Field validation.It is self-explanatory. For the password, we have specified three conditions. namely, it should not be blank, it should not have less than 6 characters and finally we have given a regular expression which means that the characters can be lowercase or uppercase or numearals ( ie) no special characters are allowed. We can test for this error one by one after putting some letters in all the fields, because, specific validation is done only after the required field condition in all the controls is met. The error condition for wrong mail-id can be easily simulated by giving it as tom @ dom.com ( we are not supposed to provide space either before or after @ ). Nor can we use capital letters.see shot 4. The date pattern has been given as 'mm/dd/yyyy'. So, if we type the date as '31/01/2005', we will get error message. Finally, for pin-code, we have provided a regular expression as well as maxlength condition.

If all these are apparently correct,we can provide further validation code in action class which is known as 'action-validation'.If due to some reason, there is no client-side java-script validation, we get server-side validation messages for all the above conditions.( see screen shots given here). (Sometimes, the results of client-side validation may differ from Server-side validation. As Husted points out, it may be confusing but that is how things stand now.) ============================================== Reference books:

----------------------------------1. STRUTS IN ACTION by TED HUSTED & OTHERS ( the chapter on Validator framework ..chapter-12... has been co-authored by David Winterfeldt, the creator of the Validatorframework and so is authoritative). ( Manning / DreamTech) 2. Programming Jakarata Struts by Chuck Cavaness (OReilly) -chapter-11 3. STRUTS SURVIVAL GUIDE by Srikanth Shenoy ********************************************

How To Develop Login Form In Struts


Apache Struts is an open-source framework for developing J2EE web applications. It uses and extends the Java Servlet API to encourage developers to adopt an MVC architecture. It was originally created by Craig McClanahan and donated to the Apache Foundation in May, 2000.
This article will explain how to develop login form in struts. Struts adopts an MVC architecture.

Model Part of Login form Example:


Model is basically data of you application. A collection of Java beans and other helper classes that you use for your application In Login Form Example ,the following classes will be used-1. Action class 2. ActionForm class

Action Class: The action class is the link between the Struts framework and your business application logic. The purpose of Action Class is to translate the HttpServletRequest to the business logic.
In this example our Action class is LoginAction.java. this Action class only forwards the login.jsp. Our Action class returns the ActionForward called "loginAction", which is defined in the struts-config.xml file . Here is code of our Action Class: LoginAction.java

package roseindia.web.struts.action; /** * @Author Sushil Pal * @Web http://www.roseindia.net * @Email pal_sushil@hotmail.com * @Copyright RoseIndia.net */ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class LoginAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception{ LoginForm loginform = (LoginForm) form; if (loginform.getUsername().equalsIgnoreCase("username") && loginform.getPassword().equals("password")) { // we are in return mapping.findForward("success"); } else { // not allowed return mapping.findForward("failure"); } } }
Action Class process the specified HTTP request, and create the corresponding HTTP response and Return an ActionForward instance describing where and how control should be forwarded. In our login action class if username field value will be 'username' and password will be 'password' then the mapping will forward to success.jsp otherwise to failure.jsp. ActionForm Class: An ActionForm is a JavaBean that extends org.apache.struts.action.ActionForm. ActionForm maintains the session state for web application and the ActionForm object is automatically populated on the server side with data entered from a form on the client side. It must have setters and getters for all the form fields.The ActionForm class is pre-populated with form data when the form is submitted. In this example our ActionForm class is LoginForm.java. Here is code of our ActionForm Class: LoginForm.java

package roseindia.web.struts.action;

/** * @Author Sushil Pal * @Web http://www.roseindia.net * @Email pal_sushil@hotmail.com * @Copyright RoseIndia.net */
/** * Form bean for the Login Entry Screen. * */

import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.*; public class LoginForm extends ActionForm { private String action="add"; private String username=null; private String password=null; private String usertype=null; public void setAction(String action){ this.action=action; } public String getAction(){ return this.action; } public void setUsername(String username){ this.username=username; } public String getUsername(){ return this.username; } public void setPassword(String password){ this.password=password; } public String getPassword(){ return this.password; } public void setUsertype(String usertype){

this.usertype=usertype; } public String getUsertype(){ return this.usertype; } public void reset(ActionMapping mapping, HttpServletRequest request){ this.username=null; this.password=null; this.usertype=null; this.action="add"; } }

View Part of Login form Example:


The View portion of a web application is most often constructed using JavaServer Pages (JSP) technology. JSP pages can contain static HTML (or XML),plus the ability to insert dynamic content based on the interpretation of special action tags. In this example our JSP pages are login.jsp, success.jsp, failure.jsp. Here is code of our JSP pages: login.jsp

<%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <html:html locale="true"> <head> <title><bean:message key="welcome.title"/></title> <html:base/> <script language="javascript"> function validate(objForm){ if(objForm.username.value.length==0){ alert("Please enter UserID!"); objForm.username.focus(); return false;

} if(objForm.password.value.length==0){ alert("Please enter Password!"); objForm.password.focus(); return false; } if(objForm.usertype.selectedIndex == 0 ){ alert("Please Select User Type!"); objForm.usertype.focus(); return false; } return true; } </script> </head> <body bgcolor="white">

<html:form action="/login" method="post" onsubmit="return validate(this);"><center> <table width="400" border="1" align="center" cellpadding="0" cellspacing="0"><tr><td> <table border="0" cellspacing="2" cellpadding="1" width="100%" > <tr bgcolor="#eaeac8"> <td align="left" colspan="2"><font size="5"> User Login</font></td></tr> <tr><td colspan="2"><p>&nbsp;</p></td></tr> <tr align="center"> <td align="right">User ID:</td> <td><html:text property="username" size="30" maxlength="30"/></td></tr> <tr align="center"> <td align="right">Password:</td> <td><html:password property="password" size="30" maxlength="30"/></td>

</tr> <tr align="center"> <td align="right">Login As:</td> <td> <html:select property="usertype"> <option>---------------Login As---------------</option> <option value="Buyer">Buyer</option> <option value="Seller">Seller</option> <option value="Guest">Guest</option> </html:select> </td> </tr> <tr><td colspan="2"><p>&nbsp;</p></td></tr> <tr> <td align="center" colspan="2"><html:submit> Login Now !</html:submit></td></tr></table> </td> </tr> </table> </center>

</html:form> <body> </html:html>

success.jsp

<%@page import="java.io.*"%> <%@page import="java.sql.*"%> <%@page import="javax.sql.*"%> <%@page import="java.util.*"%> <%@page import="javax.naming.*"%> <%@page import="javax.servlet.*"%> <% //getting value String username=request.getParameter("username"); String password=request.getParameter("password");

String usertype=request.getParameter("usertype"); %> <html> <head> <title>Success</title> </head> <body> <p> Hi , <%=username%><p> <p align="center"><font size="3" >You Are Successfully Loged in as <font color="red"><%=usertype%></font> </font></p></body></html>
failure.jsp

<%@ taglib uri="/tags/struts-bean" prefix="bean" %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <html:html locale="true"> <head> <title><bean:message key="welcome.title"/></title> <html:base/> </head> <body bgcolor="white"> <p align="center"><font size="3" color="red"> Sorry your UserId/Password is incurrect</font></p> <center><p><html:link page="/pages/login.jsp"><font size="3" color="blue">Retry click here!</font></html:link></p></center> </body> </html:html>

Controller Part of Login form Example:


The Controller part is focused on receiving requests from a web browser, deciding what business logic function is to be performed, and then delegating responsibility for producing the next phase of the user interface to an appropriate View component. The main component of the Controller in the framework is a servlet of classActionServlet. This servlet is configured by defining a set of ActionMappings.Defining the mapping for our example. Put the following code
in struts-config.xml. Put the following codes within the <form-beans> --------- </form-beans>

section.

<form-bean name="LoginForm" type="roseindia.web.struts.action.LoginForm"/> </form-beans>


Put the following codes within the <action-mappings> --------- </actionmappings> section.

<action path="/login" type="roseindia.web.struts.action.LoginAction" name="LoginForm" scope="request" validate="true" input="/pages/login.jsp"> <forward name="success" path="/pages/success.jsp"/> <forward name="failure" path="/pages/failure.jsp"/> </action>

How to run this Example:


Installing Struts Application:
Download latest version of Struts from the site of Struts http://jakarta.apache.org/struts. Copy struts-blank.war to tomcat webapps directory.

Start tomcat, Tomcat automatically extracts the file and loads the application. Download the code from here and then integrate it with the struts-blank application. Make necessary changes in the struts-config.xml, and compile application using ant. The restart the tomcat. Now your login application is ready. Now open Internet Explorer and type http://localhost:8080/strutsblank/ and press Enter. You browser window should look like:

Now click on the link Login Page Example the following window will open...

Now type User Id as 'username' and password as 'password' and select a login option then press login button. The success page will display.

Hi , username

You Are Successfully Loged in as Buyer


If you enter incorrect user id and password the failure page will display. Sorry your UserId/Password is incorrect Retry click here! In this tutorial you have learned how to develop simple login application with struts.

Struts integration with EJB in JBOSS3.2


My aim is to write about EJB2.0 in JBOSS3.2 using STRUTS FRAMEWORK.

The EJB specification provides Enterprise-level services. Typical services provided by the EJB Container are as follows. 1.Persistence 2.Declarative transactions 3.Security 4.Connection pooling 5.Support for messaging services The most famous EJB-Servers in the market are:

BEA ..WebLogic Server JBoss Application server IBM .WebSphere-5 Oracle AS

Of these , JBoss 3.2 & 4 are OpenSource and Free. JBOSS application sever has become recognized leader in the java application server market and to date is the major application server. Different kinds of Enterprise Beans are 1. Session Bean 2. Entity Bean 3. MessageDriven Bean (MDB) Session Bean

Session Bean can be defined as function bean called in RMI-IIOP style from Enterprise container. Two types of session bean are stateless session bean, stateful session bean. A stateless session bean does not maintain conversation state but stateful session bean maintains conversation state Entity Bean Entity Bean is a value bean with setter and getter methods representing one row of data in a table, invoked in RMI style from Enterprise container in Enterprise data store. Two types of Entity Beans are CMP (Container Managed Persistence), BMP (Bean Managed Persistence). In CMP, persistence code need not be written by the programmer. But In BMP Persistence code has to be written by the programmer .CMP is not satisfactory for really complex enterprise situations. ( CMP is an ORM technology ( Object-Relational Mapping Technology like Hibernate. and Hibernate is considered to be better than CMP). Message Driven Bean Session Bean and Entity bean are based on RPC mechanism. But, Message Driven Bean is based on Asynchronous messaging . MDB have no conversational state with the client and can be pooled like stateless session bean. Unlike other types of EJB, MDB have no home or remote interfaces. Messaging is like email whereas RPC is like phone call. In enterprise environment there will be heavy traffic and RPC may fail to create connection. In such situations messaging is more reliable. What is Struts?

Struts is a very famous ready made framework which implements MVC (Model View Controller) Architecture. It is open source and free. Struts frame work was developed by Craig MacLanahan in 2002 subsequently handed over to Apache Jakarta projects group. Struts is a frame work for building really complex Enterprise level applications Struts provide its own Controller component and integrates with other technologies to provide the Model and the View. For the Model, Struts can interact with standard data access technologies, like JDBC and EJB, as well as most any third-party packages, like Hibernate, iBATIS, or Object Relational Bridge. For the View, Struts works well with JavaServer Pages, including JSTL and JSF, as well as Velocity Templates, XSLT, and other presentation systems Purpose of the Struts When the user fills the form and submits the form, if the values entered by the user are wrong then the user must be presented with the same page with suitable error messages and the values already entered by the user should be preserved. If there is no error, ( validation test is passed), then the business logic is executed.. Installation Struts1.1 is zip file. Extract it. In Struts1.1 folder, there is a folder name called lib. There are many war files. One of the war file names, is struts-blank.war. Copy that struts-blank.war file to c:\tomcat5\webapps. Start the tomcat server. Now struts-blank folder is created . Copy that struts-blank folder and paste it in desktop. Rename the folder as kala .. Now, place that folder( kala ) in c:\tomcat5\webapps.( Assuming that we have installed tomcat5 in C drive). Here kala folder is our

context. Restart the tomcat server.. Open the Browser, type the URL as http://localhost:8080/kala. Now the welcome page will appear. This means that our installation process is correct. We require jboss3.2 and JDK1.4.2 for developing this exercise The following lesson illustrates the method of connecting to a stateless session bean in jboss3.2 server through a Struts-based program. We have installed jboss3.2 and JDK1.4.2 in D:\drive . Create a folder strutsejbdemo in D drive. This is our working directory. We have already created the context kala in tomcat5 as mentioned above. . Copy that kala context folder to E:\jboss32\server\default\deploy as kala.war In this lesson, we have created two packages namely demo and demo1. For this we have created the two folders namely demo and demo1 in D:\jboss32\server\default\deploy\kala.war\web-inf\classes to copy the class files D:\>cd strutsejbdemo D:\strutsejbdemo> When we use struts the concept of package is very important. D:\strutsejbdemo>md demo1 Here demo1 is our package D:\strutsejbdemo>cd demo1 Next we create a batch file to set path and classpath D:\strutsejbdemo\demo1>edit setpath.bat

set path=c:\windows\system32;d:\jdk1.4.2\bin;d:\bea\weblogic700\server\bin ( I am using WindowsXP. If you are using Windows-2000, the path to edit program should be :c:\winnt\system32.) Usually we give a class path to working directory. When we use package we giveclasspath to parent directory. This is very important. D:\strutsejbdemo\demo1\edit setcpath.bat set classpath=d:\ejbdemo;d:\jboss32\client\Log4j.jar;d:\jboss32\client\jbossj2ee.jar;d:\jboss32\client\jboss-common-client.jar;d:\jboss32\client \jnp-client.jar;d:\jboss32\client\jboss-system-client.jar;d:\jboss32\client\jbossclient.jar;d:\jboss32\client\jbosssx-client.jar;d:\jboss32\client \jboss-transaction-client.jar; After creating batch files in the working folder, Give the following command: d:\strutsejbdemo\demo1>setpath This will set the path for the window d:\strutsejbdemo\demo1>setcpath ( This will set the classpath for the window ). Checkup as follows: D:\strutsejbdemo\demo1>path D:\strutsejbdemo\demo1>echo %classpath% Now edit the following files

1. cityguide.java 2. ciyRemote.java 3. cityHome.java 4. cityBean.java D:\strutsejbdemo\demo1>edit cityguide.java package demo1; import java.util.*; public class cityguide { public String listcities(String a) { Vector vector1=new Vector(); if(a.equals("TAMILNADU")) { vector1.addElement("Madras"); vector1.addElement("Trichy"); vector1.addElement("Madurai"); } if(a.equals("KERALA")) {

vector1.addElement("Cochin"); vector1.addElement("Quicon"); vector1.addElement("Trivandrum"); } if(a.equals("KARNATAKA")) { vector1.addElement("Mysore"); vector1.addElement("Bangalore"); vector1.addElement("Hubli"); } String r=""; int n=vector1.size(); for(int j=0;j<n;j++) { String v=(String)vector1.elementAt(j); r=r+v+"<br>"; } return r; }

} //---------------------------------------------------------------------------------------------------------D:/strutsejbdemo/demo1>edit cityRemote.java package demo1; import javax.ejb.*; import java.rmi.*; public interface cityRemote extends EJBObject { public String showcities(String s) throws RemoteException; } //---------------------------------------------------------------------------------------------------------D:/strutsejbdemo/demo1>edit cityHome.java package demo1; import javax.ejb.*; import java.rmi.*; public interface cityHome extends EJBHome { public cityRemote create()

throws CreateException, RemoteException; } //--------------------------------------------------------------------------------D:/strutsejbdemo/demo1>edit cityBean.java package demo1; import javax.ejb.*; public class cityBean implements SessionBean { public String showcities(String s) { cityguide guide1= new cityguide(); String r = guide1.listcities(s); return r; } public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {}

} //---------------------------------------------------------------------------------------------------------We have already set the specified path and classpath. Compile all the above files D:\strutsejbdemo\demo1>javac *.java D:\ejbstrutsdemo\demo1>copy *.class d:\jboss32\server\default\deploy\kala.war\webinf\classes\demo1 D:\strutsejbdemo>demo1\cd.. D:\strutsejbdemo>md META-INF When we use package META-INF folder is created in parent folder. It should be in uppercase ie.,META-INF not meta-inf Now edit the ejb-jar.xml and jboss.xml in META-INF D:\strutsejbdemo\META-INF>edit ejb-jar.xml <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/dtd/ejb-jar_1_1.dtd"> <ejb-jar> <enterprise-beans> <session>

<ejb-name>city</ejb-name> <home>demo1.cityHome</home> <remote>demo1.cityRemote</remote> <ejb-class>demo1.cityBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar> //-------------------------------------------------------------------------------------------------D:\strutsejbdemo\META-INF >edit jboss.xml <?xml version="1.0" encoding="UTF-8"?> <jboss> <enterprise-beans> <session> <ejb-name>city</ejb-name> <jndi-name>cityJndi</jndi-name> </session> </enterprise-beans>

</jboss> //---------------------------------------------------------------------------------Now, cd back to D:\strutsejbdemo\ Create the jar file as follows: D:\strutsejbdemo\>jar cf city.jar demo1\*.class META-INF\*.xml Carefully note that the jar file is created in parent directory. Now, we copy the jar file to the jboss folder as shown below. D:\strutsejbdemo> copy city.jar D:\jboss32\server\default\deploy Start the jboss server as shown below Go to new window to start the jboss server. D:\jboss32\bin\>set JAVA_HOME=D:\JDK1.4.2 D:\jboss3.2\bin\>run The server will start now. If our jar file namely city.jar is deployed correctly deployed city.jar message will appear in the server. The development of the EJB and its deployment in JBOSS server is over. //----------------------------------------------------------------------------------------------------------Now we develop the Struts client program for the above EJB. D:\ejbstrutsdemo>md demo D:\ejbstrutsdemo>demo

D:\strutsejbdemo\demo>edit setcpath.bat set classpath=%classpath%;d:\strutsejbdemo;e:\struts1.1\lib\struts.jar; D:\strutsejbdemo\demo>setcpath We use the following six files, in this demo package, 1. kalaSubmit.jsp 2. kalaForm.java(derived from ActionForm) 3. kalaAction.java(derived from Action) 4. kalahelper.java ( a utility bean) 5. kalaresult.java ( a value bean) 6. kalaOutput.jsp ( besides the web.xml ,struts-config.xml files & application.properties file) D:\ejbstrutsdemo\demo1>edit kalaSubmit.jsp <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html> <body bgcolor=cyan> <center> <h1>STRUTS CLIENT FOR STATELESS</h1> </center> <html:errors/>

<html:form action="kala" name="kalaForm" type="demo.kalaForm" > State <br> <h1>Whick State Do you want to tour?</h1> <h2>TAMILNADU?KERALA?KANADA?</h2> <html:text property="state" /> <br> <html:submit /> </html:form> </body> </html> //---------------------------------------------------------------------------------------------------------When the user submits the kalaSubmit.jsp, the formbean is automatically filled up with the values from the jsp-page and the flow goes to the ActionServlet. <html:errors/> tag is used to displaying error messages. D:\strutsejbdemo\demo>edit kalaForm.java package demo; import javax.servlet.http.*;

import org.apache.struts.action.*; public class kalaForm extends ActionForm { String state =null; public String getState() { return state; } public void setState(String a) { state=a; } public void reset(ActionMapping mapping, HttpServletRequest request) { state=null; } public ActionErrors validate (ActionMapping mapping, HttpServletRequest request) {

ActionErrors errors = new ActionErrors(); if( state.length()= =0) { errors.add("state", new ActionError("errors.nullstate")); } return errors; } } //---------------------------------------------------------------------------------------------------------D:\strutsejbdemo\demo>edit kalahelper.java package demo; import java.util.*; import javax.ejb.*; import javax.rmi.*; import javax.naming.*; import java.rmi.*; import java.io.*; public class kalahelper {

public String callejb(String s) { String r; try { System.out.println("Please Wait..."); Properties props=new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.put(Context.PROVIDER_URL,"localhost"); props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); Context context=new InitialContext(props); System.out.println("Connection OK"); demo1.cityHome home= (demo1.cityHome)context.lookup("cityJndi"); System.out.println("HOME LOCATED"); demo1.cityRemote remote= home.create(); System.out.println("REMOTE READY");

r=remote.showcities(s); } catch(Exception e1){ r=""+e1; } return r; } } //------------------------------------------------------------------------------------------------D:\strutsejbdemo\demo>edit kalaresult.java package demo; public class kalaresult { String value; public kalaresult() { value=" "; } public String getValue(){ return value; }

public void setValue(String v){ value=v; } } //---------------------------------------------------------------------------------------------------The Action Class is part of the Model and is a wrapper around the business logic. The purpose of Action Class is to translate the HttpServletRequest to the business logic In our case, the action class instance is using a helper to perform the business logic. This is the bettter and recommended practice. D:\strutsejbdemo\demo>edit kalaAction.java package demo; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.struts.action.*; public class kalaAction extends Action { public ActionForward execute(ActionMapping mapping,

ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { kalaForm kalaform =(kalaForm) form; String a = kalaform.getState(); if(a.equals("TAMILNADU") || a.equals("KERALA") || a.equals("KARNATAKA")) { kalahelper helper = new kalahelper(); String r = helper.callejb(a); kalaresult kr = new kalaresult(); kr.setValue(r); String m = kr.getValue(); System.out.println(m); HttpSession session= request.getSession(); session.setAttribute("result",kr); return (mapping.findForward("success")); }

else { ActionErrors errors = new ActionErrors(); errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("errors.wrongname")); saveErrors(request,errors); return(mapping.findForward("failure")); } } }

D:\strutsejbdemo\demo>edit kalaOutput.jsp

<html> <body bgcolor=orange> <h1> <jsp:useBean id="result" scope="session" class="demo.kalaresult" /> <br> <jsp:getProperty name="result" property="value" /> </h1>

</body> </html> Now we are ready to compile the above programs.class path are already specified D:\strutsejbdemo\demo>javac *.java D:\strutsejbdemo\demo>copy *.jsp d:\jboss32\server\default\deploy\kala.war D:\strutsejbdemo\demo>copy *.class d:\jboss32\server\default\deploy\kala.war\web-inf\classes\demo The deployment process is over Go to another window. cd to D:\jboss32\server\default\deploy\kala.war\web-inf>edit struts-config.xml In the struts-config.xml file, we make two entries. One entry is for the instance of kalaForm and the other entry is for the instance of kalaAction class. -----------------------------------------( this is the part dealing with the formbean) <form-bean name="kalaForm" type="demo.kalaForm" /> The next segment of mapping in

struts-config.xml deals with the action mapping for QueryAction. <action path="/kala" type="demo.kalaAction" name="kalaForm" input="/kalaSubmit.jsp" scope="session" validate= true > <forward name="success" path="/kalaOutput.jsp"/> <forward name="failure" path="/kalaSubmit.jsp"/> </action> There is a file known as 'Application.properties' in 'WEB-INF\classes\resources' and at the end of that file we will add the following lines. errors.nullstate=<li><h1> ENTER YOUR STATE<h1></li> errors.wrongname=<li><h1>SORRY .., SERVICE NOT PROVIDED FOR THIS STATE</h1> </li> Therefore, we will get the specified error messages. Start the jboss server as usual.

Open the browser and type URL as http://localhost:8080/kala/kalaSubmit.jsp Type the name of the state ( TAMILNADU/KERALA/KARNATAKA)in the text box & then click 'submit '. It the name of the sate is correct then result will be displayed. Otherwise the home page remains with the values entered and also with the error message. As the main purpose of this note is just to explain how to connect to stateless ejb using Struts, I am leaving out Validation Framework details. Acknowledgements: The following articles from back issues of DeveloperIQ. 1) Packaged EJB by Farihah Noushene. 2) Developing EJB in Weblogic 7 by R.S.Ramaswamy **************************************************************************

Struts integration with EJB in WEBLOGIC7


My aim is to write about EJB2.0 in WEBLOGIC-7 using STRUTS FRAMEWORK. The EJB specification provides Enterprise-level services. Typical services provided by the EJB Container are as follows. 1.Persistence 2.Declarative transactions 3.Security 4.Connection pooling 5.Support for messaging services

The most famous EJB-Servers in the market are:


BEA ..WebLogic Server JBoss Application server IBM.WebSphere-5 Oracle AS

Of these , JBoss 3.2 & 4 are OpenSource and Free However, BEA has the longest record and used by many enterprises and hence a standard..Therefore, I am now writing about WebLogic-7 and later, I will cover JBoss3.2 in a separate lesson.( The latest version of Weblogic is WL-9). Different kinds of Enterprise Beans are 1. Session Bean 2. Entity Bean 3. MessageDriven Bean (MDB) Session Bean Session Bean can be defined as function bean called in RMI-IIOP style from Enterprise container. Two types of session bean are stateless session bean, stateful session bean. A stateless session bean does not maintain conversation state but stateful session bean maintains conversation state Entity Bean Entity Bean is a value bean with setter and getter methods representing one row of data in a table, invoked in RMI style from Enterprise container in Enterprise data store. Two types of Entity Beans areCMP (Container Managed Persistence), BMP (Bean Managed Persistence). In CMP, persistence code need not be written by the programmer. But In BMP Persistence code has to be written by the programmer .CMP is not satisfactory for really complex enterprise

situations. ( CMP is an ORM technology ( Object-Relational Mapping Technology like Hibernate. and Hibernate is considered to be better than CMP). Message Driven Bean Session Bean and Entity bean are based on RPC mechanism. But, Message Driven Bean is based on Asynchronous messaging . MDB have no conversational state with the client and can be pooled like stateless session bean. Unlike other types of EJB, MDB have no home or remote interfaces. Messaging is like email whereas RPC is like phone call. In enterprise environment there will be heavy traffic and RPC may fail to create connection. In such situations messaging is more reliable. What is Struts? Struts is a very famous ready made framework which implements MVC (Model View Controller) Architecture. It is open source and free. Struts frame work was developed by Craig MacLanahan in 2002 subsequently handed over to Apache Jakarta projects group. Struts is a frame work for building really complex Enterprise level applications Struts provide its own Controller component and integrates with other technologies to provide the Model and the View. For the Model, Struts can interact with standard data access technologies, like JDBC and EJB, as well as most any third-party packages, like Hibernate, iBATIS, or Object Relational Bridge. For the View, Struts works well with JavaServer Pages, including JSTL and JSF, as well as Velocity Templates, XSLT, and other presentation systems Purpose of the Struts When the user fills the form and submits the form, if the values entered by the user are wrong then the user must be presented with the same page with suitable error messages and the values already entered by the user should be preserved.

If there is no error, ( validation test is passed), then the business logic is executed.. Installation Struts1.1 is zip file. Extract it. In Struts1.1 folder, there is a folder name called lib. There are many war files. One of the war file names, is struts-blank.war. Copy that struts-blank.war file to c:\tomcat5\webapps. Start the tomcat server. Now struts-blank folder is created . Copy that struts-blank folder and paste it in desktop. Rename the folder as kala.. Now, place that folder(kala) in c:\tomcat5\webapps.( Assuming that we have installed tomcat5 in C drive). Here kala folder is our context. Restart the tomcat server.. Open the Browser, type the URL as http://localhost:8080/kala. Now the welcome page will appear. This means that our installation process is correct. We require weblogic7 and JDK1.4.2 for developing this exercise /----------------------------------------------------------------------------------------------------------The following lesson illustrates the method of connecting to a stateless session bean in weblogic7 server through a Struts-based program. We have installed weblogic7 and JDK1.4.2 in D:\drive . Create a folder strutsejbdemo in D drive. This is our working directory. We have already created the context kala in tomcat5 as mentioned above. . Copy that kala context folder to D:\bea\user_projects\mydomain\applications In this lesson, we have created two packages namely demo and demo1. For this we have created the two folders namely demo and demo1 in :D\bea\user_projects\mydomain\applications\kala\web-inf\classes\ to copy the class files D:\>cd strutsejbdemo

D:\strutsejbdemo> When we use struts the concept of package is very important. D:\strutsejbdemo>md demo1 Here demo1 is our package D:\strutsejbdemo>cd demo1 Next we create a batch file to set path and classpath D:\strutsejbdemo\demo1>edit setpath.bat set path=c:\windows\system32;d:\jdk1.4.2\bin;d:\bea\weblogic700\server\bin ( I am using WindowsXP. If you are using Windows-2000, the path to edit program should be :c:\winnt\system32.) Usually we give a class path to working directory. When we use package we giveclasspath to parent directory. This is very important. D:\strutsejbdemo\demo1\edit setcpath.bat set classpath=d:\strutsejbdemo\demo1;d:\strutsejbdemo; d:\bea\weblogic700\server\lib\weblogic.jar After creating batch files in the working folder, Give the following command: d:\strutsejbdemo\demo1>setpath This will set the path for the window

d:\strutsejbdemo\demo1>setcpath ( This will set the classpath for the window ). Checkup as follows: D:\strutsejbdemo\demo1>path D:\strutsejbdemo\demo1>echo %classpath% Now edit the following files 1.cityguide.java 2.ciyRemote.java 3.cityHome.java 4.cityBean.java D:\strutsejbdemo\demo1>edit cityguide.java package demo1; import java.util.*; public class cityguide { public String listcities(String a) { Vector vector1=new Vector(); if(a.equals("TAMILNADU"))

{ vector1.addElement("Madras"); vector1.addElement("Trichy"); vector1.addElement("Madurai"); } if(a.equals("KERALA")) { vector1.addElement("Cochin"); vector1.addElement("Quicon"); vector1.addElement("Trivandrum"); } if(a.equals("KARNATAKA")) { vector1.addElement("Mysore"); vector1.addElement("Bangalore"); vector1.addElement("Hubli"); } String r=""; int n=vector1.size();

for(int j=0;j<n;j++) { String v=(String)vector1.elementAt(j); r=r+v+"<br>"; } return r; } } //---------------------------------------------------------------------------------------------------------D:/strutsejbdemo/demo1>edit cityRemote.java package demo1; import javax.ejb.*; import java.rmi.*; public interface cityRemote extends EJBObject { public String showcities(String s) throws RemoteException; } //----------------------------------------------------------------------------------------------------------

D:/strutsejbdemo/demo1>edit cityHome.java package demo1; import javax.ejb.*; import java.rmi.*; public interface cityHome extends EJBHome { public cityRemote create() throws CreateException, RemoteException; } //--------------------------------------------------------------------------------D:/strutsejbdemo/demo1>edit cityBean.java package demo1; import javax.ejb.*; public class cityBean implements SessionBean { public String showcities(String s) { cityguide guide1= new cityguide(); String r = guide1.listcities(s);

return r; } public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {} } //---------------------------------------------------------------------------------------------------------We have already set the specified path and classpath. Compile all the above files D:\strutsejbdemo\demo1>javac *.java D:\ejbstrutsdemo\demo1>copy *.class d:\bea\user_projects\mydomain\applications\kala\web-inf\classes\demo1 D:\strutsejbdemo>demo1\cd.. D:\strutsejbdemo>md META-INF When we use package META-INF folder is created in parent folder. It should be in uppercase ie.,META-INF not meta-inf Now edit the ejb-jar.xml and weblogic-jar.xml in META-INF D:\strutsejbdemo\META-INF>edit ejb-jar.xml

<?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/dtd/ejb-jar_1_1.dtd"> <ejb-jar> <enterprise-beans> <session> <ejb-name>city</ejb-name> <home>demo1.cityHome</home> <remote>demo1.cityRemote</remote> <ejb-class>demo1.cityBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar> //-------------------------------------------------------------------------------------------------D:\strutsejbdemo\META-INF >edit weblogic-jar.xml <?xml version="1.0"?>

<!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN" "http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd"> <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>city</ejb-name> <jndi-name>cityJndi</jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar> //---------------------------------------------------------------------------------Now, cd back to D:\strutsejbdemo\ Create the jar file as follows: D:\strutsejbdemo\>jar cf city.jar demo1\*.class META-INF\*.xml Carefully note that the jar file is created in parent directory. Now we check up the jar file as follows D:\strutsejbdemo>java weblogic.ejbc city.jar city1.jar If there are no problems , we get the ejbc successful message Now, we copy the jar file to the WebLogic folder as shown below. D:\strutsejbdemo>copy city1.jar d:\bea\user_projects\mydomain\applications

Start the weblogic server as start->programfiles->BEA weblogic->user_projects->mydomain>start server The city1.jar will be deployed by the server. The development of the EJB and its deployment in WebLogic server is over. //----------------------------------------------------------------------------------------------------------Now we develop the Struts client program for the above EJB. D:\ejbstrutsdemo>md demo D:\ejbstrutsdemo>demo D:\strutsejbdemo\demo>edit setcpath.bat set classpath=%classpath%;d:\strutsejbdemo;e:\struts1.1\lib\struts.jar; D:\strutsejbdemo\demo>setcpath We use the following six files, in this demo package, 1. kalaSubmit.jsp 2. kalaForm.java(derived from ActionForm) 3. kalaAction.java(derived from Action) 4. kalahelper.java ( a utility bean) 5. kalaresult.java ( a value bean) 6. kalaOutput.jsp ( besides the web.xml ,struts-config.xml files & application.properties file) D:\ejbstrutsdemo\demo1>edit kalaSubmit.jsp

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html> <body bgcolor=cyan> <center> <h1>STRUTS CLIENT FOR STATELESS</h1> </center> <html:errors/> <html:form action="kala" name="kalaForm" type="demo.kalaForm" > State <br> <h1>Whick State Do you want to tour?</h1> <h2>TAMILNADU?KERALA?KANADA?</h2> <html:text property="state" /> <br> <html:submit /> </html:form> </body> </html>

//---------------------------------------------------------------------------------------------------------When the user submits the kalaSubmit.jsp, the formbean is automatically filled up with the values from the jsp-page and the flow goes to the ActionServlet. <html:errors/> tag is used to displaying error messages. D:\strutsejbdemo\demo>edit kalaForm.java package demo; import javax.servlet.http.*; import org.apache.struts.action.*; public class kalaForm extends ActionForm { String state =null; public String getState() { return state; } public void setState(String a) { state=a; }

public void reset(ActionMapping mapping, HttpServletRequest request) { state=null; } public ActionErrors validate (ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if( state.length()= =0) { errors.add("state", new ActionError("errors.nullstate")); } return errors; } } //---------------------------------------------------------------------------------------------------------D:\strutsejbdemo\demo>edit kalahelper.java package demo; import java.util.*;

import javax.ejb.*; import javax.rmi.*; import javax.naming.*; import java.rmi.*; import java.io.*; public class kalahelper { public String callejb(String s) { String r; try { System.out.println("Please Wait..."); Properties props=new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); String url="t3://127.0.0.1:7001"; props.put(Context.PROVIDER_URL,url); Context context=new InitialContext(props);

System.out.println("Connection OK"); demo1.cityHome home= (demo1.cityHome)context.lookup("cityJndi"); System.out.println("HOME LOCATED"); demo1.cityRemote remote= home.create(); System.out.println("REMOTE READY"); r=remote.showcities(s); } catch(Exception e1){ r=""+e1; } return r; } } //-------------------------------------------------------------------------------------------------

D:\strutsejbdemo\demo>edit kalaresult.java package demo; public class kalaresult { String value;

public kalaresult() { value=" "; } public String getValue(){ return value; } public void setValue(String v){ value=v; } } //---------------------------------------------------------------------------------------------------The Action Class is part of the Model and is a wrapper around the business logic. The purpose of Action Class is to translate the HttpServletRequest to the business logic In our case, the action class instance is using a helper to perform the business logic. This is the bettter and recommended practice. D:\strutsejbdemo\demo>edit kalaAction.java package demo; import java.io.*;

import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import org.apache.struts.action.*; public class kalaAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { kalaForm kalaform =(kalaForm) form; String a = kalaform.getState(); if(a.equals("TAMILNADU") || a.equals("KERALA") || a.equals("KARNATAKA")) { kalahelper helper = new kalahelper(); String r = helper.callejb(a); kalaresult kr = new kalaresult();

kr.setValue(r); String m = kr.getValue(); System.out.println(m); HttpSession session= request.getSession(); session.setAttribute("result",kr); return (mapping.findForward("success")); } else { ActionErrors errors = new ActionErrors(); errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("errors.wrongname")); saveErrors(request,errors); return(mapping.findForward("failure")); } } } D:\strutsejbdemo\demo>edit kalaOutput.jsp

<html>

<body bgcolor=orange> <h1> <jsp:useBean id="result" scope="session" class="demo.kalaresult" /> <br> <jsp:getProperty name="result" property="value" /> </h1> </body> </html> Now we are ready to compile the above programs.class path are already specified D:\strutsejbdemo\demo>javac *.java D:\strutsejbdemo\demo>copy *.jsp d:\bea\user_projects\mydomain\applications\kala

D:\strutsejbdemo\demo>copy *.class d:\bea\user_projects\mydomain\applications\kala\web-inf\classes\demo The deployment process is over Go to another window. cd to D:\bea\user_projects\mydomain\applications\kala\web-inf>edit struts-config.xml In the struts-config.xml file, we make two entries. One entry is for the instance of kalaForm and the other entry is for the instance of kalaAction class. ------------------------------------------

( this is the part dealing with the formbean) <form-bean name="kalaForm" type="demo.kalaForm" /> The next segment of mapping in struts-config.xml deals with the action mapping for QueryAction. <action path="/kala" type="demo.kalaAction" name="kalaForm" input="/kalaSubmit.jsp" scope="session" validate=true> <forward name="success" path="/kalaOutput.jsp"/> <forward name="failure" path="/kalaSubmit.jsp"/> </action>

. There is a file known as 'Application.properties' in 'WEB-INF\classes\resources' and at the end of that file we will add the following lines. errors.nullstate=<li><h1> ENTER YOUR STATE<h1></li> errors.wrongname=<li><h1>SORRY.., SERVICE NOT PROVIDED FOR THIS STATE</h1> </li> Therefore, we will get the specified error messages. Start the weblogic server as usual. Open the browser and type URL as http://localhost:7001/kala/kalaSubmit.jsp Type the name of the state ( TAMILNADU/KERALA/KARNATAKA)in the text box & then click submit. If the name of the state is correct then result will be displayed. Otherwise the home page remains with the values entered and also with the error message. As the main purpose of this note is just to explain how to connect to stateless ejb using Struts, I am leaving out Validation Framework details. In another article soon, I will extend this concept to connect to Hibernate from the Stateless ejb. Acknowledgements: The following articles from back issues of DeveloperIQ. 1) Packaged EJB by Farihah Noushene. 2) Developing EJB in Weblogic 7 by R.S.Ramaswamy **************************************************************************

Вам также может понравиться