You are on page 1of 93

09/03/2005

Advanced Struts

1

In this presentation, we are going to talk about advanced features of Struts. I expect the audience of this presentation has some basic understanding on Struts.

1

09/03/2005

Sang Shin
sang.shin@sun.com www.javapassion.com Java™ Technology Evangelist Sun Microsystems, Inc.
2

2

09/03/2005

Disclaimer & Acknowledgments
?

?

?

Even though Sang Shin is a full-time employee of Sun Microsystems, the content in this presentation is created as his own personal endeavor and thus does not reflect any official stance of Sun Microsystems. Sun Microsystems is not responsible for any inaccuracies in the contents. Acknowledgments: – I borrowed from presentation slides from the following sources
?

“Using the Struts framework” presentation material from Sue Spielman of Switchback Software (sspielman@switchbacksoftware.com)

– – –

Struts' user's guide is also used in creating slides and speaker notes Source code examples are from Cookbook example originally written by I also used “Programming Jakarta Struts” book written by Chuck Cavaness

3

3

09/03/2005

Revision History
? ? ?

?

12/01/2003: version 1: created by Sang Shin 04/09/2004: version 2: speaker notes are polished a bit 09/01/2005: DynaActionForm and Validation Framework slides are separated out into a different file Things to do – speaker notes need to be added – more example codes need to be added – javascript slides need to be added

4

4

09/03/2005

Advanced Struts Topics
?

Extending & customizing Struts framework

Plug-In API (1.1)

? ? ? ?

ForwardAction (1.1) DispatchAction (1.1)
Declarative exception handling (1.1) Multiple application modules support (1.1)

5

So this is the first page of the topics we will discuss in this presentation. First, we will talk about how to extend and customize Struts framework especially with plug-in mechanism. Then we will talk about DynaActionForm. We will spend quite a bit of our time talking about Validation and Tiles frameworks. Validation framework enables validation through configuration. And Tiles framework enables a flexible way of managing layouts. We will talk a bit on declarative exception handling. And then we will talk about how multiple application modules can be configured. As you can see all of these features are introduced in Struts 1.1.

5

09/03/2005

Advanced Struts Topics
? ? ? ? ?

Struts and security Struts utility classes Nested tag library Differences between Struts 1.0 and 1.1 Roadmap

6

We will then talk about how to use Struts to access databases. We will also talk about how expression language feature of JSTL can be used with Struts. We will spend a bit of time taking about how security features such as SSL can be used with Struts. Then we will talk about a few other issues.

6

09/03/2005

Advanced Struts Topics Covered in Other Presentations
? ? ? ? ? ?

Struts Tags Struts Validation Frameworks Struts and Tiles Struts and Database Access Struts Best Practices Struts Tools

7

.

7

09/03/2005

Extending & Customizing Struts Framework
8

N ow let's talk about how to extend and customize Struts framework especially plugin mechanism. We are talking about this topic first because the plugin mechanism is going to be used by Validator and Tiles frameworks.

8

09/03/2005

Extending Struts Framework
?

Struts framework is designed with extension and customization in mind
– –

It provides extension hooks Validator and Tiles use these extension hooks

?

Extend the framework only if default setting does not meet your needs

There is no guarantee on the backward compatibility in future version of Struts if you are using the extension

9

One of the reasons why Struts has become such a popular framework is it allows extension and customization in pretty much every facet of its framework. In fact, one of the original design goals of Struts is extensibility and customizability. So it is designed with these aspects in mind and as you will see in the following slides, it provides various extension hooks in its architecture. In fact, several features of Struts such as Validator and Tiles use these extensions underneath. Now Struts framework comes with lots of built-in features so in most cases you do not need to extend and customize the framework. And when you have to, it is recommended that you do it with care because there is no guarantee that your application will work with the next version of the Struts framework.

9

09/03/2005

Extension/Customization Mechanisms of the Framework
? ?

Plug-in mechanism (1.1) Extending framework classes (1.1)
– – – –

Extending Struts configuration classes Extending ActionServlet class Extending RequestProcessor class Extending Action class

?

Using multiple configuration files (1.1)

10

So the primary extension mechanism of Struts is plug-in mechanism, which was introduced as part of Struts 1.1. In addition, you can also extend the framework classes. Again, this is not necessary for most applications. We will then talk about how you can use DispatchAction class. Also we will talk about how you can use multiple configuration files. By the way, all of these features are introduced in Struts 1.1.

10

09/03/2005

Extension/Customization:

Plug-in Mechanism
11

So let's talk about plugin mechanism first.

11

09/03/2005

What is a Plug-in?
?

Any Java class that you want to initialize when Struts application starts up and destroy when the application shuts down

Any Java class that implements org.apache.struts.action.Plugin interface

