Struts projects will be moved to Struts2 (b)

<! - StartFragment ->
Please Fuzheng heroes





Migrating to Struts 2 - Part II

In the first part of this series , We explained (for Struts developers) the high level architecture, basic request workflow, configuration semantics and differences in the action framework in the new Struts 2 (formerly WebWork) and Struts 1. Armed with this knowledge, migrating an application of any size from Struts to Struts 2 should be simplified.

During the first part of a series of articles, we have introduced Struts development framework for the Struts framework, the basic request workflow, configuration semantics (my understanding is that the method of allocation), as well as Struts and Struts2 different in action. With such knowledge, the project will be of any size migration from Struts to Struts2 will become simple

The Example Application

Sample applications


To keep things simple we are going to choose an example that most people should be familiar with - a weblog. Although simple and perhaps somewhat overused (perhaps not quite as much as the Sun Pet Store), it is an example that doesn't require explaining.

To more concisely define the features, the use cases we will be discussing are:

We have chosen an example may be very familiar with - weblog. Despite the relatively simple, but the spread may be a bit of (the pet store may not be as complete Sun), but this is a case in point, do not need to explain. (Translator: This author's very interesting, reminds me of another saying "real men, do not explain")

The sake of conciseness, we will discuss the use cases are as follows:

  1. Add a new weblog entry
  2. View a weblog entry
  3. Edit a weblog entry
  4. Remove a weblog entry
  5. List all the weblog entries

1. To add a new entity weblog

2. See a webog entities

3. Edit a weblog entities

4. Delete a weblog entities

5. List all entities of the weblog

Breaking it down further, the features we want to implement are those most common to web applications. They consist of create, read, update and delete - more commonly referred to as CRUD. Making these steps easy will greatly increase productivity.

There will also be a common component between the Struts and Struts2 applications, a back-end business service. Here's what it looks like:

Breaking it down further, our web applications are the most common functions, including create, read, update and delete - usually referred to as CURD. To ensure that these simple steps can greatly increase the efficiency of learning.

We have to achieve a common component in the Struts and Struts2 ----- which can use a background of business services, as follows:

public class BlogService (
private static List <Blog> blogs = new ArrayList <Blog> ();
public List <Blog> list () (...)
public Blog create (Blog blog) (...)
public void update (Blog blog) (...)
public void delete (int id) (...)
public Blog findById (int id) (...)
)

This object will support the use cases in our example. To simplify implementation we will instantiate this object in the action for both Struts and Struts2. This would provide unnecessary coupling in a real application, but for our example focusing on the web layer it is sufficient .

SIDEBAR: In Part I we discussed the interface injection style of dependency injection used in the Struts2 actions. This is the primary style used for the injection of object instances that are servlet related (HttpServletRequest, HttpServletResponse, PrincipalProxy, etc.), But it is not the only style used.

Struts2 uses the Spring Framework as the default container, and when doing so the setter method of dependency injection is used. By adding a setter to the action (as shown below), the Struts2 framework will retrieve the correct service from the Spring Framework context and apply it to the action via the setter.

public void setBlogService (BlogService service) (
this.blogService = service;
)

Similar to the interface injection style, we need to include an interceptor - the ActionAutowiringInterceptor interceptor - to the actions interceptor stack. Now, business objects managed by the Spring Framework are injected into Struts2 actions before the action is invoked. Further configuration parameters allow you to set how (by name, by type or automatically) the match between the setter and business object is made.

Example of this object in support of our use case. In order to simplify the process of realization, we will Struts and Struts2 of Action which the object is initialized. This is true of applications which will lead to unnecessary coupling, but because of our focus on the example of web layer, so that it did enough.

Article Tools: In the first part of our discussion of the action in which Struts2 to use interface into the way of dependency injection. This approach is mainly used to inject and Servlet related objects (such as HttpServletRequest, HttpServletResponse, PrincipalProxy, etc.) but this is not the only way.

Sett in Struts2 which function to use dependency injection to achieve when, Struts2 framework will be used by Spring's dependency injection as the default container. Action of them to add a setter method (see below), Struts2 framework will be the framework from the Spring context (context) were to find the right service, and then injected through the setter method to the action which.

public void setBlogService (BlogService service) (
this.blogService = service;
)

And interface into a similar manner, we need to action which interceptors to add a new stack of interceptors - ActionAutowiringInterceptor interceptors. Spring is the framework of business objects being managed, in the Action is called before the, Spring 'business object will be injected into the Actin which Struts2. You can also use other configuration parameters to determine how (through the name, type or automatic) which match the setter method of Action and the business object.

The Struts Application Code

struts framework code


The starting point is going to be a Struts implementation. For each use case there will be an action class, as well as a class for the action form that will be re-used across all the actions that need it. This may not be the most elegant solution for our application (other solutions include using dynamic forms or using a request dispatch action), but it is a solution that all Struts developers should be familiar with. From the knowledge of converting an uncomplicated implementation, you will have the skills and the knowledge of the Struts2 framework to migrate more advanced implementations.

In Part I we spoke about the differences between a Struts and Struts2 action. Another way of looking at the differences is via UML. Here's what the general form of a Struts action looks like:

The first is the realization of Struts. Each use case needs to have a Class Action, ActionForm also need a category (this category ActionForm for the use of all of the Action). Our test with the application may not be elegant (we can use the dynamic form and request dispatch action to make our process better), but such a procedure is the Struts developers are most familiar with. Through a conversion is not complicated by the realization of the knowledge gained, you can migrate the procedures required for more advanced skills and knowledge.

In the first part we discussed the Struts and Struts2 distinction among Actionde. UML, we can also take a look at the difference between the two. The following chart:

Struts projects will be moved to Struts2 (b)

The action form will be used across multiple actions, so let's take a look at it first.

action form can be used between a number of action, we first look at how it is achieved.
public class BlogForm extends ActionForm (

private String id;
private String title;
private String entry;
private String created;

/ / Public setters and getters for all properties
)

As shown in the UML, one restriction is that our form extends the ActionForm class. The second restriction is that the fields are String classes, and hence the getters return String's and the setters accept String's.

The actions that use the action form are the view, create and update actions.

As shown in the UML diagram, there is a constraint that we must carry on the ActionForm type ActionForm. The second constraint is the fileds is String type, getter method returns String, setter method of String as a parameter to accept

The View Action:

public class ViewBlogAction extends Action (

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception (

BlogService service = new BlogService ();
String id = request.getParameter ( "id");
request.setAttribute ( "blog", service.findById (Integer.parseInt (id)));

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

The Create Action:

public class SaveBlogEntryAction extends Action (

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception (

BlogService service = new BlogService ();
BlogForm blogForm = (BlogForm) form;
Blog blog = new Blog ();
BeanUtils.copyProperties (blog, blogForm);

service.create (blog);

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

The Update Action:

public class UpdateBlogEntryAction extends Action (

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception (

BlogService service = new BlogService ();
BlogForm blogForm = (BlogForm) form;

Blog blog = service.findById (Integer.parseInt (blogForm.getId ()));
BeanUtils.copyProperties (blog, blogForm);
service.update (blog);
request.setAttribute ( "blog", blog);

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

All three of these actions follow a pattern:

  • The business object instance is created - as mentioned earlier, we are taking the most direct route to using the business object in the actions. This means that a new instance will be created in each action.
  • Data is retrieved from the request - this is in one of two forms. In the view action, the "id" is retrieved from the HttpServletRequest object directly. In the create and update action the ActionForm is used. The ActionForm is very similar to the HttpServletRequest method, the only difference being that the fields are grouped together within an object.
  • The business object is called - it is now time for the business object to be used. If the parameter (in the view action) is a simple object, it can be used after converting to the correct type (from a String to an Integer) . If the object is a more complex domain object, the ActionForm needs to be converted using the BeanUtil object.
  • The return data is set - if there is data that needs to be returned so that it can be displayed to the user, it needs to be set as an attribute on the HttpServletRequest object.
  • An ActionForward is returned - the last step in any Struts action is to find and return an ActionForward object.

The last two actions, the remove and the list action, are only slightly different. The remove action, as shown below, doesn't use the BlogForm class. By using a request attribute of "id" (similar to the view action) it can perform the necessary work using the business object. As we will see later in the configuration, it doesn't return any data, as the success result is mapped to execute the list action that will retrieve the necessary information once the record has been removed (thus keeping the concerns of the actions separate).

Followed over the following three Action mode

1.business object is created - as we mentioned, we were directly in the Action business object generation. This means that every action which will create a new business object.

2. Data from the request which has been - this is in one of two forms. In the view action of them, "id" which directly obtained from the HttpServletRequest object. In the update action and update action which uses the ActionForm. ActionForm and the HttpServletRequest method is very similar, the only difference is that the target was hit filed an object in which (I understand that as long as the ActionForm through the HttpServletRequest object which can be brought about by the data)

3. Business object is called. The use of business objects now the time has come, if the parameters (in the view Action When the total) is a simple object, which can be converted to be the correct type (from the String transformed into Integer), if the object is a complex domain object (domain object ), then to transform BeanUtil need to use ActionForm;

4. The return of the data set - if there is a need to demonstrate to the customer's data needs to be set to the attributes of the object HttpservletRequest;

5. ActionForward --- a return to any of the Struts of ActionForward which is the last step to find and return an ActionForward object

<! - StartFragment -> The last two action - remove and list action, a little different. remove action, does not require the use BlogForm category. Request as long as the use of the "id" of the attributes (the same as the view action), you can use business objects. Question we will see, it does not return any data, success result is mapped to the specified list action, after the record is deleted, list action will get the necessary information

public class RemoveBlogEntryAction extends Action (

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception (

BlogService service = new BlogService ();
String id = request.getParameter ( "id");
service.delete (Integer.parseInt (id));

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

The list action is different because is uses no input from the user. It simply calls the business service with a no-argument method, and returns to the user the list of domain objects that the service returns. Here it is:

Above the Action and the Action is different from the other, because the Action to accept data from users. Business services just call it the non-parametric method of constructing, and then return to business services through the domain object (domain object, the object is the blog) list.

public class ListBlogsAction extends Action (

public ActionForward execute (ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception (

BlogService service = new BlogService ();
request.setAttribute ( "bloglist", service.list ());

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

The Conversion to Struts2

Converted to Struts2


In Struts2 there are many ways to implement the above application. These vary from the same use-case-per-class approach (as used in Struts) to creating a class hierarchy, or even a single action class for all use cases. The approach we are going to talk about is what I consider to be the most optimized solution - a single class that implements the CRUD functionality.

Additionally, we will keep the list use case separate. This could be incorporated into the same class, but there would be class attributes that are not used in each use case (the Blog class in the list use case, and the list of Blog classes in all the other use cases) which could become confusing.

For Struts2, we are able to show all the action classes in a single UML model.

In Struts2, there are many ways to achieve the above applications. These vary from the same use-case-per-class approach (as used in Struts) to creating a class hierarchy, or even a single action class for all use cases. We will be discussing is the realization I do not think the realization of optimization methods - Use a class to achieve functional CURD.

When the sum in Struts2 that, we can display them in a UMLmodel all of the Action



Each use case is realized with a method on the action. From the UML diagram above, we see that on the BlogAction we have a method for save, update and remove. The view method is implemented using the execute method, that is inherited from the ActionSupport class. Similarly, on the ListBlogAction, the list use case is implemented using the execute method.

For simplicity, three interfaces have been left off of this diagram for the BlogAction. These are the ServletRequestAware interface, the Prepareable interface and the ModelDriven interface.

The first interface is the ServletRequestAware, which we covered in detail in Part I. Using this interceptor provides access to the HttpServletRequest object in the action, which will allow us to place objects back in to the request to be rendered in the JSP's.

The Preparable interface is next, and works in conjunction with the PrepareInterceptor. When using these two pieces together, a prepare method is provided which is called before the execute method. This allows for setup, configuration or pre-population code in the action.

In our case, the prepare method checks whether this is a new blog or a pre-existing one by checking the value of the blogId field. For a non-zero value, the blog model is retrieved and set on the action.

Next is the ModelDriven interface. In the previous article we saw that one of the most profound differences is that in Struts the actions need to be thread-safe, where in Struts2 there is no such restriction. Each action is instantiated and invoked on each request . Having this restriction removed in Struts2 allows the action class to take advantage of class-level attributes and methods (in particular getters and setters). Combining this with interceptor functionality, allows the attributes in the HttpServletRequest to be set directly on the action.

Each use case in which the use of Action to achieve a function. From the UML diagram above we can see in the BlogAction of them save, update and remove methods. view function is to execute methods in which to achieve, this method is inherited from the ActionSuppot category. In ListBlogAction are listed in the user's use case is the execute method in which to achieve.

The sake of simplicity, BlogAction three interfaces are not drawn, the three interface is ServletRequestAware, Prepareable and ModelDriven.

The first interface is ServletRequestAware, this interface in the previous article we discussed them. The use of the blocker action can provide the ability to access HttpServletRequest object so that you can allow us to request the data on them for rendering JSP.

Is the next interfaces Preparable is PrepareInterceptor interface and work together. When the two interfaces at the same time, a prepare method before the call to execute method is called, this method can be used for setup, configuration or pre-population. t

In our use case, the method has been applied to this domain by checking the value of blogid to confirm this is a new blog that already exists or blog. If blogid is a non-zero value, then the blog model will be available, and set them to the Action.

Is the next interfaces ModelDriven. In the previous article, we know Struts and Struts2 one of the largest difference between Struts in Action is necessary, thread-safe, and Struts without this constraint. Each request will generate a new Action object. Struts2 as long as there is no such constraint, we can use them in the Action member variables and member functions (setter and getter). Combination of the interface and the function of the interceptor, which can be directly HttpServletRequest attribute set to the action which

It goes like this:

  • The list of attribute names in the HTTP request is iterated over
  • A setter for the name of the current attribute is searched for on the current action
  • The value for the attribute name is retrieve from the HttpServletRequest
  • The value is converted to the correct type for the setter in the action
  • The converted value is then applied to the action via the setter

The interceptor that provides this functionality is the ParametersInterceptor interceptor.

TIP: When developing an action, if for some reason the values are not being set correctly, a good first step is to ensure that this interceptor is in the stack applied to the action.

In fact, this is a good strategy to follow at all times. When debugging an issue, if there seems to be something out of place or not working the way that is expected, there is a good chance that it is interceptor related. Check the interceptors that are being applied, and the order in which they are being applied. Interceptors may interfere with each other in ways that you may not expect.

Now that we have the string-based form or request attributes being applied to the actions, the next step is to have them applied to the fields of a domain object or value / transfer object. This is very easy. In fact, the only things that you need to do different as a developer is to implement the ModelDriven interface (which has a single getModel () method) and ensure that the ModelDrivenInterceptor is applied to the action.

Process is as follows:

1. Iterative HTTP request which the names of all of the properties;

2. Is there any action to find them and match the current attribute setter method name;

3. From the HttpServletRequest attributes under the name of which to obtain the value of property;

4. The value will be converted to the correct type;

5. Setter method call to action among the set;

Provide these functions is the ParametersInterceptor interceptors.

TIP: When the development of an action which, if for some reason which led to the value of property is not the correct settings, the first step is to confirm to ensure that the interceptor in the interceptor stack, the role of the action.

In fact, there is a very good strategy. When debugging a problem yes. If it is found that the location of something is not or can not work and may be on the interceptor. Check whether the application of the interceptor, the interceptor is enough to correct the order. Interceptors may be hope in a way you do not influence each other.

Now, we have set up a String based on the fomr or request parameters inside Action, Trial next step the data set to the domain object, or value / transfer object. This is very simple. In fact, we as developers only need to do is to achieve ModelDrivern interface (the interface only a getModel () method), and has been set up to really ModelDrivenInterceptor on this action.

Now, instead of finding a setter on the action, the model is first retrieved and checked to see whether it has a setter matching the attribute name. If there is no such setter on the model object, but there is on the action, then the value will be set on the action. We see this flexibility in practice in the BlogAction - as well as the fields for the Blog model object, there is a setId () method on the action. This allows the id of the blog to be set on the action and used in the prepare method to pre-fetch the correct Blog instance, before the values for the fields of the object are set directly on the Blog instance retrieved.

With these two features in place, the implementation of the methods that will be invoked on the action becomes trivial - the specific business service is called, and data to be rendered is placed in the HttpServletRequest.

Now, first of all objects in the model to find setter method inside to see if the setter method name and attributes match, then the corresponding attribute set to model them, rather than in the Action were to find setter method. If none of the setter methods of model, but in the action which, then the value attribute will be set into action. We will BlogAction in the process of realization of this method see flexibility - like the blog model the object in which, in the action of which there is a setId () method. This blog's ID can be set up in the action were, and prepare method (which is an excuse Preparable method), which prefetch objects blog right, This allows the id of the blog to be set on the action and used in the prepare method to pre-fetch the correct Blog instance, before the values for the fields of the object are set directly on the Blog instance retrieved.

Because these two properties, called business services, as well as rendering the data will need to set them on the HttpServletRequest is meaningless.

public class BlogAction extends ActionSupport
implements ModelDriven, Preparable, ServletRequestAware (

private int blogId;
private Blog blog;
private BlogService service = new BlogService ();
private HttpServletRequest request;

public void setServletRequest (HttpServletRequest httpServletRequest) (
this.request = httpServletRequest;
)

public void setId (int blogId) (
this.blogId = blogId;
)

public void prepare () throws Exception (
if (blogId == 0) (
blog = new Blog ();
) Else (
blog = service.findById (blogId);
)
)

public Object getModel () (
return blog;
)

public String save () (
service.create (blog);
return SUCCESS;
)
public String update () (
service.update (blog);
request.setAttribute ( "blog", blog);
return SUCCESS;
)

public String remove () (
service.delete (blogId);
return SUCCESS;
)

public String execute () (
request.setAttribute ( "blog", blog);
return SUCCESS;
)

)

Last is the list action. It also requires access to the HttpServletRequest object to provide data to render and, hence, must implement the ServletRequestAware interface. But, because it takes no input to perform the use case, there is no need for the additional interfaces . Here is the implementation:

Among the list action, but also need access to HttpServletRequest object to provide the need for rendering the data, it is necessary to achieve ServletRequestAware interface. However, this use case in which there is no input, so the interface does not require the achievement of other

public class ListBlogsAction extends ActionSupport implements ServletRequestAware (

private BlogService service = new BlogService ();
private HttpServletRequest request;

public void setServletRequest (HttpServletRequest httpServletRequest) (
this.request = httpServletRequest;
)

public String execute () (
request.setAttribute ( "bloglist", service.list ());
return SUCCESS;
)

)

This completes our implementation of the action code. In the final part of the series we will be able to simplify the action even further - when we combine it with a new Struts2 user interface.

These are all of our code to achieve action. During the last part of a series of articles, we will use struts2 new user interface will become more simple action

Configuring the Actions

Configuration Actions


Before we can invoke any of the actions from a browser we need to configure them. This is achieved via XML configuration files.

For Struts, we use a file named "struts-config.xml" in the WEB-INF directory, in which we will need to configure two elements - the action form and the action itself. The Struts2 configuration, using a file named "struts . xml 'in the classes directory, is a little more complex, as we need to configure interceptors, as well as actions.

The Struts configurations' form-beans node is easy, with attributes for a unique name (provided by the developer) and a type, which is the package and name of the ActionForm class.

We call them in the browser action, we must first be configured. Configuration is carried out through the XML document.

In Struts, we use in the WEB-INF folder of the "struts-config.xml" file, the document need to configure the two elements - action form and action. Struts2 configuration in which the use of them in the classes directory of the "struts.xml" file, slightly more complicated than the struts that we need to configure the interceptors.

Struts configuration in which "form-beans" node is very easy and requires a unique name (by the developers) and a type, the type of packet is ActionForm name + class name
<struts-config>

<form-beans>
<form-bean name = "blogForm"
type = "com.fdar.articles.infoq.conversion.struts.BlogForm" />
</ form-beans>
...

</ struts-config>

There are three different ways that we are configuring the actions in the example application.

1. Redirect Configuration

In this configuration no action class is used. Instead, the request is forwarded onto a JSP with no backend processing.

In the Struts configuration, each mapping provides a path element that maps to the URL that will invoke the action, ie the path "/ struts / add" maps to the URL "/ struts / add.do". There is also a forward attribute that provides the URL to forward to - in this case, "/ struts / add.jsp"

We have three ways to configure the sample program which action

1.Redirect configuration

In such a configuration which does not apply action, and there is no back-end processing, is to launch a request to a JSP.

Configuration in the struts, we call in the action which will provide a mapping of each element and a URL path mapping between. ie the path "/ struts / add" mapped to "/ struts / add.do". There is also a Jump forward elements to provide the URL - which in this use case is "/ struts / add.jsp"

<struts-config>
...

<action-mappings>

<action path="/struts/add" forward="/struts/add.jsp"/>
...

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

The Struts2 configuration has more structure to it.

In Struts2, the more the structure of configuration:

<struts>
<include file="struts-default.xml"/>

<package name="struts2" extends="struts-default" namespace="/struts2">

<action name="add">
<result> / struts2/add.jsp </ result>
</ action>
...

</ package>
</ struts>

The first thing you have probably noticed is that instead of an action-mappings node, there is an include and package node. Struts2 modularizes the configuration by allowing you to sub-divide the configuration into an arbitrary number of files. Each file has exactly the same structure, just different names.

The include node, using the file attribute for the name of the file, inserts the contents of an external file into the current file. The package node groups together actions, and must have a value for the name attribute that is unique.

In the Struts action configuration, the path attribute specified the entire URL. In Struts2, the URL is a concatenation of the namespace attribute of the package, the name attribute of the action node, and the action extension (defaulting to ". Action") . The action above would then be invoked by "/ struts2/add.action".

The last attribute of the package node is the extends attribute. As well as providing namespace separation, packages also provide structure. By extending another package you gain access to its configuration - actions, results, interceptors, exceptions, etc. The "struts2" package above extends the "struts-default" package (defined in the included file "struts-default.xml") - this is the master include file that should be the first line of all configurations. It will save you typing by providing all the default configurations for result types, interceptors, and the more common interceptor stacks that can be used.

Last is the result node, and is just a value for the URL to forward to. What we have left out are the name and type attributes. Unless you are changing these from the default values, you can leave them out, making the configuration simpler . The default values render a JSP for a "success" result being returned from the action.

We first noted is not action-mappings node, but include and package node. sturts2 a modular configuration allows you to configure more than one person down to the document. The structure of each document as just a different name.

Include nodes in, file attribute value is the name of a document, the contents of the external file into the current document. node will package together all of the action, aciton the name of each attribute value must be unique.

In the struts action which the oh ah, path attribute entities developed a URL. Struts2 them in, URL is a property associated with the following things - package of namespace attribute, action attribute node and the action of the name of the extension (the default is ". Action"). Above action should be used "/ sturts2/add . action "to call.

package node is an attribute of the last extends. package not only provides namespace separator, but also provide the organizational structure. Through the succession of other configuration files, you can visit its action, resulet, interceptor and unusual and so on. In the above configuration file them, "struts2" package inherited the "struts-default" (defined in include file "struts-default.xml" them that), this document should contain all of the configuration file to include the first line on. It will provide you with all the default configuration, including the result types, interceptors, and interceptors common stack;

In the result, the configuration is the goal of Jump URL. We omitted the name of the label and the type attribute. Unless you want to modify the default values can be omitted on their structure, which allows simple configuration. By default, the action which the return of "success" can be played up on the JSP.

2. Action Configuration

action configuration

An action class is invoked to provide backend processing, the result from processing is defined in the configuration and the user redirected to the corresponding view.

This is the next step from a configuration that is a redirect configuration. There are two additional attributes on the action node. The type attribute provides the package and name of the action class, and the scope attribute ensures that any form beans (if used) are placed in the request scope.

Instead of a forward attribute, the action configuration uses a forward node. There should be one node for each and every result that the action can return.

Call for action to deal with the background and return to a definition in the configuration of which result, and then the user will be redirected to the appropriate view.

This is the configuration file in which the role of the redirect. Node in the action of which the other two attributes, type attribute specifies the action of the package name + class name, scope attribute is specified on the form baen to request them.

Configuration in the action which the use of forward nodes, rather than the use of forward attribute. This will return to action for each possible outcome of a forward configuration
<struts-config>
...

<action-mappings>

<action path = "/ struts / list" scope = "request"
type = "com.fdar.articles.infoq.conversion.struts.ListBlogsAction">
<forward name="success" path="/struts/list.jsp"/>
</ action>
...

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

In the case of an action configuration, the XML for the Struts2 configuration is similar to before. The only difference being that the package and name of the action to be invoked is provided via the class attribute on the action node.

Action in this case which, struts2 similar configuration and in front. The only difference is the action of the package name and class name through the action of which the class attribute node to set up.

<struts>
...

<package name="struts2" extends="struts-default" namespace="/struts2">

<default-interceptor-ref name="defaultStack"/>

<action name = "list"
class = "com.fdar.articles.infoq.conversion.struts2.ListBlogsAction">
<result> / struts2/list.jsp </ result>
<interceptor-ref name="basicStack"/>
</ action>
...

</ package>
</ struts>

If a method other than the execute method is to be invoked (which will be the case for most of the configurations referencing the BlogAction class), a method attribute provides the name of the method. In the example below, the update method would be invoked .

If you want to call the execute method in addition to other methods (which will be the case for most of the configurations referencing the BlogAction class), the need for action to configure a node which attributes method. Like the following example will call the update method.

<action name = "update" method = "update"
class = "com.fdar.articles.infoq.conversion.struts2.BlogAction">
...
</ action>

The difference comes from the default-interceptor-ref and the interceptor-ref nodes. In Part I, we saw how the request passes through a series of interceptors before the action is invoked, these nodes configure the interceptors. The default-interceptor-ref node provides the name of the interceptor stack to use as the default for the package. When the interceptor-ref node is provided, it overrides the default interceptor (the name attribute on the interceptor-ref node can reference either a single interceptor or a stack of interceptors that have been previously configured). Additionally, multiple interceptor-ref nodes can be provided, with processing occurring in the order that they are listed.

Let us look at the default-interceptor-ref and the interceptor-ref distinction between nodes. In the first part, we see that in action before the call, reuqest will be through a series of interceptors. default-interceptor-ref the node specified by a package to use the default interceptor stack. If there is interceptor-ref node, it will override the default interceptors (interceptor-ref node can use the name attribute of the statement before any interceptors or interceptor stack). If there are a number of interceptor-ref node, then the order of their implementation is the order of their rank.

3. Post-Redirect Configuration

Configuration 3.Post-Redirect

The final configuration we are using is for submitting forms when there is an additional requirement that refreshing the resulting page should not re-submit the form. This is known as the "post-redirect pattern" or, more recently, "flash scope."

As this is a form, we need to specify the ActionForm that Struts will be using. This is achieved by providing the name of the form (configured above) in the name attribute of the action node. The only other change that is needed is setting the redirect attribute to true in the forward node.

We are the last of the configuration process is to ensure that we will not submit the issue of duplication. This is known as the "post-redirect pattern" or, more recently, "flash scope."

We need to specify a form for this ActionFOrm for use Struts. We need to name the action node to provide the form name attribute value (configured in front of us). In addition, we also need to forward the redirect attribute node value to true.

<struts-config>
...

<action-mappings>
<action path = "/ struts / save"
type = "com.fdar.articles.infoq.conversion.struts.SaveBlogEntryAction"
name = "blogForm" scope = "request">
<forward name="success" redirect="true" path="/struts/list.do"/>
</ action>
...

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

Rather than augmenting the existing configuration, Struts2 provides the post-redirect functionality through a new type of result. So far we have used the default "dispatch" result type, but there are many different result types available. The result used here is the " redirect "type.

Struts2 them in through the use of a new type of result to achieve the post-redirect function. So far we need to use the default "dispatch" result types but there are many other types can be used, where we use the "redirect" type.
<struts>
...

<package name="struts2" extends="struts-default" namespace="/struts2">

<action name = "save" method = "save"
class = "com.fdar.articles.infoq.conversion.struts2.BlogAction">
<result type="redirect"> list.action </ result>
<interceptor-ref name="defaultStack"/>
</ action>
...

</ package>
</ struts>

Once again, we are using the default result of "success".

Once again, we used the default "succes" result type

Wrap-Up

Summary


We've been able to cover a lot in this article, but there are some things that we didn't have time for. For a better understanding of the framework and additional implementation options, here is a short list of things to take a look at:

  • Configuring interceptors and interceptor stacks - take a look at the "struts-default.xml" file in the struts2-core JAR file for examples. Creating your own interceptors for cross-cutting application features can be a great time saver, and the examples in "struts-default.xml" will show you how to configure your own application-based interceptor stacks that includes the new interceptor.
  • Wildcard patterns in configuration files - as well as typing everything out, there is an option of using wildcard patterns in Struts2. This is a port of the Struts implementation to Struts2.
  • Utilize UI property maps using the ParameterAware interface - instead of having a model / transfer / value object or specific attributes on a class, you can configure Struts2 to place all the request or form attributes into a map in the action. This simulates the dynamic form feature of Struts.

Another question you might be asking yourself is "does this really work with the same UI?" - And the answer is yes. I have included the full source code for the examples in this article, and you will see from these that the only change necessary is to modify the extension of the URL being called (from ". do" to ". action"). Additionally, the Struts taglibs (for forms) could have been easily used instead of JSTL. I will leave this as an exercise for interested readers.

In the next and final article in the series we look at the user interface. We will talk about the architecture; look into themes and tags; talk about how validation fits into the picture; and discuss ways to re-use code using UI components. After which, we will have a fully transformed application.

In this article we cover a lot of them, but there are still some things we did not have time to finish. In order to better understand the framework and the realization of additional options, we provide a list of:

1. Configured interceptors and interceptor stacks - look at the struts2-core JAR file "struts-default.xml" document example. Create your own interceptors and cross-cutting application, it saves a lot of time. In the "struts-default.xml" file which will tell you the example by including a new interceptors, to configure your own applications based on the interceptor stack.

2. Wildcard mode configuration file - as well as typing everything out, in which Struts2 can also use wildcard patterns. This is a port of the Struts implementation to Struts2.

3. ParameterAware interface through which the use of UI attributes - in addition to the use of category model / transfer / value objects, you can configure Struts2 all Add request or action parameters which form a map. This is to imitate the dynamic form which sturts characteristics.

You may have a question - "If the UI is exactly the same as you can," the answer is yes. I included this example all the source code, you can use this code to understand the characteristics of the above, you have to do is change the URL by calling the extension (from the ". Do" into ". Action"). In addition Struts tags can easily be JSTL alternative. If you are interested, you can try.

In this series were the last article we discussed the user interface. We will discuss the architecture, theme and the tag, to discuss how to verify the picture, as well as through the UI components to increase code reusability. At that time, we will get a good full conversion applications.
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Struts projects will be moved to Struts2 (b)

  • hibernate using c3p0 connection pooling

    Private http://www.lifevv.com/tenyo/doc/20070605102040991.html c3p0 for open source's JDBC connection pool, with the release hibernate. This article describes how to use the hibernate configuration in c3p0. c3p0 connection pool configuration is v ...

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • Build flex + spring + blazeds + hibernate application

    Build flex + spring + blazeds + hibernate application First, set up the project blazeds 1, will blazeds.war extract to a directory, such as: myflex /; 2, set up java works were such as: MyFlex, in the orientation of selection create project from exis ...

  • Process migration from tomcat to websphere changes

    Process migration from tomcat to websphere changes Because customers use the web application server software used by different what tomcat5, tomcat6, websphere5.1, websphere6.1, weblogic8, and so on, and the software used inconsistent standards, ibm's

  • Hibernate connection pool configuration

    Hibernate connection pool configuration <! - Jdbc -> <property name="connection.driver_class"> oracle.jdbc.driver.OracleDriver </ property> <property name="connection.url"> jdbc: oracle: thin: @ 10.203.14.132:15

  • hibernate generic generic DAO

    package org.lzpeng.dao; import java.io.Serializable; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.criterion.Criterion; import org.springside.modules.orm.hibernate.Page; /** * * @version 2009-1-10 *

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Hibernate secondary cache

    Hibernate cache: 2-bit cache, also known as process-level cache or SessionFactory level cache, secondary cache can be shared by all of the session Cache configuration and the use of: Will echcache.xml (the document code in hibernate package directory ...

  • Hibernate's lazy strategy

    hibernate Lazy strategy can be used in: <class> tag, it can be true / false Tags can <PROPERTY> values true / false type of necessary tools to enhance <set> <list> can tag values true / false / extra <many-to-one> <on ...

  • J2EE questions Noodles

    2. Abstract class and interface difference (1) interface can be multiple implements, can only be a single abstract class extends (2) only the definition of interfaces, abstract class can have the definition and implementation (3) the definition of the def

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries