Modified: commons/proper/chain/trunk/apps/example1/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/example1/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java?rev=1327509&r1=1295180&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/apps/example1/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java (original) +++ commons/proper/chain/trunk/apps/example1/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java Wed Apr 18 13:41:56 2012 @@ -19,10 +19,13 @@ package org.apache.commons.chain2.apps.e import org.apache.commons.chain2.Command; import org.apache.commons.chain2.Context; +import org.apache.commons.chain2.web.servlet.ServletWebContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.chain2.web.servlet.ServletWebContext; +import javax.servlet.ServletException; import javax.servlet.RequestDispatcher; +import java.io.IOException; +import java.lang.RuntimeException; /** * <p>Foo Command</p> @@ -30,7 +33,7 @@ import javax.servlet.RequestDispatcher; * @version $Revision$ $Date$ */ -public class ForwardCommand implements Command { +public class ForwardCommand implements Command<String, Object, ServletWebContext> { private Log log = LogFactory.getLog(ForwardCommand.class); @@ -64,22 +67,26 @@ public class ForwardCommand implements C * @return <code>false</code> so that processng will continue * @throws Exception If an error occurs during execution. */ - public boolean execute(Context context) throws Exception { - - String uri = getForward(context); - if (uri != null) { - if (log.isDebugEnabled()) { - log.debug("Forwarding to " + uri); - } - ServletWebContext swcontext = (ServletWebContext)context; - RequestDispatcher rd = swcontext.getContext().getRequestDispatcher(uri); - rd.forward(swcontext.getRequest(), swcontext.getResponse()); - return true; - } else { - if (log.isDebugEnabled()) { - log.debug("No forward found"); + public boolean execute(ServletWebContext context) { + try { + String uri = getForward(context); + if (uri != null) { + if (log.isDebugEnabled()) { + log.debug("Forwarding to " + uri); + } + RequestDispatcher rd = context.getContext().getRequestDispatcher(uri); + rd.forward(context.getRequest(), context.getResponse()); + return true; + } else { + if (log.isDebugEnabled()) { + log.debug("No forward found"); + } + return false; } - return false; + } catch (ServletException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); } } @@ -89,7 +96,7 @@ public class ForwardCommand implements C * @param context The {@link Context} we are operating on * @return The uri to forward to */ - protected String getForward(Context context) { + protected String getForward(ServletWebContext context) { String uri = (String)context.get("forward"); if (uri == null) { uri = getForward();
Propchange: commons/proper/chain/trunk/apps/example2/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Wed Apr 18 13:41:56 2012 @@ -0,0 +1 @@ +target Modified: commons/proper/chain/trunk/apps/example2/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/example2/pom.xml?rev=1327509&r1=1327508&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/apps/example2/pom.xml (original) +++ commons/proper/chain/trunk/apps/example2/pom.xml Wed Apr 18 13:41:56 2012 @@ -7,7 +7,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,105 +19,46 @@ */ --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.commons</groupId> - <artifactId>commons-parent</artifactId> - <version>10</version> - </parent> - - <artifactId>chain-example2</artifactId> - <packaging>war</packaging> - <version>1.3-SNAPSHOT</version> - <name>Chan Example 2 App</name> + <parent> + <groupId>org.apache.commons</groupId> + <artifactId>commons-chain-examples</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../</relativePath> + </parent> - <dependencies> + <artifactId>chain-example2</artifactId> + <packaging>war</packaging> + <name>Apache Commons Chain :: Examples :: Chain Example 2 App</name> + + <dependencies> <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> - <groupId>javax.servlet</groupId> - <artifactId>servlet-api</artifactId> - <version>2.4</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>commons-digester</groupId> - <artifactId>commons-digester</artifactId> - <version>1.8</version> - </dependency> - - <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - <version>1.7.0</version> - </dependency> - - <dependency> - <groupId>commons-chain</groupId> - <artifactId>commons-chain</artifactId> - <version>1.3-SNAPSHOT</version> - <exclusions> - <exclusion> - <groupId>javax.portlet</groupId> - <artifactId>portlet-api</artifactId> - </exclusion> - <exclusion> - <groupId>myfaces</groupId> - <artifactId>myfaces-api</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - <version>1.1.1</version> - </dependency> - - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - <version>1.2.12</version> - </dependency> - - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>jstl</artifactId> - <version>1.1.2</version> - </dependency> - - <dependency> - <groupId>taglibs</groupId> - <artifactId>standard</artifactId> - <version>1.1.2</version> - </dependency> - </dependencies> - -<!-- - <build> - <plugins> - <plugin> - <artifactId>maven-assembly-plugin</artifactId> - <configuration> - <descriptors> - <descriptor>src/main/assembly/dep.xml</descriptor> - </descriptors> - </configuration> - </plugin> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <configuration> - <excludes> - <exclude>**/systest/**</exclude> - </excludes> - </configuration> - </plugin> - </plugins> - </build> ---> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-chain2</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-chain2-web</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> </project> Modified: commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/CountCommand.java URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/CountCommand.java?rev=1327509&r1=1295180&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/CountCommand.java (original) +++ commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/CountCommand.java Wed Apr 18 13:41:56 2012 @@ -30,7 +30,7 @@ import org.apache.commons.logging.LogFac * @version $Revision$ $Date$ */ -public class CountCommand implements Command { +public class CountCommand implements Command<String, Object, WebContext> { private Log log = LogFactory.getLog(CountCommand.class); @@ -67,13 +67,12 @@ public class CountCommand implements Com * @return <code>false</code> so that processng will continue * @throws Exception If an error occurs during execution. */ - public boolean execute(Context context) throws Exception { + public boolean execute(WebContext context) { count++; log.info("Executing: " + attribute + "=" + count); - WebContext webContext = (WebContext)context; - webContext.getSessionScope().put(attribute, new Integer(count)); + context.getSessionScope().put(attribute, new Integer(count)); return false; Modified: commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ExampleServlet.java URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ExampleServlet.java?rev=1327509&r1=1295180&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ExampleServlet.java (original) +++ commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ExampleServlet.java Wed Apr 18 13:41:56 2012 @@ -17,6 +17,8 @@ package org.apache.commons.chain2.apps.example; import java.io.IOException; +import java.lang.Object; +import java.lang.String; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -33,6 +35,11 @@ import org.apache.commons.logging.LogFac */ public class ExampleServlet extends HttpServlet { + /** + * + */ + private static final long serialVersionUID = 1L; + private String servletName; /** @@ -64,23 +71,18 @@ public class ExampleServlet extends Http */ public void service(HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - - CatalogFactory factory = CatalogFactory.getInstance(); - Catalog catalog = factory.getCatalog(servletName); + throws IOException { + + CatalogFactory<String, Object, ServletWebContext> factory = CatalogFactory.getInstance(); + Catalog<String, Object, ServletWebContext> catalog = factory.getCatalog(servletName); if (catalog == null) { catalog = factory.getCatalog(); } ServletWebContext context = new ServletWebContext(getServletContext(), request, response); - Command command = catalog.getCommand("COMMAND_MAPPER"); - try { - command.execute(context); - } catch (Exception e) { - throw new ServletException(e); - } - + Command<String, Object, ServletWebContext> command = catalog.getCommand("COMMAND_MAPPER"); + command.execute(context); } } Modified: commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java?rev=1327509&r1=1295180&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java (original) +++ commons/proper/chain/trunk/apps/example2/src/main/java/org/apache/commons/chain2/apps/example/ForwardCommand.java Wed Apr 18 13:41:56 2012 @@ -19,10 +19,13 @@ package org.apache.commons.chain2.apps.e import org.apache.commons.chain2.Command; import org.apache.commons.chain2.Context; +import org.apache.commons.chain2.web.servlet.ServletWebContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.chain2.web.servlet.ServletWebContext; +import javax.servlet.ServletException; import javax.servlet.RequestDispatcher; +import java.io.IOException; +import java.lang.RuntimeException; /** * <p>Foo Command</p> @@ -30,7 +33,7 @@ import javax.servlet.RequestDispatcher; * @version $Revision$ $Date$ */ -public class ForwardCommand implements Command { +public class ForwardCommand implements Command<String, Object, ServletWebContext> { private Log log = LogFactory.getLog(ForwardCommand.class); @@ -64,22 +67,26 @@ public class ForwardCommand implements C * @return <code>false</code> so that processng will continue * @throws Exception If an error occurs during execution. */ - public boolean execute(Context context) throws Exception { - - String uri = getForward(context); - if (uri != null) { - if (log.isDebugEnabled()) { - log.debug("Forwarding to " + uri); - } - ServletWebContext swcontext = (ServletWebContext)context; - RequestDispatcher rd = swcontext.getContext().getRequestDispatcher(uri); - rd.forward(swcontext.getRequest(), swcontext.getResponse()); - return true; - } else { - if (log.isDebugEnabled()) { - log.debug("No forward found"); + public boolean execute(ServletWebContext context) { + try { + String uri = getForward(context); + if (uri != null) { + if (log.isDebugEnabled()) { + log.debug("Forwarding to " + uri); + } + RequestDispatcher rd = context.getContext().getRequestDispatcher(uri); + rd.forward(context.getRequest(), context.getResponse()); + return true; + } else { + if (log.isDebugEnabled()) { + log.debug("No forward found"); + } + return false; } - return false; + } catch (IOException e) { + throw new RuntimeException(e); + } catch (ServletException e) { + throw new RuntimeException(e); } } @@ -89,7 +96,7 @@ public class ForwardCommand implements C * @param context The {@link Context} we are operating on * @return The uri to forward to */ - protected String getForward(Context context) { + protected String getForward(ServletWebContext context) { String uri = (String)context.get("forward"); if (uri == null) { uri = getForward(); Added: commons/proper/chain/trunk/apps/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/apps/pom.xml?rev=1327509&view=auto ============================================================================== --- commons/proper/chain/trunk/apps/pom.xml (added) +++ commons/proper/chain/trunk/apps/pom.xml Wed Apr 18 13:41:56 2012 @@ -0,0 +1,95 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.commons</groupId> + <artifactId>commons-chain-parent</artifactId> + <version>2.0-SNAPSHOT</version> + <relativePath>../</relativePath> + </parent> + + <artifactId>commons-chain-examples</artifactId> + <packaging>pom</packaging> + + <name>Apache Commons Chain :: Examples</name> + <description> + Example modules using the chain of responsibility pattern. + </description> + + <modules> + <module>example1</module> + <module>example2</module> + <module>cookbook-examples</module> + </modules> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.10</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <version>2.9.1</version> + <dependencies> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-chain2-build-tools</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <executions> + <execution> + <goals> + <goal>checkstyle-aggregate</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> Propchange: commons/proper/chain/trunk/apps/pom.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/chain/trunk/apps/pom.xml ------------------------------------------------------------------------------ svn:keywords = Date Revision Author HeadURL Id Propchange: commons/proper/chain/trunk/apps/pom.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Propchange: commons/proper/chain/trunk/build-tools/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Wed Apr 18 13:41:56 2012 @@ -1 +1,3 @@ target +bin +maven-eclipse.xml Propchange: commons/proper/chain/trunk/configuration/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Wed Apr 18 13:41:56 2012 @@ -1 +1,3 @@ target +bin +maven-eclipse.xml Propchange: commons/proper/chain/trunk/core/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Wed Apr 18 13:41:56 2012 @@ -1 +1,3 @@ target +bin +maven-eclipse.xml Modified: commons/proper/chain/trunk/core/src/main/java/org/apache/commons/chain2/Command.java URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/core/src/main/java/org/apache/commons/chain2/Command.java?rev=1327509&r1=1327508&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/core/src/main/java/org/apache/commons/chain2/Command.java (original) +++ commons/proper/chain/trunk/core/src/main/java/org/apache/commons/chain2/Command.java Wed Apr 18 13:41:56 2012 @@ -84,7 +84,6 @@ import java.util.Map; */ public interface Command<K, V, C extends Map<K, V>> { - /** * <p>Commands should return <code>CONTINUE_PROCESSING</code> if the processing * of the given {@link Context} should be delegated to a subsequent Modified: commons/proper/chain/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/pom.xml?rev=1327509&r1=1327508&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/pom.xml (original) +++ commons/proper/chain/trunk/pom.xml Wed Apr 18 13:41:56 2012 @@ -43,6 +43,7 @@ <module>core</module> <module>configuration</module> <module>web</module> + <module>apps</module> <module>dist</module> </modules> @@ -200,7 +201,7 @@ <artifactId>maven-checkstyle-plugin</artifactId> <version>2.9.1</version> <configuration> - <configLocation>org/apache/commons/chain2/checkstyle.xml</configLocation> + <configLocation>build-tools/src/main/resources/org/apache/commons/chain2/checkstyle.xml</configLocation> <enableRulesSummary>false</enableRulesSummary> <headerLocation>org/apache/commons/chain2/license-header.txt</headerLocation> </configuration> Modified: commons/proper/chain/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/src/changes/changes.xml?rev=1327509&r1=1327508&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/src/changes/changes.xml (original) +++ commons/proper/chain/trunk/src/changes/changes.xml Wed Apr 18 13:41:56 2012 @@ -43,6 +43,9 @@ The <action> type attribute can be add,u <action dev="simonetripodi" type="add" issue="CHAIN-67" due-to="Elijah Zupancic"> Refactor of explicit Exception throws to a RuntimeException type </action> + <action dev="simonetripodi" type="add" issue="CHAIN-66" due-to="Elijah Zupancic"> + Updated Chain documentation to include new changes to the API + </action> <action dev="simonetripodi" type="add" issue="CHAIN-65" due-to="Elijah Zupancic"> Rename package org.apache.commons.chain to org.apache.commons.chain2 for v2 of chain. </action> Modified: commons/proper/chain/trunk/src/site/xdoc/cookbook.xml URL: http://svn.apache.org/viewvc/commons/proper/chain/trunk/src/site/xdoc/cookbook.xml?rev=1327509&r1=1327508&r2=1327509&view=diff ============================================================================== --- commons/proper/chain/trunk/src/site/xdoc/cookbook.xml (original) +++ commons/proper/chain/trunk/src/site/xdoc/cookbook.xml Wed Apr 18 13:41:56 2012 @@ -264,31 +264,26 @@ <example> <title>Testing whether a Profile object is created</title> - <source><![CDATA[package org.apache.commons.mailreader; + <source><![CDATA[package org.apache.commons.chain2.cookbook.profile; -import junit.framework.TestCase; import org.apache.commons.chain2.Command; -import org.apache.commons.chain2.Context; -import org.apache.commons.chain2.mailreader.commands.ProfileCheck; -import org.apache.commons.chain2.mailreader.commands.Profile; -import org.apache.commons.chain2.impl.ContextBase; +import org.junit.Test; +import static org.junit.Assert.assertNotNull; -public class ProfileCheckTest extends TestCase { +public class ProfileCheckTest { - public void testProfileCheckNeed() { + @Test + public void testProfileCheckNeed() { - Context context = new ContextBase(); - Command command = new ProfileCheck(); - try { - command.execute(context); - } catch (Exception e) { - fail(e.getMessage()); - } + ProfileContext context = new ProfileContext(); + Command<String, Object, ProfileContext> command = new ProfileCheck(); - Profile profile = (Profile) context.get(Profile.PROFILE_KEY); - assertNotNull("Missing Profile", profile); + command.execute(context); - }]]></source> + Profile profile = context.getProfile(); + assertNotNull("Missing org.apache.commons.chain2.cookbook.profile.Profile", profile); + } +}]]></source> </example> <p>Since we're using a test-first approach, we can't run or even @@ -351,20 +346,19 @@ public class ProfileCheckTest extends Te <example> <title>A Command to create a Profile, if one doesn't exist.</title> - <source><![CDATA[package org.apache.commons.chain2.mailreader.commands; + <source><![CDATA[package org.apache.commons.chain2.cookbook.profile; import org.apache.commons.chain2.Command; -import org.apache.commons.chain2.Context; -public class ProfileCheck implements Command { +public class ProfileCheck implements Command<String, Object, ProfileContext> { + + public Profile newProfile(ProfileContext context) { return new Profile(); } - public Profile newProfile(Context context) { return new Profile(); } + public boolean execute(ProfileContext context) { + Profile profile = context.getProfile(); - public boolean execute(Context context) throws Exception { - Object profile = context.get(Profile.PROFILE_KEY); if (null == profile) { - profile = newProfile(context); - context.put(Profile.PROFILE_KEY, profile); + context.setProfile(newProfile(context)); } return false; } @@ -378,9 +372,10 @@ public class ProfileCheck implements Com <example> <title>The simplest Profile class that can possibly work.</title> - <source><![CDATA[package org.apache.commons.chain2.mailreader.commands; -public class Profile { - public static String PROFILE_KEY = "profile"; + <source><![CDATA[package org.apache.commons.chain2.cookbook.profile; + +public class Profile { + public static String PROFILE_KEY = "profile"; }]]></source> </example> @@ -397,7 +392,7 @@ public class Profile { test.</p> <p><figure> - <title>Green bar for org.apache.commons.mailreader.ProfileCheckTest + <title>Green bar for org.apache.commons.chain2.cookbook.ProfileCheckTest [TODO: Screen capture]</title> <mediaobject> @@ -465,13 +460,16 @@ public class Profile { interface.</p> <p><example> - <title>The Context interface is a "marker" interface extending - Map.</title> + <title>The Context interface is a interface extending + Map with a single method for returning type-safe values.</title> + + <p><source><![CDATA[public interface Context<K, V> extends Map<K, V> { + + <T extends V> T retrieve(K key); - <p><source><![CDATA[public interface Context extends Map { }]]></source></p> - </example>However, to provide developers with type-safety, - encapsulation, and interoperability, Chain provides a sophisticated + </example>In addition, to provide developers with type-safety, + encapsulation, and interoperability, Chain also provides a sophisticated <code>ContextBase</code> class that also supports JavaBean properties.</p> @@ -535,44 +533,46 @@ public class Profile { <title>LocaleValueTest proves that our context is interoperable and type-safe.</title> - <p><source><![CDATA[package org.apache.commons.mailreader; -import junit.framework.TestCase; -import junit.framework.Assert; -import org.apache.commons.chain2.mailreader.MailReader; + <p><source><![CDATA[package org.apache.commons.chain2.cookbook.mailreader; + +import org.junit.Before; +import org.junit.Test; import java.util.Locale; +import static org.junit.Assert.*; -public class LocaleValueTest extends TestCase { +public class LocaleValueTest { MailReader context; + @Before public void setUp() { context = new MailReader(); } + @Test public void testLocaleSetPropertyGetMap() { Locale expected = Locale.CANADA_FRENCH; context.setLocale(expected); - Locale locale = (Locale) context.get(MailReader.LOCALE_KEY); - Assert.assertNotNull(locale); - Assert.assertEquals(expected, locale); + // the retrieve() method is a nice type-safe alternative to get() + Locale locale = context.retrieve(MailReader.LOCALE_KEY); + assertNotNull(locale); + assertEquals(expected, locale); } + @Test public void testLocalePutMapGetProperty() { Locale expected = Locale.ITALIAN; context.put(MailReader.LOCALE_KEY, expected); Locale locale = context.getLocale(); - Assert.assertNotNull(locale); - Assert.assertEquals(expected, locale); + assertNotNull(locale); + assertEquals(expected, locale); } + @Test(expected = UnsupportedOperationException.class) public void testLocaleSetTypedWithStringException() { String localeString = Locale.US.toString(); - try { - context.put(MailReader.LOCALE_KEY, localeString); - fail("Expected 'argument type mismatch' error"); - } catch (UnsupportedOperationException expected) { - ; - } + // Expected 'argument type mismatch' error + context.put(MailReader.LOCALE_KEY, localeString); } }]]></source></p> </example>A <code>MailReader</code> Context object that passes @@ -580,13 +580,19 @@ public class LocaleValueTest extends Tes <title>The simplest MailReader object that will pass LocalValueTest.</title> - <p><source><![CDATA[package org.apache.commons.chain2.mailreader; + <p><source><![CDATA[package org.apache.commons.chain2.cookbook.mailreader; + import org.apache.commons.chain2.impl.ContextBase; import java.util.Locale; -public class MailReader extends ContextBase {Prop +public class MailReader extends ContextBase { + public static String LOCALE_KEY = "locale"; + private Locale locale; + + public MailReader() {} + public Locale getLocale() { return locale; } @@ -609,12 +615,12 @@ public class MailReader extends ContextB import org.apache.commons.chain2.Context; import java.util.Hashmap; -public class MailReader extends Hashmap implements Context { +public class MailReader extends Hashmap<String, Locale> implements Context<String, Locale> { public static String LOCALE_KEY = "locale"; }]]></source></p> </example>By extending the stock ContextBase subclass, or rolling your own class with a HashMap, you can use whatever type of context is best for - your own artichtecture.</p> + your own architecture.</p> </section> <section name="Create a Catalog"> @@ -658,19 +664,22 @@ public class MailReader extends Hashmap <title>A Catalog stores Commands that an application can lookup and execute.</title> - <p><source><![CDATA[ boolean executeCatalogCommand(Context context, - String name, HttpServletRequest request) - throws Exception { - + <p><source><![CDATA[ private boolean executeCatalogCommand(MailReader context, + String name, HttpServletRequest request) { + ServletContext servletContext = - request.getSession().getServletContext(); - Catalog catalog = - (Catalog) servletContext.getAttribute("catalog"); - Command command = catalog.getCommand(name); - boolean stop = command.execute(context); - return stop; + request.getSession().getServletContext(); + + // Due to the servlet API limitations, we have to do a cast here + @SuppressWarnings("unchecked") + Catalog<String, Object, MailReader> catalog = + (Catalog<String, Object, MailReader>) servletContext + .getAttribute("catalog"); - } ]]></source></p> + Command<String, Object, MailReader> command = catalog.getCommand(name); + + return command.execute(context); + }]]></source></p> </example></p> <!-- p><remark>[Glossary: Add <em>"type-safety"</em>, @@ -703,7 +712,8 @@ public class MailReader extends Hashmap a user profile before changing a user's locale setting. If we wanted to make running a <code>CheckProfile</code> Command part of "LocaleChange", we could change the Catalog to make "LocaleChange" a - Chain. <!-- Example 10 --> The following example shows Catalog metadata where "LocaleChange" is a Chain. + Chain. <!-- Example 10 --> The following example shows Catalog metadata where + "LocaleChange" is a Chain. <example> <title>A Catalog can be refactored with zero-changes to the application code.</title> @@ -805,13 +815,15 @@ public class MailReader extends Hashmap <code>HttpServletRequest</code> instance, you can access the catalog by coding:</p> - <p><source><![CDATA[Catalog catalog = (Catalog) request.getSession() - .getServletContext().getAttribute("catalog");]]></source></p> + <p><source><![CDATA[Catalog<String, Object, MailReader> catalog = + (Catalog) request.getSession() + .getServletContext().getAttribute("catalog");]]></source></p> <p>Given the catalog, you can execute a command and pass it a context, like so:</p> - <p><source><![CDATA[Command command = catalog.getCommand(commandName); + <p><source><![CDATA[Command<String, Object, MailReader> command = + catalog.getCommand(commandName); boolean stop = command.execute(context);]]></source></p> <p>Of course, the hard part is populating the context and determining @@ -824,6 +836,9 @@ public class MailReader extends Hashmap <section name="Call a Command From Struts"> + <p><em>Note: Struts documentation is out of date and does not include + the proper usage of the new generics API in 2.xx.</em></p> + <p><em>Problem:</em> You'd like to call Commands from within a Struts application.</p> @@ -1051,7 +1066,7 @@ public class CommandAction extends Actio this:<source><![CDATA[ String name = mapping.getParameter(); + if ((null==name) || (name=="")) name = mapping.getName();]]></source></p> - <p>Or you could mix and match the two approches, using CommandAction + <p>Or you could mix and match the two approaches, using CommandAction when the formbean name and the command name match, and a CommandParameterAction, when they do not. Struts allows you to use as many Actions, and standard Actions, as you like.</p> @@ -1189,18 +1204,21 @@ public class CommandAction extends Actio <title>Test to assert that our Controller can process a Request and return an appropriate Response</title> - <p><source><![CDATA[package org.apache.commons.agility; + <p><source><![CDATA[package org.apache.commons.chain2.cookbook.agility; + +import org.apache.commons.chain2.cookbook.agility.impl.ControllerCatalog; +import org.apache.commons.chain2.cookbook.agility.impl.HandlerCommand; +import org.apache.commons.chain2.cookbook.agility.impl.RequestContext; +import org.junit.Test; -import junit.framework.TestCase; -import org.apache.commons.agility.impl.ControllerCatalog; -import org.apache.commons.agility.impl.HandlerCommand; -import org.apache.commons.agility.impl.RequestContext; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -public class ProcessingTest extends TestCase { +public class ProcessingTest { + @Test public void testRequestResponseName() { - - String NAME = "TestProcessing"; + String NAME = "TestProcessing"; Controller controller = new ControllerCatalog(); @@ -1234,7 +1252,8 @@ public class ProcessingTest extends Test interfaces.</title> <p><source><![CDATA[// Controller.java -package org.apache.commons.agility; +package org.apache.commons.chain2.cookbook.agility; + public interface Controller { void addHandler(RequestHandler handler); RequestHandler getHandler(String name) throws ProcessException; @@ -1242,7 +1261,8 @@ public interface Controller { } // Request.java -package org.apache.commons.agility; +package org.apache.commons.chain2.cookbook.agility; + public interface Request { String getName(); Response getResponse(); @@ -1250,21 +1270,24 @@ public interface Request { } // Response.java -package org.apache.commons.agility; +package org.apache.commons.chain2.cookbook.agility; + public interface Response { String getName(); } // RequestHandler.java -package org.apache.commons.agility; +package org.apache.commons.chain2.cookbook.agility; + public interface RequestHandler { String getName(); void handle(Request request) throws ProcessException; } // ProcessException.java -package org.apache.commons.agility; -public class ProcessException extends Exception { +package org.apache.commons.chain2.cookbook.agility; + +public class ProcessException extends RuntimeException { public ProcessException(Throwable cause) { super(cause); } @@ -1289,16 +1312,32 @@ public class ProcessException extends Ex <title>HandlerCommand provides default behavior that subclasses can override</title> - <p><source><![CDATA[package org.apache.commons.agility.impl; + <p><source><![CDATA[/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.chain2.cookbook.agility.impl; -import org.apache.commons.agility.ProcessException; -import org.apache.commons.agility.Request; -import org.apache.commons.agility.RequestHandler; -import org.apache.commons.agility.Response; import org.apache.commons.chain2.Command; -import org.apache.commons.chain2.Context; +import org.apache.commons.chain2.cookbook.agility.ProcessException; +import org.apache.commons.chain2.cookbook.agility.Request; +import org.apache.commons.chain2.cookbook.agility.RequestHandler; +import org.apache.commons.chain2.cookbook.agility.Response; -public class HandlerCommand implements Command, RequestHandler { +public class HandlerCommand implements Command<String, Object, RequestContext>, + RequestHandler { String name = null; public HandlerCommand(String name) { @@ -1309,11 +1348,6 @@ public class HandlerCommand implements C return name; } - public boolean execute(Context context) throws Exception { - handle((Request) context); - return true; - } - public void handle(Request request) throws ProcessException { try { String name = request.getName(); @@ -1323,6 +1357,12 @@ public class HandlerCommand implements C throw new ProcessException(e); } } + + public boolean execute(RequestContext requestContext) { + handle(requestContext); + + return CONTINUE_PROCESSING; + } }]]></source></p> </example>The <code>handle(Request)</code> method of HandlerCommand realizes the prime responsibility for this class: create a @@ -1350,9 +1390,9 @@ public class HandlerCommand implements C <title>Many other implementations of ResponseContext are possible. They just need to implement Response and extend ContextBase.</title> - <p><source><![CDATA[package org.apache.commons.agility.impl; + <p><source><![CDATA[package org.apache.commons.chain2.cookbook.agility.impl; -import org.apache.commons.agility.Response; +import org.apache.commons.chain2.cookbook.agility.Response; import org.apache.commons.chain2.impl.ContextBase; public class ResponseContext extends ContextBase implements Response { @@ -1381,26 +1421,35 @@ public class ResponseContext extends Con <title>RequestHandlers can be added to the CatalogController programatically or through metadata</title> - <p><source><![CDATA[package org.apache.commons.agility.impl; + <p><source><![CDATA[package org.apache.commons.chain2.cookbook.agility.impl; -import org.apache.commons.agility.Controller; -import org.apache.commons.agility.ProcessException; -import org.apache.commons.agility.Request; -import org.apache.commons.agility.RequestHandler; -import org.apache.commons.chain2.impl.CatalogBase; import org.apache.commons.chain2.Command; +import org.apache.commons.chain2.cookbook.agility.Controller; +import org.apache.commons.chain2.cookbook.agility.ProcessException; +import org.apache.commons.chain2.cookbook.agility.Request; +import org.apache.commons.chain2.cookbook.agility.RequestHandler; +import org.apache.commons.chain2.impl.CatalogBase; + +public class ControllerCatalog extends CatalogBase<String, Object, RequestContext> + implements Controller { -public class ControllerCatalog extends CatalogBase implements Controller { public RequestHandler getHandler(String name) { - return (RequestHandler) getCommand(request.getName()); + @SuppressWarnings("unchecked") + RequestHandler handler = (RequestHandler) getCommand(name); + + return handler; } public void addHandler(RequestHandler handler) { - this.addCommand(handler.getName(), (Command) handler); + @SuppressWarnings("unchecked") + Command<String, Object, RequestContext> command = + (Command<String, Object, RequestContext>)handler; + + this.addCommand(handler.getName(), command); } public void process(Request request) throws ProcessException { - Handler handler = getHandler(request.getName()); + RequestHandler handler = getHandler(request.getName()); if (handler != null) handler.handle(request); } }]]></source></p> @@ -1430,10 +1479,10 @@ public class ControllerCatalog extends C <p><example> <title>RequestContext ties it all together</title> - <p><source><