Professional Jakarta Struts _ISBN 0-7645-4437-3_

Reviews
Shared by: keara
Stats
views:
45
rating:
not rated
reviews:
0
posted:
10/31/2009
language:
ENGLISH
pages:
0
Professional Jakarta Struts (ISBN 0-7645-4437-3) by James Goodwill & Richard Hightower last change 3/4/9 1) Chapter 1:Struts Intro a) Jakarta project i) http://jakarta.apache.org/ ii) http://struts.apache.org/ iii) Model-View-Controller design pattern (p2 note about other patterns) (1) Model: supporting data objects usually with jdbc connections (2) View: JSP driven GUI representation of current state of Model (extensive use of tag libraries) (3) Controller: View-Model interface iv) Struts version of MVC (p3 chart & steps involved) b) Java Web applications i) Servlets ii) JSP iii) Custom tag libraries iv) java classes v) Static HTML, etc vi) Web app deployment descriptor (web.xml p7, 67)) vii) Directory Structure (1) (2) config & tld files go here (3) (4) .../wroxapp/WEB-INF/classes .../wroxapp/WEB-INF/lib .../wroxapp .../wroxapp/WEB-INF xml c) Tomcat servlet container (The following assumes individual installs not the All-in-one MyEclipse) i) Install java jdk first (1) I am using the 1.7.0x version in Linux & 1.6.0 in Windows (2) http://java.sun.com (3) Important: make sure the versions (32bit or 64bit) of java & Eclipse match ii) Now install Apache Tomcat (1) http://tomcat.apache.org (2) Use only the release builds (3) If you have errors installing the first time, set an environment variable JAVA_HOME=”C:\where\ever\jdk\is” then try again iii) Then install your IDE (1) If using eclipse and MyEclipse (docs are here) (a) Eclipse (3.4 Works Now) first: http://www.eclipse.org/ if you have zip problems get WinZip (b) then MyEclipse (7.0GA): http://www.myeclipseide.com if you have install problems use the manual install version (c) Put jdk bin directory at first of PATH (d) ** Note as of MyEclipse 6 the All in One installation does everything in Windows ** ================================================== 2) Servlet & JSP Overview a) I assume some familiarity from previous Classes b) JHTP 5th edition Servlets (ch24), JSP (ch25) c) Servlets i) Figure 2.2: HttpServlet Object Model (Sun's Reference Site) ii) Setting up book code examples iii) Lifecycle: contructor, init, service, destroy iv) Deploying a servlet exploded and as war file v) Servlet Context (1) Facilitates servlet-container communication (2) Storage area for objects available to all components in a webapp (3) Every webapp has only one ServletContext (4) getAttribute(), setAttribute, getAttributeNames() (5) ContextServlet.java (p21): jsp will return “could not find...” (a) implicit objects in Context.jsp (23): application, out (6) run context servlet (http://localhost:8080/ch02app/context) (7) then rerun Context.jsp vi) Http data (1) ServletRequest methods (a) ng getParameter(String name) (b) ng[] getParameterValues(String name) (c) eration (d) et.java (26) & Form.html(28) getParameterNames() ParameterServl java.util.Enum java.lang.Stri java.lang.Stri d) JSP: quick reference card i) Steps of a JSP request (fig 2.9 p 31) (1) Request: container recognizes the extension & passes to JSP engine (2) First time requested since change, jsp is used to create a servlet (3) Servlet is compiled & run (4) Response is sent back to client ii) Components of a JSP (1) JSP Directives provide global info about a jsp page (a) (i) mport=”somefiletoimport” (ii) ession=”true|false” (iii) rrorPage=”someerrorpageurl.jsp” (iv) sErrorPage=”true|false” <%@ page i s e i (b) include Directives are used to insert text and/or code at JSP translation time (i) < $@ include file=”somefile.jsp” %> (c) taglib Directive says that the including page uses a custom tag library (i) < %@ taglib url=”tagLibraryURL” prefix=”tagXMLprefix %> (ii) %! public String SomeMethod(String name) {... (b) (i) ello <%=name %> how are you today
(c) source %> (i) % callsomeclass.method() %> more html <% someotherjavacode %> etc <% scriptlet < <%= expression H < < (3) JSP Error Pages (a) errorpage.jsp (36) (b) testerror.jsp (37) (4) Implicit Objects (a) out (b) request (request.jsp 39) (c) response (d) pageContext (e) session (session.jsp 40) (f) application (g) config (h) pagesexception (5) Object scope: page vs request vs session vs application (6) Standard Actions (a) id=”name” scope=”...” class=”project.class” /> (c) (b) provides parameters for include, forward, & plugin (f) evaluated each time page is requested as opposed to include directive include.jsp (48) (g) page=”relativeURL” > (i) orward.jsp (50), welcome.jsp (51), management.jsp (51) ... (i) see quick reference card ================================================== 3) Struts – Apache User Guide a) jakarta.apache.org --> struts.apache.org --> where is struts 1.1 ??? b) Installation with / without MyEclipse i) WEB-INF/lib ii) iii) iv) Tomcat/common/lib web.xml struts-config.xml tld definitions c) A New struts webapp using MyEclipse i) file-new-Web Application (1) gives directory structure & web.xml file (steps 2 & 4) ii) MyEclipse-Add Struts capabilities (1) look at config path, action servlet name, servlet url pattern, base package (ch03), install jars & tld (2) when Finished have jars, struts-config.xml, web.xml, tld files (steps 1, 3, & 5) ----------------------------------------------------------- d) The first struts webapp i) index.jsp view: create the query view (1) file-new-jsp struts 1.1 with a form (a) lots of tag lib defs + basic jsp with html:form tags (2) fix form to match book index.jsp (3) MyEclipse version versus book ii) LookupForm.java: create the form bean (1) file-new-class LookupForm.java (2) change parent class to be ActionForm (3) paste code from example into new class (4) Edit struts-config.xml file to match pg 61 (5) Note the names of the methods. You MUST the JavaBean standard naming convention iii) quote.jsp: Create using standard jsp template ie no struts code (1) Add Current Price: <%= request.getAttribute("PRICE") %> LookupAction.java: Create the controller iv) (1) file-new-class LookupAction (a) extend org.apache.struts.action.Action (2) paste code from example into new class (3) remove all the Wiley logging stuff (4) edit struts-config.xml file to match p65 (a) be careful using right click on the outline v) Deploying: MyEclipse changed the web.xml file already (1) servlet def in p66 (2) servlet-mapping on p66 (3) web.xml file on p67 Run it, remember to use SUNW if you want a quote (1) (a) 1 – creates necessary html code for form (b) 2 – checks for instance of LookupForm in session scope (c) 3 – submit causes /ch03app/Lookup.do to be called (i) this uses the action-mapping to call the ActionServlet (d) 4 – ActionServlet looks for an ActionMapping entry that matches Lookup (i) creates ActionMapping objects for all values in action-mapping element (ii) creates LookupAction (iii)calls LookupAction.execute(...) (iv) when control returned to ActionServlet it uses returned ActionForward to call appropriate view vi) vii) Other ways to create simple web app ================================================== 4) Actions & ActionServlet The Controller components: ActionServlet.class, Action.class, Plugins (which we will mostly ignore), & the RequestProcessor a) ActionServlet When a request is received: i) doGet() or doPost() invoke the process() method ii) process() gets current RequestProcess and calls process() method iii) RequestProcessor.process() (1) Uses struts-config action element to match request path (2) Uses action name attribute to match form-bean iv) Creates or retrieves form bean v) Populations the bean vi) Validates using ActionForm.validate() method if required vii) Creates an Action class and calls Action.execute() viii) When processing returns a ActionForward object uses it to send control to target ix) Configuring ActionServlet: (1) Init parameters in web.xml (table 4.1 pg 76) b) Action Class The most common component in struts webapps i) ii) iii) iv) v) vi) Create class that extends Action Implement the execute() method Return ActionForward object Put action element in struts-config.xml Put class and xml files on server Configuring Action classes (1) Path attribute in action element must be unique (2) Class can be reused as required by other unique paths (3) Forward, input, path, & type attributes in Table 4.3 pg 82 c) Plugins i) Must implement the org.apache.struts.action.Plugin interface ii) Useful for allocating resources (properties files), setting up jdbc or jndi, & other init functions ex: tiles.TilesPlugin & validator.ValidatorPlugin iii) Create a class that implements the Plugin interface iv) Add an empty constructor, a init(ActionServlet, ModuleConfig), & a destroy() method v) Put what you want to happen at application startup in the init method We will use logging from http://logging.apache.org/log4j/1.2/index.html & reading a properties file vi) Add the to the main struts-config.xml file Please note from the example that this must be the last element in the config file vii) Put controller element in struts-config file after action-mapping and before message-resources (listing 4.3 pg 89) d) Logging with log4j i) Logging in any webapp is critical to track problems, use of the system, &/or development progress ii) System.out.println or err.println can be used but is not as effective iii) Get the log4j jar file from the apache.org web site above iv) Put the jar file in your project’s WEB-INF/lib folder and click Refresh in eclipse v) The online docs at the apache site are the best source of info on the properties file and its loggers, appenders, conversion patterns, log levels, etc vi) Please note priority of log levels is debug < info < warn < error < fatal and that incoming log level request must be equal to or greater than the system loggers level set in the properties file to be printed --- To use the default tomcat logging system --vii) Create a log4j.properties file (leave that as the name) and put it in the root of your src folder #Example log4j.properties file log4j.rootLogger=INFO, fileout log4j.appender.fileout=org.apache.log4j.RollingFileAppender log4j.appender.fileout.File=/home/durrett/temp/durrett.log log4j.appender.fileout.MaxFileSize=10MB log4j.appender.fileout.MaxBackupIndex=10 log4j.appender.fileout.layout=org.apache.log4j.PatternLayout log4j.appender.fileout.layout.ConversionPattern=%d %-5p %-30.30c{1} %x - %m%n viii) For any class where you wish to use logging (1) import the commons logging jars import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; (2) Create a class level static attribute private static Log log = LogFactory.getLog(FindDogAction.class); Please note the logger naming convention (3) Anytime you wish to output logging information if (log.isInfoEnabled()) { log.info("Getting dogtype property"); } -- The next part assumes you are creating a Plugin to initialize your own logging system --ix) Create a log4j.properties (log4j.pjsprops) file and put it in your WEB-INF folder Please note that putting the log4j.properties file in WEB-INF/classes overrides the default logger x) Initialize a static Logger object in your PlugIn class public static Logger pjsLog = Logger.getLogger(“A1”); xi) Configure the pjsLog object String fullPathtoYourWebapp = servlet.getServletContext().getRealPath("/"); PropertyConfigurator.configure(fullPathtoYourWebapp + “/WEB-INF/log4j.pjsprops”); xii) Anywhere in your application that you want to log use the instructions from viii above and, Logger pjsLog = Logger.getLogger("A1"); // get the specific logger you created in your plugin pjsLog.info("Symbol: " + sStk); e) Properties files i) Setup a properties file. This can be xml or java properties (the version I use in the pjs project) type SYSTEM_TITLE=Professional Jakarta Struts ii) Save the file in the WEB-INF folder of your app iii) Create a file object File file = new File(fullPathtoYourWebapp + "/WEB-INF/props.txt"); iv) Open a FileInputStream: FileInputStream fis = new FileInputStream(file); v) Load the properties: properties.load(fis); vi) Add the properties to the ServletContext (the webapplication memory space) ServletContext context = servlet.getServletContext(); context.setAttribute(“PROPERTIES”, properties); vii) You can use the set properties anywhere in your webapp like this: ServletContext context = request.getSession().getServletContext(); Properties rProperties = (Properties)context.getAttribute("PROPERTIES"); String sTitle = rProperties.getProperty("SYSTEM_TITLE"); f) RequestProcessor When customizing ActionServlet this is where to start i) ii) iii) iv) v) Create a class that extends action.RequestProcessor Override processPreprocess() method Return true for success ie continue as normal Return false for processing completed, ie do not call Action Put controller element in struts-config file after action-mapping and before message-resources (listing 4.3 pg 89) ============================================ 5) Advanced Action Classes a) Design Notes i) Limit the “business logic” in your jsp (1) jsp's are for user views, they DO NOT talk to the model, they only display pieces of it (2) Actions are for control & select the next view not the jsp (3) the struts-config.xml file controls ALL system flow (4) Helper object models implement business logic b) Forward Actions (basic) i) Typical link: action must match complete path defined in struts-config file ActionForm must be defined in action name attribute ii) optional attributes (a) of initial focus attribute” (2) resulting html: focus=”name (3) property must be a property in the ActionForm class optional attributes (a) value=”initial value of attribute” (b) readonly=”true if desired” (4) resulting html userid : (5) struts-config iii) ActionForm Beans (1) get & set Methods for each attribute (2) reset() method called to reset all attributes to default values This help avoid stale data being left in form bean (3) struts-config iv) Steps in submission of struts form (1) Controller creates (or retrieves) instance of LoginForm & stores it in session (2) Controller calls LoginForm.reset() (3) Controller populates LoginForm object with data from html:form attributes (4) Controller invokes LoginAction.execute method (5) Controller forwards processing to appropriate jsp after execute returns ActionForward v) DynaActionForm Dynamic ActionForm for use with simple data inputs (1) Add form-bean element to struts (2) Create data input jsp (DynamicLogin.jsp) only difference is the action name (3) Create new action class (DynamicLoginAction) the only changes needed are to the following lines // Use the DynamicForm to get the request parameters //LoginForm lf = (LoginForm) form; DynaActionForm lf = (DynaActionForm)form; // make sure arguments match form-property names //String su = lf.getUserid(), sp = lf.getPassword(); String su = (String)lf.get("userid"), sp = (String)lf.get("password"); (4) Add DynamicAction to strutsname="dynamicloginform" config file ============================================ 7) Debugging Struts 8) Custom Action Mappings http://struts.apache.org/userGuide/index.html a) ActionMapping class i) An ActionMapping object describes an Action instance to the ActionServlet It uniquely defines an instance of a particular action class They are setup / defined by the action element in the struts-config file b) Custom Action Mappings i) allow addition of parameters to custom ActionMapping classes c) Attributes of ActionMapping Object in struts-config file (p 144) i) className -- fully qualified ActionMapping class name typically used for custom ActionMappings ii) iii) iv) v) type – Action class that will process the request input – where to return control if ActionErrors are returned name – ActionForm key path – Context relative path of submitted request, must start with / used by ActionServlet to determine which Action to call for each request parameter – used to pass additional arguments to Action object for instance the parameter=method in the DispatchAction vi) d) Creating a custom ActionMapping (1) Extend ActionMapping (a) Create new class such as: public class WroxActionMapping extends ActionMapping (b) Add new properties: add property, get and set methods (c) make sure to call super() as first line in constructor (2) Setup struts-config file action element to use new ActionMapping (a) add className attribute to action element definition className=”ch08.WroxActionMapping” (b) add new set-property element (3) Create Action class that utilizes new Attribute in ActionMapping sub class WroxActionMapping wm = (WroxActionMapping) mapping; if (wm.getLogResults()) ... 9) Internationalizing Struts (i18n) a) i18n Components i) Resource bundle based Message class ii) tag b) Controller i) java properties file containing key=value pairs ex: app.symbol=Symbol ii) iii) ApplicationResources.properties (default file) ApplicationResources_language_COUNTRY.properties (naming pattern) (1) ApplicationResources_en_US.properties (2) ApplicationResources_it_IT.properties (3) supported locales: http://java.sun.com/j2se/1.4.2/docs/guide/intl/locale.doc.html iv) v) Resources filename can be anything. Depends on config file setting When changing resource messages webapp must be reloaded or tomcat restarted c) Deployment of resource bundle EITHER web.xml file (1) servlet element (2) (3) ex: application ApplicationResources i) ii) OR struts-config.xml file (1) iii) default iv) placement in WEB-INF/classes other placement per java package format ie. WEB-INF/classes/com/notreally/ApRes.properties d) bean tag Library If using eclipse/MyEclipse when you enable struts it is done for you i) e) Example files: http://jdurrett.ba.ttu.edu/4383/Examples/ch09/index.html 10) Managing Errors a) ActionError pattern is key, placeholder, may have 0-4 placeholders or use array i) new ActionError(String key) ii) new ActionError(String key, Object objRef) iii) new ActionError(String key, Object ...) iv) ex new ActionError(“errors.sql.insert.one”); b) ActionErrors i) ActionErrors errs = new ActionErrors() ii) errs.add(“some_property_value”, new ActionError(“somekey”)); iii) property value is the property in the input jsp that caused the error c) ActionForm validate method returns ActionErrors Object Reference d) struts-config (pg 162) i) validate=”true” ii) input=”/where_the_error_came_from.jsp” usually a jsp with a struts-based input form e) ActionForm i) public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) ii) ex: (pg 164) public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errs = new ActionErrors(); if (some test is true) { errs.add(“this param”, new ActionError(“errors.sql.select.only”)); } return errs; f) ApplicationResources.properties (pg 165) i) errors.header=

