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: