Start using the commons chain (first part) [Pick]

xiaoxiao2021-04-06  290

Summary: As a program developer, we often need to apply object-oriented methods to an actual procedural system. Business analysts and managers describe such systems often do not use classes and sequence diagrams, but flow diagrams and workflow charts. But in any case, use more flexibility when using object-oriented methods to solve these problems. Object-oriented design patterns provide useful structures and behaviors to describe such sequence, such as template method [GOF] and Chain of Responsibility [GOF].

Article tool

Collect

Voting score

Comment

copy Link

Start using Commons Chain (Part 1)

Author: Bill Siggelkow (author of Jakarta Struts Cookbook)

Translator:

Niuji

Copyright Notice: Any website that is authorized by Matrix, please be sure to indicate the original source and author information and this statement by hyperlink.

Author: Bill Siggelkow;

Niuji

Original address:

http://www.onjava.com/pub/a/onjava/2005/03/02/commonchains.html

Chinese address:

Http://www.matrix.org.cn/resource/Article/44/44049_commons chain.html

Keywords: commons chain

As a program developer, we often need to apply object-oriented methods to an actual system. Business analysts and managers describe such systems often do not use classes and sequence diagrams, but flow diagrams and workflow charts. But in any case, use more flexibility when using object-oriented methods to solve these problems. Object-oriented design patterns provide useful structures and behaviors to describe such sequence, such as template method [GOF] and Chain of Responsibility [GOF].

Jakarta Commons Subject Chase CHAIN ​​combines the above two modes into a multiplexed Java framework for describing the sequence of processing. This framework developed in the Jakarta Commons Project community has been widely accepted and used in many interesting applications, especially he is used by the Struts and Shale application framework as the basic mechanism for processing HTTP request processing. You can use Commons Chain when you need to define and perform a set of continuous steps.

As for classic design patterns, developers and architects generally use the template method modeling sequence. The method of using an abstract parent class definition in the template method (Template method): the step of processing, the specifically implemented subclass. Of course, the parent class can also provide a default implementation for the methods used by the algorithm.

Since the template method depends on inheritance - subclasses must inherit the parent class defined algorithm - therefore use this mode software to show a tight coupling and lack flexibility. In addition, due to the implementation of the type to add your own behavior, you must expand the parent class, the ditch is a picker every squat, the mosa, the public, Wo, the maid, the screen, the screen, the hills, the midney feet, the MMons chain uses the configuration file definition algorithm , Resolve the configuration file when the program is running, so that this problem is solved.

Now let's take a look at the work of Commons Chain. We started from a manual example: the commercial process of the used car salesman. The following is the step of the sales process:

1. Get user information

2. Trial

3. Negotiation sale

4. Arrange finance

5. End sales

It is now assumed to use the template method modeling. First establish an abstract class defined algorithm: Listing 1

public abstract class SellVehicleTemplate {public void sellVehicle () {getCustomerInfo (); testDriveVehicle (); negotiateSale (); arrangeFinancing (); closeSale ();} public abstract void getCustomerInfo (); public abstract void testDriveVehicle (); public abstract void negotiateSale (); Public abstract void arrarangefinancing (); public abstract void clossale ();

Now let's take a look at how to implement this process with Commons Chain. First, download Commons Chain. You can download the latest ZIP or TAR file directly, or you can detect the latest code from the CVS or Subversion source library. Unzip the package file and put the commons-chain.jar into your classpath.

Using Commons Chain implements this business process, you must write each step in the process into a class, this class needs to have a PUBLIC method Execute (). This is the same as the traditional command pattern (Command Pattern). The following is a simple implementation of "getting user information":

Listing 2

package com.jadecove.chain.sample; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; public class GetCustomerInfo implements Command {public boolean execute (Context ctx) throws Exception {System.out .println ("Get Customer Info"); CTX.PUT ("Customername", "George Burdell"); Return False;}}

This class does not do a lot of work because it is just a demonstration. The username is placed in the CONTEXT object CTX. This context object is connected to each command. This object will be imagined to imagine a hash table according to the keyboard access value. All subsequent commands can access the username just placed. The implementation of TestDriveVehi, Negotiatesale and ArrangeFinancing commands is just simple printing.

Listing 3

package com.jadecove.chain.sample; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; public class TestDriveVehicle implements Command {public boolean execute (Context ctx) throws Exception {System.out .println ( "Test drive the vehicle"); return false;}} public class NegotiateSale implements Command {public boolean execute (Context ctx) throws Exception {System.out.println ( "Negotiate sale"); return false;}} public class ArrangeFinancing implements Command {public boolean execute (Context ctx) throws Exception {System.out.println ( "Arrange financing"); return false;}} CloseSale extracted from the user name into GetCustomerInfo Context object, and printed.

Listing 4

package com.jadecove.chain.sample; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; public class CloseSale implements Command {public boolean execute (Context ctx) throws Exception {System.out .println ("CONGRATULATIONS" CTX.Get ("Customername") ", You Bought A New Car!"); Return False;}}

Now you can define this process into a sequence (or "command chain").

Listing 5

package com.jadecove.chain.sample; import org.apache.commons.chain.impl.ChainBase; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; import org.apache.commons .chain.impl.ContextBase; public class SellVehicleChain extends ChainBase {public SellVehicleChain () {super (); addCommand (new GetCustomerInfo ()); addCommand (new TestDriveVehicle ()); addCommand (new NegotiateSale ()); addCommand (new ArrangeFinancing ()); addCommand (new CloseSale ());} public static void main (String [] args) throws Exception {Command process = new SellVehicleChain (); Context ctx = new ContextBase (); process.execute (ctx);} } Run this class will output the following results:

Get Customer Infotest Drive The Vehicles Financongratulations George Burdell, you bought a new car!

Let's take a look at the class and interface we use.

figure 1

The relationship between the COMMAND class and the CHAIN ​​is the example of Composite Pattern [GOF]: Chain is not only made of multiple Command, but also it is Command. This allows you to make you very easy to replace a single command to chain composed of multiple commands (Command). This method defined by the Command object is represented by a direct command:

Public Boolean Execute (Context Context);

The parameter context is just a collection of name-value. Interface Context is here as a tag interface: it expands java.util.map but does not add any special behavior. In contrast, class ContextBase not only provides the implementation of MAP and increases a feature: attribute - domain transparency. This feature can operate the JavaBean domain by using the MAP PUT and GET method, of course, these domains must be defined using standard Getfoo and setfoo methods. Those values ​​set through the "setter" method of JavaBean can be obtained by the corresponding domain name, with the MAP GET method. Similarly, those settings set with MAP can be obtained by JavaBean's "getter" method.

For example, we can create a dedicated Context provides explicit CustomerName property support.

Listing 6

package com.jadecove.chain.sample; import org.apache.commons.chain.impl.ContextBase; public class SellVehicleContext extends ContextBase {private String customerName; public String getCustomerName () {return customerName;} public void setCustomerName (String name) { This.customername = name;}} Now you can use the general attribute access operation of MAP, which can also use explicit JavaBean access and modification of the domain, which will produce the same effect. But first you need to instantiate SellveHiceContext when running SellveHicleChain instead of ContextBase.

Listing 7

Public static void main (string [] args) THROWS Exception {command process = new selvehiclech (); context ctx = new selvehicleContext (); process.execute (ctx);}

Although you don't change the method of saving your username in GetCustomerInfo - Still using CTX.PUT ("Customername", "George Burdell") - You can get your username with the getCustomerName () method in CloseSale.

Listing 8

public boolean execute (Context ctx) throws Exception {SellVehicleContext myCtx = (SellVehicleContext) ctx; System.out.println ( "Congratulations" myCtx.getCustomerName () ", you bought a new car!"); return false;}

Those commands that depend on type security and explicit domains (Command) can take advantage of standard Getter and Setter methods. When some new commands (Command) are added, they do not take into account the specific implementation of Context, directly through the MAP GET and PUT operation properties. Regardless of the mechanism, the ContextBase class ensures that the command (Command) can be interoperable through context.

The following example shows how to build and execute a set of order commands using the API of the Commons Chain. Of course, like most Java software now, Commons Chain can use the XML file as a configuration file. You can define the steps of the Car Sales process in the XML file. This file has a normative name chain-config.xml.

Listing 9

chain profile can contain multiple chain definitions, these chain definitions can be collected Copying point. In this example, the chain is defined in a default catalog. In fact, you can define the catalog of multiple names in this file, each catalog, you can have your own chain.

Now you can load catalogs and get the specified chain using the class of COMMONS Chain, without having to define a set of commands in the program like SellveHicleChain:

Listing 10

package com.jadecove.chain.sample; import org.apache.commons.chain.Catalog; import org.apache.commons.chain.Command; import org.apache.commons.chain.Context; import org.apache.commons.chain .config.ConfigParser; import org.apache.commons.chain.impl.CatalogFactoryBase; public class CatalogLoader {private static final String CONFIG_FILE = "/com/jadecove/chain/sample/chain-config.xml"; private ConfigParser parser; private Catalog catalog; public CatalogLoader () {parser = new ConfigParser ();} public Catalog getCatalog () throws Exception {if (catalog == null) {parser.parse (. this.getClass () getResource (CONFIG_FILE));} catalog = CatalogFactoryBase.getInstance (). Getcatalog (); return catalog;} public static void main (string [] args) throws exception {catalogloader loader = new catal ogLoader (); Catalog sampleCatalog = loader.getCatalog (); Command command = sampleCatalog.getCommand ( "sell-vehicle"); Context ctx = new SellVehicleContext (); command.execute (ctx);}} Chain read using Commons Digester Take and parse the configuration file. So you need to add Commons Digester.jar to ClassPath. I used 1.6 versions and work very well. Digester uses Commons Collectios (I use of 3.1), Commons Logging (Version 1.0.4), Commons BeanuTils, so you also need to add their JAR files to classpath. After joining these JAR, CatalogLoader can be compiled and running, and its output is identical to the other two tests.

Now you can define a chain in the XML file and you can get this chain in the program (don't forget the chain is also a command), which extension can be said to be unlimited. Suppose the process "Arrangements" is actually handled by a fully separated business sector. This department hopes to build its own workflow for this sales. Chain provides a nested chain to achieve this requirement. Because the chain itself is a command, you can replace a single-use command with reference to another chain. Below is the definition of the chain of new processes: Listing 11

Commons Chain provides a commonly used command lookupCommand to find and perform another chain. Attribute Optional is used to control how to deal with when the specified nested chain is not found. Optional = true, even if the chain is not found, the process will continue. Conversely, LookUpCommand will throw an IllegaLargumentException to tell the specified command to be found.

In the three cases, the command chain will end:

1. Command's Execute method Returns TRUE

2. Run the end of the chain

3. Command throw an exception

When the chain is completely processed, the command returns True. This is the basic concept of Chain of Responsibility. Processing from a command to another until a command (Command) has handled this command. If there is still no processing back to TRUE at the end of the command sequence, it is assumed that the chain is ended normally. When there is a command to throw an error, the chain will end properly. In Commons Chain, if there is an error, the execution of the chain will be interrupted. Whether it is a runtime error or an application error (Application Exception), it will be thrown into the chain caller. However, many applications require a clear handling of errors defined outside the command. Commons Chain provides a Filter interface to meet this request. Filter inherited Command and added a method called PostProcess.

Public Boolean PostProcess (Context Context, Exception Exception);

As long as the Filter's Execute method is called, the Commons Chain will ensure that the Filter's PostProcess method is called regardless of whether the error is thrown during the execution of the chain. The same as the Servlet filter (Filter) is executed in the order in which they are in the order in the chain. Similarly, Filter's PostProcess method is executed in reverse. You can use this feature to implement your own error handling. Below is a Filter for handling errors in our example:

Listing 12

package com.jadecove.chain.sample; import org.apache.commons.chain.Context; import org.apache.commons.chain.Filter; public class SellVehicleExceptionHandler implements Filter {public boolean execute (Context context) throws Exception {System.out .println ( "Filter.execute () called."); return false;} public boolean postprocess (context context, Exception exception) {if (exception == null) return false; System.out.println ( "Exception" exception .getMessage () "occrred."); return true;}}

Filter is the same as the definition in the configuration file.

Listing 13

The execute method of the Filter is called by the defined sequence. However, its PostProcess method will be executed after the chain is executed or throws an error. When an error is thrown, the PostProcess method will return TRUE after processing, indicating that the error handling has been completed. The implementation of the chain does not end this, but in essence, this error is captured and will not throw out. If the PostProcess method returns false, the error will continue to throw out, and then the chain will end properly.

Let us assume arrangefinan to throw errors because the user credit card is damaged. SELLVEHICLEEXCEPTIONHANDLER can capture this error, the program output is as follows:

Filter.execute () Called.get Customer Infotest Drive The Vehiclenegotiate SaleException Bad Credit Occurred.

After the filter (Filter) and sub-chain technology, you can make a very complex workflow.

Commons chain is a very promising framework, is still developing, new features are frequently added thereto. In the next article about Commons Chain, we will study how Struts 1.3 uses Commons Chain.

Struts 1.3 replaces the original processing HTTP request with the class completely using the COMMONS CHAIN. If you have custom-made Struts request processing (Request Processor), you will find that Commons Chain brings good flexibility to the program when it is handling this issue.

Resource

· Matrix-Java Developer Community:

http://www.matrix.org.cn

· Onjava.com:

Onjava.com

转载请注明原文地址:https://www.9cbs.com/read-132368.html

New Post(0)