Error List

    ii) errors.footer=

iii) errors.sql.select.only=
  • Sorry only select is currently supported
  • iv) errors.sql.sqlerror=
  • {0}
  • Note the use of the {0} as placeholder placeholders are formatted according to java.text.MessageFormat g) jsp's i) tag (pg 166) (1) any where in jsp (2) be careful of tags inserted by MyEclipse h) Action.execute (pg 168) (1) test for error condition (2) set forward string to failure (3) create ActionErrors object ActionErrors errs = new ActionErrors(); (4) add ActionError to ActionErrors object errs.add("sql", new ActionError("errors.sql.sqlerror", sqlException.getMessage())); (5) save ActionErros if not empty collection saveErrors(request, errs); (6) return ActionForward (7) As long as the key used in the ActionError constructor is in the ApplicationResources.properties file or is in the input or failure forward jsp IT WILL WORK, hopefully :-) Example Steps 1. index.jsp from ch09/ 2. 3. actions for ch10 (copy ch9, change paths & forwards) 4. validate method & add ActionError import 5. ApplicationResources files 6. ApplicationResources files Run the project in tomcat, put in no symbol 7. validate=”false” in the ch10 action Reload & run test it again 8. 9. no symbol found error check Change the validate to true Edit the ch09.LookupAction & add Edit the struts-config file and put in Add error.header & error.footer to Add error message key used in 4 to Edit ch09.LookupForm: change Change actions in ch10/index.jsp Change struts-config: add new Create /ch10/index.jsp copy 10. ApplicationResources files 11.
    xi) 11. Copy the validator-rules.xml and validation.xml files into WEB-INF or the module folder under WEB-INF GOTCHA: be very sure you are using the same versions of your struts.jar & the validator xml files if you do not you will get strange errors like this: java.lang.NoSuchMethodException: org.apache.struts.validator.FieldChecks.validateRequired(java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, javax.servlet.http.HttpServletRequest) xii) 12. Subclass ValidatorForm instead of ActionForm in your form (step 1 above) public class RegistrationForm extends ValidatorForm { GOTCHA: if you have a validate method make sure to call super.validate and assign the result to an ActionErrors object. Only then can you run your own validation logic and add errors to the existing ActionErrors object. xiii) 13. Add a form to the form sets in the validation.xml file Note: When debugging watch the console output in Eclipse. Small errors like zipcode instead of zipCode will show up easily Note: regular expressions and the mask rule are very powerful xiv) xv) 14. Add a field, rules, errors, & error arguments to the form set created in step 13 15. Add error messages to the resource bundle for all errors created in step 14 Note: use the examples from the top of the validator-rules.xml file as a start Points: Two Rules with one depends, regular expression masks, constants, dates xvi) Misc. b) Overriding the validate method, ex:validation between two fields public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errs = super.validate(mapping, request); if (!password.equals(passwordChk)) { errs.add("password", new ActionError("errors.password.mismatch")); } return errs; } c) Writing Your own rules i) 1. Create a java class (it can extend anything you wish) public class ValidatePassword ii) 2. Add a static validation method public static boolean matchPasswords(Object bean, ValidatorAction va, Field pass1, ActionErrors errors, HttpServletRequest request) { return true if everything is ok false if not iii) 3. Create an entry in the validatorrules.xml file iv) 4. To use your new rule simply follow steps 13 – 15 above d) DynaActionForms use DynaValidatorForm instead of DynaActionForm in the form-bean element e) Client-Side JavaScript Saves round trip communication requirements Each validator in the validator-rules.xml file can have script associtated with it Can add a js file with all scripts to enable caching by browser (1) jsp <bean:message key="registration.title" /> Add onsubmit="return validateRegistrationform (3) Add cancel Boolean variable to ActionForm: if (this.isCancelled(request)) { sFwd = "home"; } global-forward: (4) To optimize Client-Server traffic put JavaScript in separate js file a. create a new file with the extension .js b. Put your JavaScript code in this file; do not include opening and closing SCRIPT tags you can get this from a test run of the jsp setup in 1, 2, & 3 above c. change the
    • <%= error%>
    g) Wizard style Work Flow: or multiple jsp for the same ActionForm / Validate process i) Benefits: Allows multiple jsp to access a single form Allows “Wizard” style input streams Basic Process (this is slightly different from the text) (1) Change Action to subclass DispatchAction (see ch5, p97) this makes small incremental actions possible public class PhasedRegisterAction extends org.apache.struts.actions.DispatchAction { public ActionForward step1( … public ActionForward step2( … (2) Create new Form to hold new stream of input data (3) Add parameter=”method” to new Form allow passing of method to Action ie. if method=”step1” then the Action.step1 method will be used remember to add getMethod() and setMethod() private String method; public String getMethod() { return method; } public void setMethod(String s) { this.method = s; } (4) Create two input jsp (my examples are reg1.jsp & reg2.jsp and are simply segments of the previous version) (5) Add two form & action-mappings to struts-config (6) Create two input jsp, use the new form and actions created above (7) Add a hidden field to the jsp to identify the Action method to use for example on the first step input jsp: Test it now, if you look at the form data when you are in the second input phase (either debug or System.err.println) you will notice everything from the first input is gone. The problem is request scope. (8) In the action-mappings in the struts-config file, change form to session scope to allow repeated access (9) Modify validation.xml & make necessary changes to the Form and the Action classes to allow validation Following the books naming (a) Add an additional hidden field for page to each of the input jsp Notice that you can either set the page variable value in the Action as the book does or as a “static” value in the tag as I do above. (b) Add a new validation form to the validation.xml file & setup all field validation rules (c) Add a page=’?’ attribute to each field element indicating where (on which jsp) the field should be validated 13) Tiles or visual struts components Goal is reusable presentation components & ability to standardize webapp views a) Definitions & Overview i) Tiles are reusable visual components (page == tile) ii) Arguments are passed to Tiles as parameters in tile scope iii) Tile scope is similar to page scope, less general than request scope iv) Parameters and Arguments are available ONLY to the tile they are passed to v) Tile layouts can provide default argument to tiles That means the individual visual components need override only those args specific to them vi) A region is an area in a tile layout vii) A Tile Definition defines parameters for calling a tile layout viii) Tile definitions can extend other definitions ix) The tiles framework provides a custom RequestProcessor There are several ways to “define” a site layout in my opinion the xml version is best b) Steps in creating and using a tile layout (METHOD 1) (1) Find the similarities between jsp or design the structure of a web site (2) Create a new layout page (a) Import the Tiles taglib into the jsp <%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %> versus <%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> (b) Use (c) Use (3) Create two new content pages that contain only the differences between jsp (4) Insert the tile layout into the new pages and send parameters to the tiles to customize content (a) Import the Tiles taglib (b) Use the Example passing text (html) as region component <%= request.getAttribute("PRICE") %> (d) Build the component pages (footer.jsp, header.jsp, & indexContent.jsp above) c) creating and using a tile layout definition in a non visual jsp (METHOD 2) tile definitions add the ability to pass default parameters, this ability helps limit code repetition (1) (2) (3) (4) import the Tiles tag library use Content goes here Create the page that uses the new layout definition (5) Use (6) Use d) creating and using a tile layout definition in a non visual XML (METHOD 3) (1) Add the Tiles plugin for struts to the struts-config file (2) Create a new Content goes here . (3) Replace the beanName and beanScope tags in the previous index2.jsp (index3.jsp) e) Notes: i) If you are using modules remember to make all the jsp in tile:put tags relative ii) If you have set the validate xml property in the plugin to true Remember to include a link to the dtd in the tiles-defs.xml file iii) 14) Developing a Complete Struts application A link to a similar article from The Server Side: Struts Redirect-after-Post These notes follow the creation of the employees application in PJS: Ch14 as adapted to our system a) Basic Tomcat / eclipse /MyEclipse / MySql webapp setup (1) Create a new Project (I followed the book and named mine employees) (2) Use MyEclipse to add struts capabilities (I used com.wrox as the base package and employeesResources for the resource file) (3) Add the mysql jdbc driver jar file to your java build path (4) Create an English resource bundle (Listing 14.3 pg 247) (5) Create the /WebRoot/images folder with required images (6) NOTE: Setting up the tag libraries. In the book the authors always put tag lib defs in the web.xml file, however when using our environment none are ever found there. The following note from http://struts.apache.org/userGuide/configuration.html explains why: Servlet 2.3 users only: The Servlet 2.3 specification simplifies the deployment and configuration of tag libraries. The instructions above will work on older containers as well as 2.3 containers (Struts only requires a servlet 2.2 container); however, if you're using a 2.3 container such as Tomcat 4.x, you can take advantage of a simplified deployment. All that's required to install the Struts tag libraries is to copy struts.jar into your /WEB-INF/lib directory and reference the tags in your code like this: <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> Note that you must use the full uri defined in the various tlds (see the example configuration for reference) so that the container knows where to find the tag's class files. You don't have to alter your web.xml file or copy tlds into any application directories. (7) Create the employees database: mysqladmin create employees -u root –p grant all privileges on employees.* to '4383'@'%' identified by 'durrett'; grant all privileges on employees.* to '4383'@'localhost'; mysql -p employees < mysqlscripts.sql (I removed the first two line so that I could add my own new db and user) b) Create the basic data model objects (1) com.wrox.Employee.java (a very simple struts form) (2) com.wrox.EmployeeData.java Provides the webapp --- business model interface (3) Add the data-source element to your struts-config file Remember to change the username and password c) Create the list, add, edit, & delete transactions for the employee database i) Welcome (1) create the index.jsp page (it is a simple forward to the EmployeeList action) (2) add the index.jsp url to the welcome-file-list element in the web.xml file ii) list employees (1) Create the com.wrox.EmployeeListAction.java (2) Create the /WebRoot/employeelist.jsp Since we did not put the tag defs in web.xml, remember to change the uri’s in the jsp <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> Also, note the edit and delete links for each employee ">Edit property="username" />"> Delete (3) Add the /EmployeeList action-mapping to the struts-config file iii) add employee (1) Create the /WebRoot/addemployee.jsp (2) Create the com.wrox.EmployeeForm.java the reset method simply sets the default values the validate method enforces not null requirements of the employees table (3) Create the com.wrox.AddEmployeeAction.java (4) Add the employeeForm form-bean and the the /Add action-mapping to the struts-config file iv) edit employee (1) Create the com.wrox.GetEmployee.java (2) Create the /WebRoot/editemployee.jsp (3) Create the com.wrox.EditEmployeeAction.java (4) Add the /Edit & /EditEmployee paths to the action-mappings in the struts-config file v) delete employee (1) Create the com.wrox.DeleteEmployeeAction.java (2) Add the /Delete path to the action-mappings in the struts-config file test the webapp, every thing should work vi) 15) The struts-config.xml File An amplification / overview of the heart of any struts project http://struts.apache.org/dtds/struts-config_1_2.dtd The elements must be in exactly this order (they must follow the dtd listed above) a) XML Elements are delimited by angle brackets and identify the nature of the content they surround. The element’s content model follows the element name. ? in the content model indicate optional sub-elements that can occur only once * in the content model indicate optional sub-elements that may occur zero or more times + indicate optional sub-elements that must occur once but can more times Attributes are name-value pairs that occur inside start-tags after the element name % identifies a parameter entry in an element definition Comments begin with (1) A CDATA section instructs the parser to ignore most markup characters i) ii) iii) iv) v) vi) vii) viii) Between the start of the section, , all character data is passed directly to the application, without interpretation b) Top-level sub-elements i) (%Location;)> (%Location;)> iii) (#PCDATA)> c) data-sources i) ii) iii) d) type – optional DataSource class (default: javax.sql.DataSource) must meet java bean specs className – optional configuration object must extend org.apche.struts.config.DataSourceConfig key – unique identifier required if more than one data-source used form-beans ` i) name – unique identifier ii) type – class name of the form class e) global-exceptions defines an ExceptionHandler to execute when an Action's execute method throws an Exception. (1) subclass org.apache.struts.action.ExceptionHandler and override the execute method (2) Your execute method should process the Exception and return an ActionForward object (3) Edit struts-config This configuration element says that com.yourcorp.ExceptionHandler.execute will be called when any IOException is thrown by an Action. The key is a key into your message resources properties file that can be used to retrieve an error message. ii) You can override exception handlers by defining an exception inside an action f) global-forwards name: The logical name for this forward. Used in Action’s execute method to forward to the next appropriate resource. ii) path: The context relative path to the resource. Example: /index.jsp or /index.do iii) redirect: True or false. Should ActionServlet redirect to the resource instead of forward? [false] i) g) action-mappings h) controller (all attributes are optional and can be selectively changed) http://struts.apache.org/userGuide/configuration.html For each request made of the controller, the method process(HttpServletRequest, HttpServletResponse) will be called. This method determines which module should service the request and then invokes that module's Request Processor’s process method, passing the same request and response. public class GaiteRequestProcessor extends TilesRequestProcessor { protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) { // If user is trying to access login page // then don't check String sServletPath = request.getServletPath(); if( sServletPath.equals("/Login.do") || sServletPath.equals("/locale.do") ) return true; // Check if userName attribute is there is session. // If so, it means user has allready logged in User user = (User)request.getSession().getAttribute(GaiteSystemConstants.USERKEY); if( user != null ) return true; else { try { // If no redirect user to login Page request.getRequestDispatcher("/Login.do").forward(request,response); }catch(Exception ex){ } } return false; } } bufferSize – size (bytes) of the input buffer used for processing file uploads. [4096] className - Classname of configuration bean. [org.apache.struts.config.ControllerConfig] contentType - Default content type (and optional character encoding) to be set on each response. May be overridden by the Action, JSP, or other resource to which the request is forwarded. [text/html] v) forwardPattern - Replacement pattern defining how the "path" attribute of a element is mapped to a context-relative URL when it starts with a slash (and when the contextRelative property is false). This value may consist of any combination of the following: ii) iii) iv) * $M - Replaced by the module prefix of this module. * $P - Replaced by the "path" attribute of the selected element. * $$ - Causes a literal dollar sign to be rendered. * $x - (Where "x" is any character not defined above) Silently swallowed, reserved for future use. If not specified, the default forwardPattern is consistent with the previous behavior of forwards. [$M$P] inputForward - Set to true if you want the input attribute of elements to be the name of a local or global ActionForward, instead of as a module-relative path to the resource to be used as the input form. [false] vii) locale - Set to true if you want a Locale object stored in the user's session if not present. [true] viii) processorClass - The fully qualified Java class name of the RequestProcessor subclass to be used with this module. [org.apache.struts.chain.ComposableRequestProcessor] ix) maxFileSize - The maximum size (bytes) of a file to be accepted as a file upload. Can be expressed as a number followed by a "K", "M", or "G", [250M] vi) i) message-resources multiple resource files can be used key="key.in.resourcefile" bundle="key name in message-resources j) plugins k) Gotcha: i) Forward vs. redirect: if you set the redirect attribute to true in the forward you loose the request scope objects (you keep the session scope object of course) 16) The HTML tag library http://struts.apache.org/struts-taglib/tlddoc/ Tag library documentation is IMHO lacking. So what you are going to get here is interesting examples a) The Problem: you need to create a combo box from database information for example a set of departments from a dept table as in the chapter 14 employees app b) The solution (1) Create java bean class with all the properties necessary for each of your “options” In my example project (jrd) this is the MenuItem class public class MenuItem { private String prompt; private String value; private String link; … Note: the link attribute is not used in the html:select tag but in the logic:iterate example later (2) Create a collection (a simple array is the easiest) of the beans from your database In my example I simply “fake it” MenuItem[] menu = new MenuItem[3]; menu[0] = new MenuItem("BA", "3", "http://www.ba.ttu.edu/"); menu[1] = new MenuItem("Accounting", "4", "http://accounting.ba.ttu.edu/"); menu[2] = new MenuItem("Finance", "5", "http://finance.ba.ttu.edu/"); GOTCHA: If any item in your collection is null you will get server errors (3) Save the collection you created in some scope (in my example request) request.setAttribute("menu", menu); (4) Create your standard struts jsp – form-bean – action to allow input (5) On the input jsp add the html:select tag department : (a) property is the property in your input form-bean (b) size is the number of selections to allow (6) Add the html:options tag as a sub-element in the select element (a) collection is the name of the bean that you saved in some scope (b) property is the “value” (c) labelProperty is the prompt for each option (d) scope is the memory space in which to look for the collection bean 17) 18) The Logic Tag Library http://struts.apache.org/userGuide/dev_logic.html a) The Problem: you need to create a set of links from database information for example the main menu in a webapp depends on the role of the person who logs in b) The solution (1) – (4) Follow the same pattern as in the html tag example above (5) On the input jsp add the logic:iterate code >
    . (a) id is the object name used in the loop for the collection (b) name is the collection name in some memory space (c) scope is where to look for the collection of beans . (6) Add the bean:write tags in the logic:iterate element (a) name is the object name from id in the logic:iterate element (b) property is the bean property to call with a getSomeProperty query (c) The rest is normal html (7) Addendum 1. Modules Using modules allows developers to partition a single web application into functional areas. This allows independent development without struts-config, form, and action coordination problems. (a) Steps in Using Modules i. Create a struts-config file for each module ii. Configure the web.xml deployment descriptor for each module iii. Configure links to access module specific jsps struts configuration files Having seperate config files allows independent forwards, forms, actions, etc The only difference with module config files is how the Tiles and Validator plugins are setup i. The typical naming convention for module config files is struts-config-MODULE.xml where MODULE is the name of the specific module ii. However when using Tiles and/or Validator this option is more practical /WEB-INF/moduleA/struts-config.xml /WEB-INF/moduleB/struts-config.xml this struture allows seperate placement of the Tiles and Validator config files: And in Eclipse allows adding forms, etc through the outline (Linux) /WEB-INF/moduleA/tiles-defs.xml /WEB-INF/moduleA/validation.xml /WEB-INF/moduleB/tiles-defs.xml /WEB-INF/moduleB/validation.xml (b) (c)Configure the web.xml file for each module i. The typical, single module web.xml file the struts-config file is specified as: config /WEB-INF/struts-config.xml ii. When using modules each config parameter must be named to exactly identify the module. The param-name must be: config/moduleName where moduleName is the exact name you want to use for your module in this webapplication. For instance, assume you have two modules named ch08 and ch10: config/ch08 /WEB-INF/struts-config-ch08.xml config/ch10 /WEB-INF/struts-config-ch10.xml iii. The name given to the module in the web.xml param-name is called the module-prefix and is very important. It is used by struts to distinguish and route requests to each module. The module-prefix becomes part of the URL that is always used to access module jsps, actions, etc> All of a module's action paths are relative to the module. For instance, if we have a webapp named s05_4383 a module named ch08 and an action who's path is /query the URL becomes: http://someserver:someport/s05_4383/ch08/query iv. When using modules the standard config file, ie the one in the WEB-INF directory without any module name and specified in the web.xml file as simply config, is the default struts-config file and is used when no module is listed in the URL. Thus files placed in the webapp root or in folders not named after modules will be controlled through this default config file. (d) Configure links and actions to access module specific jsps and actions When using modules you cannot simply link to the relative directory (ch08/index.jsp) The problem is that the jsp URL will not go through the struts servlet and thus the relative module configuration will not be loaded and any tag libraries or actions used will be loaded from the default config file. To correct this problem all requests for module changing jsps must be routed through the struts servlet. This is accomplished as follows: i. Add the SwitchAction mapping to each struts-config file You may use any action path you wish ii. When linking from a jsp to go to a sub-module index.jsp use: to go to the top level “default” module index.jsp use: iii. You may also use any modular jsp rather than the index pages (e)Using Eclipse 3.1.0 with MyEclipse 3.8.4 i. Create a web project, add struts capabilities (PJS in this example) Be sure to backup the project (or deploy it) before continuing just in case :-) ii. Add a new module to the new project (ch11) You will get an web.xml file with the correct config param: config/ch11 /WEB-INF/struts-config-ch11.xml if you wish to use Tiles or the Validator remember to change the structure per b.ii. Above. And a “blank” module config file iii. Open the new config file iv. Create a new form Right click on the form-beans element in the outline and chose new Form You may use the default package or a package name for the form class Note that the new module is chosen by default Create the form as you have before do not add the module name to any of the paths You will end up with a typical form-bean entry and a new ActionForm class Make the appropriate changes to the class v. Create a new action Right click on the action-mapping element in the outline and chose new Action Fill out the appropriate entries as always, Remember that all paths are relative to the module. You should now have an Action class and an action entry in the module struts-config file. Edit the Action class as you wish to accomplish your action. vi. WebRoot folder vii. viii. Create a new folder that has the same name as the module in the Create the necessary jsps in this new folder If you wish a module index add the necessary global forward and actions and create the index using standard struts links for local module actions and SwitchAction links for changing to other modules ix. x. Make any changes as required to master (top level) jsps Deploy and reload the project to the Tomcat server 2. MyEclipseIDE Database Explorer MyEclipse Database Explorer Requirements: 1. Java 2 SDK, Standard Edition 1.4 or later installed 2. Eclipse 3.0.x SDK 3. MyEclipse 3.8.3 at least 4. A database server that is supported bythe MyEclipse Database Explorer 5. The MyEclipse Database Explorer configured to browse a sample database (a) Database Explorer i. Install Driver: /Window/Preferences/MyEclipse/Database Explorer/Drivers A. Disable Row Limit B. Load all database meta data ii. New profile (the icon on the browser pane) A. B. C. iii. iv. table definitions (b) Change the driver to the one you just edited Change the URL to 129.118.51.6:20/yourdb_db I suggest prompt for password Right click on the new connection and pick open Be careful playing around, you can change both the data and the ER diagrams Currently limited to creating diagrams from current databases i. Open database connection ii. Right click on database and choose create ER diagram iii. A. Preferences B. in InnoDB tables C. Notes: You might have to edit the diagram colors in MySQL (version 4.1.7) supports foreign keys only InnoDB create sql InnoDB insert sql D. iv. 4.1.7 or greater) A. B. C. D. E.show tables; Interesting sql commands (some are dependent on MySQL version show engines; show create table SomeTableName; show table status; describe SomeTableName; 3. User authentication (a) Authentication i. Option 1: include a user table in the db schema A. something like this: (email is the userid) This option assumes that your db contains a table create table RefUsers ( password varchar(20) NOT NULL, nickname varchar(20) NOT NULL, email varchar(50) NOT NULL, scope varchar(15) NOT NULL, lastname varchar(30), firstname varchar(30), bselect boolean default 1, binsert boolean default 0, bupdate boolean default 0, bdelete boolean default 0, PRIMARY KEY (email) ); B. With insert statement like: insert into RefUsers values ("bob", "DrBob", "bob@bob.com", "select", "Bob", "Bob"); insert into RefUsers values ("durrett", "DrJohn", "john@durrett.org", "admin", "Durrett", "John"); C. And validation queries like (u is userid and p is password) : select * from RefUsers where email=\"" + u + "\" and password=\"" + p + "\"” D. generic sql query on the db and the user does: select * from RefUsers They are going to get Password Bob Durrett nickname DrBob DrJohn The problem here is that if I give the ability to do a email scope bob@bob.com select john@durrett.org admin lastname Bob Durrett firstname Bob John Probably not what you would want The solution is to use encryption E. Leave the create table syntax the same but change the insert statements to: insert into RefUsers values (AES_ENCRYPT('Tom','DrJohnisaGreatTeacher!'), "Just Tom", "tom@tom.com", "select", "Tom", "Thompson"); F. And valiation queries like: select * from RefUsers where email=”useridvar" and AES_DECRYPT(password,\'DrJohnisaGreatTeacher!\') ="passvar”; G. Password Bob Tﱪ6£Mak/æÏ nickname DrBob Just Tom Email bob@bob.com tom@tom.com Then your query results above look like: scope Lastname firstname select Bob Bob select Tom Thompson Much less informative. The problem is keeping track of the encryption key H. @enckey:='DrJohnisaGreatTeacher!'; If you do select when creating a connection object then select * from RefUsers where email=”useridvar" and AES_DECRYPT(password,@enckey) ="passvar”; to validate the user the key stays on the server ii. Option 2: Do not include users in the db that the user has access to A. First, create two completely different databases on the server in our example these will be ref_db (for the data files) and Ref_User_db for user validation B. Second, insert data into ref_db and users into Ref_User_db and add appropriate users to MySQL C. Third, either create two data-source elements in your struts-config file or connect to the Ref_User_db in LogonAction and the ref_db in SqlQueryAction iii. Option 3: IMHO the best option is to do both. I would probably put the db on different servers if possible too. iv. A. To setup the @enckey in MySQL Extend ActionServlet and override the init() public class RefActionServlet extends ActionServlet { public void init() throws ServletException { super.init(); method B. In the init method: C. Call super.init() as the first line in the new method D. Get a DataSource from the servlet context for the ref_user_db (DataSource)getServletContext().getAttribute("ref_user");. E. Get a connection and a statement F. Execute the select to setup the constant statement.executeQuery("select @enckey:='DrJohnisaGreatTeacher!'");. I would put the constant value and the variable name in GlobalConstants G. ActionServlet Change the web.xml file to use the new action ref.RefActionServlet H. use the new constant Change the select statement in the LoginAction to

    Related docs
    Jakarta Struts For Dummies - allfreeebooks.tk
    Views: 18  |  Downloads: 5
    struts framework
    Views: 53  |  Downloads: 6
    Jakarta
    Views: 447  |  Downloads: 9
    ISBN
    Views: 0  |  Downloads: 0
    Struts Best Practises
    Views: 291  |  Downloads: 28
    Struts Outline
    Views: 52  |  Downloads: 10
    How to begin coding a struts app
    Views: 13  |  Downloads: 4
    Jakarta Bike Week 2006
    Views: 113  |  Downloads: 0
    premium docs
    Other docs by keara
    Istanbul Maltepe Military Hospitals Pharmacy
    Views: 307  |  Downloads: 0
    ISMP Survey Reveals Pharmacy Interventions
    Views: 290  |  Downloads: 0
    IRB Pharmacy Verification
    Views: 312  |  Downloads: 0
    IRB and Pharmacy Clarification
    Views: 223  |  Downloads: 0
    IPG
    Views: 95  |  Downloads: 0
    Investigational Drug Pharmacy
    Views: 95  |  Downloads: 1