public interface PlugIn { public void init(ActionServlet servlet, ApplicationConfig config) throws ServletException; public void destroy(); }
12

A plugin under Struts context is basically any Java class that implements org.apache.struts.action.Plugin interface. As you can see in the slide, the Plugin interface has init(..) and destroy() methods, which are used for one-time initialization and cleanup respectively. The initialization occurs when Struts application gets started up and the cleanupoccurs when the application is being shut down. So inside the init() method, for example, you might want to create a database connection, and inside the destroy() method, you might want to close the database connection.

12

09/03/2005

Why Plug-in?
?

?

?

Before Struts 1.1 (in Struts 1.0), you had to subclass ActionServlet to initialize application resources at startup time With plugin mechanism (in Struts 1.1), you create Plugin classes and configure them Generic mechanism

Struts framework itself uses plugin mechanism for supporting Validator and Tiles

13

So why do we need plugin mechanism? Before plugin is introduced, that is under Struts 1.0, the only way you can do some initialization is to subclass ActionServlet class. Obviously this is not really a convenient way of performing an initialization. With plugin mechanism, you create plugin classes and then configure them through struts-config.xml file. So, as was mentioned, Struts framework itself uses plugin mechanism for adding validator and tiles frameworks.

13

09/03/2005

How do you configure Plug-in's?
?

?

Must be declared in struts-config.xml via <plug-in> element 3 example plug-in's in struts-example sample application
<plug-in className="org.apache.struts.plugins.ModuleConfigVerifier"/> <plug-in className="org.apache.struts.webapp.example.memory.MemoryDatabasePlugIn"> <set-property property="pathname" value="/WEB-INF/database.xml"/> </plug-in> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in>

14

Struts PlugIns are configured using the <plug-in> element within the Struts configuration file. This element has only one valid attribute, 'className', which is the fully qualified name of the Java class which implements the org.apache.struts.action.PlugIn interface. For PlugIns that require configuration themselves, the nested <set-property> element is available. So this slide shows three <plug-in> elements in the struts-config.xml file of the struts-examples1 sample code that you find in the hands-on lab/homework material you download from the class website. The first plugin is ModuleConfigVerifier that verifies module configuration. This plugin comes with Struts. The second is MemoryDatabasePlugin that provides in-memory SQL database functionality and the third one is Validator plugin.

14

09/03/2005

How do Plug-in's get called?
?

?

During startup of a Struts application, ActionServlet calls init() method of each Plug-in configured Plug-ins are called in the order they are configured in struts-config.xml file

15

So how do these plugin's get called? During the startup of a Struts applicatiuon, ActionServlet calls init() method of each plugin configured. And these plugins are called in the order they are configured in the struts-config.xml. So if the order of initialization is important, make sure they are configured in the right order.

15

09/03/2005

init() of MemoryDatabasePlugin in struts-example sample application
public final class MemoryDatabasePlugIn implements PlugIn { ... /** * Initialize and load our initial database from persistent storage. * * @param servlet The ActionServlet for this web application * @param config The ApplicationConfig for our owning module * * @exception ServletException if we cannot configure ourselves correctly */ public void init(ActionServlet servlet, ModuleConfig config) throws ServletException { log.info("Initializing memory database plug in from '" + pathname + "'"); // Remember our associated configuration and servlet this.config = config; this.servlet = servlet;

16

This is code fragment from the MemoryDatabasePlugin code that comes with struts-example1 sample code you download from the class website.

16

09/03/2005

Continued...
// Construct a new database and make it available database = new MemoryUserDatabase(); try { String path = calculatePath(); if (log.isDebugEnabled()) { log.debug(" Loading database from '" + path + "'"); } database.setPathname(path); database.open(); } catch (Exception e) { log.error("Opening memory database", e); throw new ServletException("Cannot load database from '" + pathname + "'", e); } // Make the initialized database available servlet.getServletContext().setAttribute(Constants.DATABASE_KEY, database); // Setup and cache other required data setupCache(servlet, config); } 17

This is the continuation of the init() method of the plugin.

17

09/03/2005

destroy() of MemoryDatabasePlugin in struts-example1 sample code
public final class MemoryDatabasePlugIn implements PlugIn { ... /** * Gracefully shut down this database, releasing any resources * that were allocated at initialization. */ public void destroy() { log.info("Finalizing memory database plug in"); if (database != null) { try { database.close(); } catch (Exception e) { log.error("Closing memory database", e); } } servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY); database = null; servlet = null; database = null; config = null; 18 }

This is the code fragment of the MemoryDatabasePlugin which shows the destroy() method.

18

09/03/2005

Extension/Customization:

Extending Struts Framework Classes
19

OK. we just took a look at the plug-in mechanism. Now let's see how you can extend Struts framework classes. Again, as was mentioned before, in most cases, you do not need to extend Framework classes.

19

09/03/2005

Extending Configuration Classes
?

org.apache.struts.config package contains all the classes that are in-memory representations of all configuration information in struts-config.xml file

ActionConfig, ActionMapping, ExceptionConfig, PluginConfig, MessageResourcesConfig, ControllerConfig, DataSourceConfig, FormBeanConfig, etc

?

You extend these classes and then specify the extended class with class name attribute in struts-config.xml
20

Under Struts 1.1, all the configuration information specified in the strutsconfig.xml file is internally represented by various configuration classes. And all these classes are in the “org.apache.struts.config” package. And the above slide shows all these configuration classes. And I assume you might be already familiar with ActionMapping or FormBeanConfig classes. Now you can extend (subclass) these classes and then specify them in the appropriate place in the struts-config.xml file where class file name can be specified. So let's take a look at a few cases where some of these classes can be extended and then configured.

20

09/03/2005

Extending ActionServlet Class
?

In Struts 1.0, it is common to extend ActionServlet class since
– –

There was no plugin mechanism ActionServlet handles all the controller functionality since there was no RequestProcessor

? ?

Rarely needed in Struts 1.1 Change web.xml
<servlet> <servlet-name>action</servlet-name> <servlet-class> myPackage.myActionServlet </servlet-class> </servlet>
21

First, let's take a look at a case where you can extend ActionServlet class. As was mentioned before, in Struts 1.0 where there was no plugin mechanism, extending ActionServlet class was a common practice. In Struts 1.1, in which we now have plugin mechanism and introduction of RequestProcessor class, it is rare that you have to extend ActionServlet class. In case you have to, basically the way you can provide your own customized ActionServlet class is to extend the ActionServlet, let's call it myActionServlet, and then configure it in the web.xml as shown above.

21

09/03/2005

Extending RequestProcessor Class
? ?

?

Via <controller> element in struts-config.xml process() method of RequestProcessor class is called before ActionForm class is initialized and execute() method of Action object get called Example in struts-cookbook sample code
<controller processorClass=”org.apache.struts.tiles.TilesRequestProcessor”/>

22

RequestProcessor class was introduced in Struts 1.1 and it took over much of the functionality that ActionServlet does in Struts 1.0. The process() method of RequestProcssor class gets called before ActionForm class is initialized and before calling execute() method of Action object. Since process() method of RequestProcessor class gets called internally by ActionServlet, normally, you don't have to worry about this class. Now if you want to extend it, then you have to do it by explicitly specifying <controller> element as mentioned above.

22

09/03/2005

Extending Action Classes
?

Useful to create a base Action class when common logic is shared among many Action classes

Create base Action class first then subclass it for actual Action classes

23

Now let's see how we can extend Action class. Extending Action class can be useful when you have to create many Action classes and these Action classes share common logic. In that case, what you can do is to create a base Action class then subclass it for actual Action classes.

23

09/03/2005

Extension/Customization:

Using Multiple Struts Configuration File
24

Now let's talk about how you can use multiple Struts configuration files.

24

09/03/2005

Multiple Configuration Files
?

Useful for multi-developer environment

At least, a single struts-config.xml file is not a bottleneck anymore

?

Different from “Multiple modules” support

25

Being able to use multiple Struts configuration files in a multi-developer environment is useful since Struts configuration file is no longer a bottleneck. Please note that this is a different feature from “multiple modules” support which we will talk about later on.

25

09/03/2005

web.xml of struts-example
<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, /WEB-INF/struts-config-registration.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
26

So how do you let Struts framework know that you have multiple con figuration files? Basically you provide common separated configuration fikles as <initparams>.

26

09/03/2005

struts-config-registration.xml of struts-example sample app
<!-This is the Struts configuration file for the registration portion of the example application, using the proposed new syntax. --> <struts-config> <!-- ========== Form Bean Definitions =================================== --> <form-beans> <!-- Registration form bean --> <form-bean name="registrationForm" type="org.apache.struts.webapp.example.RegistrationForm"/> </form-beans> <!-- ========== Global Forward Definitions ============================== -> <global-forwards> <forward name="registration" path="/registration.jsp"/> 27 </global-forwards>

The struts-examples1 sample code has two configuration files - strutsconfig.xml and struts-config-registration.xml files. This slide and the following slide shows the contents of the latter. As you can see this file contains contents of normal struts configuration file such as <form-beans> and <global-forwards> and so on.

27

09/03/2005

struts-config-registration.xml of struts-example
<!-- ========== Action Mapping Definitions ============================== --> <action-mappings> <!-- Edit user registration --> <action path="/editRegistration" type="org.apache.struts.webapp.example.EditRegistrationAction" attribute="registrationForm" scope="request" validate="false"> <forward name="success" path="/registration.jsp"/> </action> <!-- Save user registration --> <action path="/saveRegistration" type="org.apache.struts.webapp.example.SaveRegistrationAction" name="registrationForm" scope="request" input="registration"/> </action-mappings> </struts-config> 28

This slide shows <action-mappings> element.

28

09/03/2005

ForwardAction

29

N ow let's talk about how to extend and customize Struts framework especially plugin mechanism. We are talking about this topic first because the plugin mechanism is going to be used by Validator and Tiles frameworks.

29

09/03/2005

Why ForwardAction?
?

?

If you have the case where you don't need to perform any logic in the Action but would like to follow the convention of going through an Action to access a JSP, the ForwardAction can save you from creating many empty Action classes You don't have to create an Action class

All you have to do is to declaratively configure an Action mapping in your Struts configuration file.

30

There are probably many cases in your application where you want an Action to just forward to a JSP. In fact, the previous tip stated that it's good practice to always front a JSP with an Action. If you have the case where you don't need to perform any logic in the Action but would like to follow the convention of going through an Action to access a JSP, the ForwardAction can save you from creating many empty Action classes. The benefit of the ForwardAction is that you don't have to create an Action class of your own. All you have to do is to declaratively configure an Action mapping in your Struts configuration file.

30

09/03/2005

Example: ForwardAction
?

?

Suppose that you had a JSP page called index.jsp and instead of calling this page directly, you would rather have the application go through an Action class http://hostname/appname/home.do
<action path="/home" parameter="/index.jsp" type="org.apache.struts.actions.ForwardAction" > </action>

31

For example, suppose that you had a JSP called index.jsp and instead of calling this page directly, you would rather have the application go through an Action class. What you can do is set up an Action mapping like this: <action path="/home" parameter="/index.jsp" type="org.apache.struts.actions.ForwardAction" scope="request" validate="false"> </action> When the home action is invoked, the ForwardAction performs a forward to the index.jsp page.

31

09/03/2005

Example: ForwardAction
?

Another way for forwarding
<action path="/home" forward="/index.jsp"> </action>

32

While we are discussing forwarding without having to provide an Action class, it should also be mentioned that you could also use the forward attribute of the <action> element to achieve the same behavior. The <action> element would look like this: <action path="/home" forward="/index.jsp"> </action> Both approaches save you time and help to reduce the number of files needed by an application.

32

09/03/2005

Why ForwardAction?
?

You can also prevent direct access to a JSP page
– –

Move your JSP page under /WEB-INF Use ForwardAction

<action path="/home" forward="/WEB-INF/index.jsp"> </action>

33

Another reason you might want to ue ForwardAction is to prevent direct access to a JSP page by an end-user mostly due to security reasons. You can move the JSP page under WEB-INF directory and then use ForwardAction. Please note that anything under WEB-INF directory cannot be directly addressable by an end-user.

33

09/03/2005

Why ForwardAction?
? ?

Aligned with Model 2 MVC design pattern If you are using <html:link>, you are not using Model 2 MVC (dispatching is done inside JSP page)
<html:link page="/index.jsp"> Top page </html:link>

?

If you are using ForwardAction, you are using Model 2 MVC
<action path="/home" forward="/WEB-INF/index.jsp"> </action>

34

.

34

09/03/2005

DispatchAction

35

N ow let's talk about how to extend and customize Struts framework especially plugin mechanism. We are talking about this topic first because the plugin mechanism is going to be used by Validator and Tiles frameworks.

35

09/03/2005

Why DispatchAction?
?

To allow multiple “related” operations to reside in a single Action class

Instead of being spread over multiple Action classes Related operations typically share some common business logic

?

To allow common logic to be shared

36

What is the motivation of using DispatchAction class? DispatchAction class allows mutliple “related” operations to reside in a single Action class instead of being spread over multiple Action classes. It also allows common logic to be shared among these operations since these related operations typically share some common business logic.

36

09/03/2005

How to use DispatchAction?
?

?

Create a class that extends DispatchAction (instead of Action) In a new class, add a method for every function you need to perform on the service

The method has the same signature as the execute() method of an Action class Because DispatchAction class itself provides execute() method

?

Do not override execute() method

?

Add an entry to struts-config.xml
37

So how do you use DispatchAction? First you create a class that extends DispatchAction class and then add a method for every function you need to perform on the service. These methods should receive same set of parameters and types as a typical execute() method of an Action class. And because execute() method is provided by the DispatchAction class itself, you should not override the execuite() method. Finally you would need an entry to the struts-config.xml file.

37

09/03/2005

Example: ItemAction class extends DispatchAction
public class ItemAction extends DispatchAction { public ActionForward addItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { try { // Code for item add } catch(Exception ex) {//exception} } public ActionForward deleteItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { try { // Code for item deletion } catch(Exception ex){//exception} } }

38

38

09/03/2005

Example: struts-config.xml
<action path="/item" type=" com.infosys.j2ee.sample.web.actions.ItemAction" name="itemForm" scope="request" validate="true" parameter="actionType"/> The method can be invoked using a URL, like this: ItemAction.do?actionType=addItem

39

39

09/03/2005

Example: How To Use it
?

Using URL: Invoke it using a URL

ItemAction.do?actionType=addItem

?

From JSP page
<html:form action="/ ItemAction"> <html:select property="method" size="2"> <html:option value="addItem">Save</html:option> <html:option value="deleteItem">Remove</html:option> </html:select> <html:submit/><html:cancel/> </html:form>
40

.

40

09/03/2005

Declarative Exception Handling

41

41

09/03/2005

Why Declarative Exception Handling?
?

Previously (Struts 1.0), Action class has to deal with all business logic exceptions itself
– –

No common exception handling Rather difficult to implement

42

42

09/03/2005

What is Declarative Exception Handling?
?

Exception handling policy is declaratively specified in struts-config.xml
– –

Exceptions that may occur What to do if exceptions occur From a particular Exception class or super class To an application-relative path

?

Can be global and per-Action
– –

?

Requires a small change to your Action to leverage this feature ...
43

43

09/03/2005

Example in struts-example
<!-- Process a user logon --> <action path="/logon" type="org.apache.struts.webapp.example.LogonAction" name="logonForm" scope="session" input="logon"> <exception key="expired.password" type="org.apache.struts.webapp.example.ExpiredPasswordException" path="/changePassword.jsp"/> </action>

44

44

09/03/2005

How Does it Work?
?

?

?

When an Exception is thrown inside execute() of Action class, processException() method of RequestProcessor class is called processException() method checks if <exception> element is configured for that specific exception type If there is,
– –

Default exception handler creates and stores an ActionError into the specified scope Control is then forwarded to the resource specified in path attribute
45

45

09/03/2005

Example in struts-example1
public ActionForward execute (ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ... throw new PasswordExpiredException(...); ... }

46

46

09/03/2005

Customizing Exception Handling
?

Create a class that extends org.apache.struts.action.ExceptionHandler

Override execute() method
public ActionForward execute( Exception ex, ExceptionConfig exConfig, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response ) throws ServletException;

47

To install your customized exception handler, the first step is to create a class that extends org.apache.struts.action.ExceptionHandler. There are two methods that you can override, execute() and storeException(). In most cases, however, you will just need to override the execute() method. The signature for the execute() method in the ExceptionHandler class is shown here: public ActionForward execute( Exception ex, ExceptionConfig exConfig, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response ) throws ServletException; The method takes in several arguments, including the original exception, and returns an ActionForward object, which directs the controller as to where the request should be forwarded after the exception is dealt with. You can perform whatever behavior you like, but generally you should inspect the exception that was thrown and do something based on the type of exception. Again, the default behavior is to create an error message and forward to the resource specified in the configuration file. An example of why you would want or need 47 to customize this functionality is to support nested exceptions. Suppose the exception contained nested exceptions, and those exceptions also may contain other exceptions. You would need to override the execute() method to create error messages for each of these.

09/03/2005

Customizing Exception Handling
?

Configure the Custom Exception Handler (globally or per action basis)

<global-exceptions> <exception handler="com.cavaness.storefront.CustomizedExceptionHandler" key="global.error.message" path="/error.jsp" scope="request" type="java.lang.Exception"/> </global-exceptions>

48

Once you have created your specialized ExceptionHandler class, you will need to inform the Struts framework to use your version instead of the default Struts exception handler. To do this, you will just need to declare your class in the Struts configuration file; this is the declarative part. You can configure your ExceptionHandler to be used by certain Action mappings or by all Actions. For specific Action mappings, you include an <exception> element inside of the <action> element. To utilize the ExceptionHandler for all Action mappings, you can specify it inside the <global-sections> element. For example, suppose we want to use a customized exception handler called CustomizedExceptionHandler for all Action mappings. The <global-exceptions> element might look like this: <global-exceptions> <exception handler="com.cavaness.storefront.CustomizedExceptionHandler" key="global.error.message" path="/error.jsp" scope="request" type="java.lang.Exception"/> </global-exceptions>

48

09/03/2005

Customizing Exception Handling
?

Multiple Custom Exception Handlers

<global-exceptions> <exception handler="com.cavaness.storefront.CustomizedExceptionHandler" key="global.error.message" path="/error.jsp" scope="request" type="java.lang.Exception"/> <exception handler="com.cavaness.storefront.SecurityExceptionHandler" key="security.error.message" path="/login.jsp" scope="request" type="com.cavaness.storefront.SecurityException"/> </global-exceptions>

49

You can have different exception handlers for different exceptions. In the example above, the CustomizedExceptionHandler was configured to process any exceptions that were children of java.lang.Exception. However, you can create multiple exception handlers, each one worrying about different exception trees. The following XML fragment shows how this can be configured:

49

09/03/2005

Application Modules

50

50

09/03/2005

What are Application Modules?
?

Allows a single Struts application to be split into multiple modules

Each module has its own Struts configuration file, JSP pages, Actions

51

51

09/03/2005

Multiple Application Module Support
?

Necessary for large scale applications

Allows parallel development Support multiple independent Struts configuration files in the same application Modules are identified by an "application prefix" that follows the context path Existing Struts-based applications should be able to be installed individually, or as a sub-application, with no changes to the pages, Actions, form beans, or other code
52

?

Design goals:
– – –

52

09/03/2005

Multiple Application Modules Support
?

Implications of the design goals:
– – – –

"Default" sub-application with a zero-length prefix (like the ROOT context in Tomcat) "Context-relative" paths must now be treated as "sub-application-relative" ActionServlet initialization parameters migrate to the Struts configuration file Controller must identify the relevant subapplication, and make its resources available (as request attributes) APIs must be reviewed for assumptions about there being (for example) only one set of ActionMappings
53

53

09/03/2005

Application Modules: How to configure modules
54

54

09/03/2005

How to set up and use multiple Application Modules?
? ? ?

Prepare a config file for each module. Inform the controller of your module. Use actions to refer to your pages.

55

Very little is required in order to start taking advantage of the Struts application module feature. Just go through the following steps: 1. Prepare a config file for each module. 2. Inform the controller of your module. 3. Use actions to refer to your pages.

55

09/03/2005

Informing the Controller
?

In web.xml
... <init-param> <param-name>config</param-name> <param-value>/WEB-INF/conf/struts-default.xml</param-value> </init-param> <init-param> <param-name>config/module1 </param-name> <param-value>/WEB-INF/conf/struts-module1.xml</param-value> </init-param> ...

56

In struts 1.0, you listed your configuration file as an initialization parameter to the action servlet in web.xml. This is still done in 1.1, but it's augmented a little. In order to tell the Struts machinery about your different modules, you specify multiple config initialization parameters, with a slight twist. You'll still use "config" to tell the action servlet about your "default" module, however, for each additional module, you will list an initialization parameter named "config/module", where module is the name of your module (this gets used when determining which URIs fall under a given module, so choose something meaningful!). For example: ... <init-param> <param-name>config</param-name> <param-value>/WEB-INF/conf/struts-default.xml</param-value> </init-param> <init-param> <param-name>config/module1</param-name> <param-value>/WEB-INF/conf/struts-module1.xml</param-value> </init-param> ... This says I have two modules. One happens to be the "default" module, which has no "/module" in it's name, and one named "module1" (config/module1). I've told the controller it can find their respective configurations under /WEB-INF/conf (which is where I put all my 56 configuration files). Pretty simple! (My struts-default.xml would be equivalent to what most folks call struts-config.xml. I just like the symmetry of having all my Struts module files being named struts-<module>.xml)

09/03/2005

Application Modules: How to switch modules
57

57

09/03/2005

Methods for Switching Modules
?

Two basic methods to switching from one module to another
– –

Use a forward (global or local) and specify the contextRelative attribute with a value of true Use the built-in org.apache.struts.actions.SwitchAction

58

There are two basic methods to switching from one module to another. You can either use a forward (global or local) and specify the contextRelative attribute with a value of true, or you can use the built-in org.apache.struts.actions.SwitchAction.

58

09/03/2005

Global Forward
... <struts-config> ... <global-forwards> <forward name="toModuleB" contextRelative="true" path="/moduleB/index.do" redirect="true"/> ... </global-forwards> ... </struts-config>

59

Here's an example of a global forward:

59

09/03/2005

Local Forward
... <struts-config> ... <action-mappings> ... <action ... > <forward name="success" contextRelative="true" path="/moduleB/index.do" redirect="true"/> </action> ... </action-mappings> ... </struts-config>
60

You could do the same thing with a local forward declared in an ActionMapping:

60

09/03/2005

org.apache.struts.actions.SwitchAction
... <action-mappings> <action path="/toModule" type="org.apache.struts.actions.SwitchAction"/> ... </action-mappings> ...

61

Finally, you could use org.apache.struts.actions.SwitchAction.

61

09/03/2005

How to change module
?

To change module, use URI

http://localhost:8080/toModule.do?prefix=/module B&page=/index.do

?

If you are using the "default" module as well as "named" modules (like "/moduleB"), you can switch back to the "default" module with a URI

http://localhost:8080/toModule.do?prefix=&page=/i ndex.do

62

There are two basic methods to switching from one module to another. You can either use a forward (global or local) and specify the contextRelative attribute with a value of true, or you can use the built-in org.apache.struts.actions.SwitchAction.

62

09/03/2005

Struts & Security
63

63

09/03/2005

Security
?

?

Struts 1.1 and later offers direct support for the standard Java Authentication and Authorization Service (JAAS) You can now specify security roles on an action-by-action basis
<action forward="/pages/roles/Admin.jsp" path="/roles/Admin" roles="admin"/> <action forward="/pages/roles/AnyUser.jsp" path="/roles/AnyUser" roles="admin,role1,tomcat"/>
64

While Struts can work with any approach to user authentication and authorization, Struts 1.1 and later offers direct support for the standard Java Authentication and Authorization Service (JAAS). You can now specify security roles on an action-by-action basis.

64

09/03/2005

SSL Extension (sslext)
?

Extension to Struts 1.1

http://sslext.sourceforge.net

?

?

Extends the ActionConfig class, RequestProcessor , and Plugin classes to define a framework where developers may specify the transmission protocol behavior for Struts applications Within the Struts configuration file, developers specify which action requests require HTTPS transmission and which should use HTTP
65

An extension to Struts 1.1, named sslext, helps solve many of these issues for Struts developers. It extends the ActionConfig class, RequestProcessor, and Plugin classes to define a framework where developers may specify the transmission protocol behavior for Struts applications. Within the Struts configuration file, developers specify which action requests require HTTPS transmission and which should use HTTP. Developers can also specify whether to redirect "improperly-protocoled" requests to the correct protocol.

65

09/03/2005

SSL Extension (sslext)
?

?

Can also specify whether to redirect "improperly-protocoled" requests to the correct protocol <html:link> and <html:form> tag extension

Struts actions specified in either of these tags are analyzed to determine the protocol that should be used in requesting that action The HTML generated by these tags will specify the proper protocol

66

Developers can also specify whether to redirect "improperly-protocoled" requests to the correct protocol. In addition to these extensions, the <html:link> and the <html:form> tags have been extended. In these extensions, the Struts actions specified in either of these tags are analyzed to determine the protocol that should be used in requesting that action. The HTML generated by these tags will specify the proper protocol. An additional custom tag is defined for allowing users to specify the transmission protocol for an individual JSP. This is most often used for form-based authentication pages.

66

09/03/2005

Commons: DynaBeans
67

67

09/03/2005

COMMONS-BEANUTILS
? ?

Pluggable type converters Mapped properties

contact.phone(Work) Transparently supported by BeanUtils and PropertyUtils

?

DynaBeans

68

The Bean Introspection Utilities component of the Jakarta Commons subproject offers low-level utility classes that assist in getting and setting property values on Java classes that follow the naming design patterns outlined in the JavaBeans Specification, as well as mechanisms for dynamically defining and accessing bean properties.

68

09/03/2005

Commons-Beanutils -DynaBeans
public interface DynaBean { public Object get(String name); public Object get(String name, int index); public Object get(String name, String key); public void set(String name, Object value); public void set(String name, int index, Object value); public void set(String name, String key, Object value); }

69

DynaBeans combine the extensibility of JavaBeans with the flexibility of a Map. Defining even the simplest JavaBean requires defining a new class and coding a field and two methods for each property. The properties of a DynaBean can be configured via an XML descriptor. The virtual properties of a DynaBean can't be called by standard Java methods, but work well with components that rely on reflection and introspection. In a Struts application, you can use DynaBeans to describe your HTML forms. This strategy can avoid creating a formal JavaBean subclass to store a few simple properties.

69

09/03/2005

Struts Utilities

70

70

09/03/2005

Utilities
? ?

?

?

org.apache.struts.util package ‘Families’ of classes that solve common web app problems. Suitable for general Java programming and are worth checking out Utilities classes include:
– – – –

Beans & Properties Collection Classes JDBC connection pool Message Resources
71

71

09/03/2005

Utility Classes
?

common-*.jar – Now required for Struts

Might require some package renaming for 1.0.2 Struts apps

?

Many utilities are now located in the Jakarta Commons project
– – – –

http://jakarta.apache.org/commons/ BeanUtils Package org.apache.commons.beanutils Collections Package org.apache.commons.collections Digester Package org.apache.commons.digester

72

72

09/03/2005

BeanUtil & PropertyUtil
? ?

?

Relies on using Java Reflection to manipulate Java Beans Used throughout Struts (IteratorTag, WriteTag) Need to make sure you have a valid bean!
– – –

Null constructor Public class declaration Mutator/Accessor methods

73

73

09/03/2005

XML Parsing
?

?

?

Digester package provides for rules-based processing of arbitrary XML documents. Higher level, more developer-friendly interface to SAX events Digester automatically navigates the element hierarchy of the XML document
– –

Element Matching Patterns Processing Rule

74

74

09/03/2005

Struts and J2EE Patterns
75

75

09/03/2005

Struts and Core J2EE Patterns
Controller
Action Servlet Action Mapping (xml) Action

Model
Service Interface Business Delegate Business Service

Request Client

uses
Response JSP View Action Forward Action Form

Service Locator

View

View Helper

76

76

09/03/2005

Struts and Core J2EE Patterns
Front Controller
PresentationRequestController ActionServlet CreateAccountDispatcher Action

Business Delegate
UserAccountManagerDelegate

Session Facade Composite View
«JSPInclude»

«ServerPage» template.jsp

«EJBSessionBean» UserAccountManagerEJB

+ themenu.jsp «ServerPage» menu.jsp

Compsite Entity
«ServerPage» new_account.jsp «EJBEntityBean» UserAccountEJB
«EJBEntityBean»

CreditCardEJB

«ServerPage» new_account_confirm.jsp

UserAccountValues

CreditCardValues

DataTransfer Object

DataTransfer Object 77

77

09/03/2005

Nested Tag Library

78

78

09/03/2005

The "Nested" Tag Library
?

?

Brings a nested context to the functionality of the Struts custom tag library Written in a layer that extends the current Struts tags, building on their logic and functionality

The layer enables the tags to be aware of the tags which surround them so they can correctly provide the nesting property reference to the Struts system <%@ taglib prefix="nested" uri="http://jakarta.apache.org/struts/tags-nested" %>
79

79

09/03/2005

The "Nested" Tag Library
? ?

Nested tags allow you to establish a default bean for nested property references 1:1 correspondence, and identical functionality, of other Struts tags

Except the "name" property gets set for you automatically ...

80

80

09/03/2005

Example: Scenario
?

Company has many departments

Company bean has a collection of Department beans Department bean has a collection of Employee beans

?

Each department has many employees

81

81

09/03/2005

Example: Suppose You Want To Display the following...

82

82

09/03/2005

Example: Using JSTL for Iterating Nested Beans
COMPANY: <html:text property="companyName"/> <c:forEach items="${companyForm.departments}" var="dept" varStatus="deptStatus"> Department: <html:text property="departments[${deptStatus.index}]. deptName" value="${dept.deptName}" /> <c:forEach items="${dept.employees}" var="emp" varStatus="empStatus"> Employee: <html:text property="departments[${deptStatus.index}]. employees[${empStatus.index}].empName" value="${emp.empName}" /> E-mail: <html:text property="departments[${deptStatus.index}]. employees[${empStatus.index}].email" value="${emp.email}" /> <br/> </c:forEach> </c:forEach>

83

83

09/03/2005

Example: Using Nested Tag for Doing the Same Thing
COMPANY: <html:text property="companyName"/> <nested:iterate property="departments"> Department: <nested:text property="deptName"/> <nested:iterate property="employees"> Employee: <nested:text property="empName"/> E-mail: <nested:text property="email"/> </nested:iterate> </nested:iterate>

84

84

09/03/2005

Example 2:
?

Before using the nested tags:
<bean:write property="address.city"/> <bean:write property="address.state"/> <bean:write property="address.zip"/>

?

After using the nested tags:
<nested:nest property="address"> <nested:write property="city"/> <nested:write property="state"/> <nested:write property="zip"/> </nested:nest>
85

85

09/03/2005

Changes Between Struts 1.0 & 1.1
86

86

09/03/2005

Struts 1.1 ActionServlet
?

Introduction of request processor
– –

Via RequestProcessor class Handles much of the functionality of ActionServlet in Struts1.0
?

ActionServlet in 1.1 is a thin layer

Allows developers to customize the request handling behavior more easily

87

87

09/03/2005

Struts 1.1 Actions
?

Method perform() replaced by execute()
– –

Backwards compatible Change necessary to support declarative exception handling Supports multiple business methods instead of a single execute() method Allows easy group of related business methods

?

Addition of DispatchAction class
– –

88

88

09/03/2005

Changes to web.xml and struts-config.xml
?

web.xml
– –

Serveral initialization parameters removed
?

Uses elements in struts-config.xml

Supports a few new parameters

89

89

09/03/2005

New Features in Struts 1.1
? ? ? ? ? ? ? ?

Plug-ins Dynamic ActionForms Multiple application modules Declative exception handling Validator framework Nested tags Dependency to Commons projects Action-based authorization
90

90

09/03/2005

Roadmap

91

I

91

09/03/2005

New Features in Struts 1.2
? ? ? ?

Some deprecations Validator enhancements DigestingPlugin added MappingDispatchAction added

92

92

09/03/2005

Passion!
93

93