You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Sgarlata Matt <sg...@bah.com> on 2003/09/24 14:39:05 UTC

[Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

The conversation threads are getting kind of crazy, so I'm going to skip
inline quotes for parts of this.

Craig, now I do see your point about using the ConfigRuleSet to digest a
portion of
an arbitrary XML file.  That is very cool, and now I understand why the
names of the XML elements are configurable.  I always understood the value
of letting attributes to the <command> element (and other elements).  This
is a much slicker approach than creating nested <set-property> elements.
Still, I think it could be useful to have a DTD for the *default* behavior
of the ConfigRuleSet.  I think in general users will start off using the
default behavior, and then may at a later date decide to fold their commands
into some other file, so a DTD will be nice to get people started with the
Chain package.  I agree with most your points about the constraints I placed
in the DTD being inappropriate, and will explicitly address each if we ever
decide to make a DTD.

As I've thought more about the package, I don't understand why some design
decisions were made.  First let me say that I think of Chains as being an OO
way to simulate procedural logic.  Many of my comments will basically be
concerning why some of the standard control flow abilities (if/then
statements, loops, exception handling, etc) in Java aren't more easily
done/simulated using the Chain package.  So, here I go with questions:
1) How come Chains have a static structure?  Related to this, how come
Command.execute returns boolean instead of returning Command?  If it
returned Command this would basically eliminate the need for a Chain
interface altogether.  Chain would become a concrete implementation of
Command that repeatedly executed Commands until the last command executed
returned null (which would be the new value to indicate the end of a chain).
Static chains (such as those configured using an XML file) would easily be
supported by another concrete implementation of Command which executed a
series of commands in order, completely ignoring their return values.
2) How come Filters have a postprocess method but no catchexception method?
The postprocess block can deal with exceptions, but it seems to me like it
would be more natural for exceptions to be dealt with in a catchexception
block and for postprocess to be strictly for freeing resources that the
Command acquired when its execute method was called.

Ted Husted wrote:
> Of course, another way to go would be to make the Catalog a singleton,
> or available through some registry, but I'm thinking that going through
> the Context may be the cleanest approach, since the Context is
> essentially a Registry too.

How about making a Register class which is an implementation of Context
which stores only references to Catalogs?  We could make the registry itself
a singleton, and write in design notes that since the registry is shared
between apps, each app should store its Catalog(s) in an
application-specific attribute like below:

Registry
|
|---org.apache.struts
|---|---actions.RequestProcessor
|---|---somethingElse
|---com.bah.krm
|---org.apache.commons.something

That's not explained incredibly well, but if each application component
reserves its own spot in the registry, we should be able to make the
registry a singleton everyone can share.  This keeps us from tying ourselves
to the Servlet API, as was mentioned in the ChainServlet discussion thread.

Matt
----- Original Message ----- 
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Monday, September 22, 2003 9:33 PM
Subject: Re: [Chain] examples XML file available?


> Sgarlata Matt wrote:
>
> >Comments below...
> >----- Original Message ----- 
> >From: "Craig R. McClanahan" <cr...@apache.org>
> >To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> >Sent: Sunday, September 21, 2003 5:53 PM
> >Subject: Re: [Chain] examples XML file available?
> >
> >
> >
> >
> >>On Sun, 21 Sep 2003, Sgarlata Matt wrote:
> >>
> >>
> >>
> >>>Date: Sun, 21 Sep 2003 13:45:37 -0400
> >>>From: Sgarlata Matt <sg...@bah.com>
> >>>Reply-To: Jakarta Commons Developers List
> >>>
> >>>
> ><co...@jakarta.apache.org>
> >
> >
> >>>To: commons-dev@jakarta.apache.org
> >>>Subject: [Chain] examples XML file available?
> >>>
> >>>I'm interested in possibly using the Chain package in some of my
> >>>
> >>>
> >projects
> >
> >
> >>>and I was hoping I could get an example XML file to feed to the
> >>>
> >>>
> >Digester?  I
> >
> >
> >>>don't need the Command classes associated with the file or anything
like
> >>>that, I'd just like to see an example so I don't have to
> >>>
> >>>
> >reverse-engineer
> >
> >
> >>>its structure from the ConfigRuleSet.
> >>>
> >>>
> >>>
> >>There's an example in the unit tests of the source module
> >>
> >>  src/test/org/apache/commons/chain/config/test-config.xml
> >>
> >>although, in truth, this is only a test of the default rules -- you
> >>actually get to configure what element and attribute names are
recognized
> >>by setting properties on your own copy of ConfigRuleSet instead of using
> >>the default one (unit tests for this would be definitely appreciated
:-).
> >>
> >>
> >
> >Wow, that is a very cool how you set that up :)  Is there a use-case you
had
> >in mind where this type of functionality would be useful?  To be honest,
I
> >think that it might be better to make the ConfigRuleSet a little less
> >powerful and expect a set DTD.  More comments on how this would work
> >below...
> >
> >
> The use case goes like this:
>
> * Each command should be a JavaBean (i.e. has a zero-args constructor and
>   is configured with property setters).
>
> * The set of properties each command class is interested in will be unique
>   to that command class.
>
> * Users that are utilizing the Digester-based mechanism for configuring
> command chains
>   will want the most concise mechanism for configuring commands as
possible.
>
> Experience with processing both Tomcat and Struts configuration files
> (both of which use Digester) make it pretty clear this use case is
> common -- and it is exactly the use case that Digester was designed for.
>
> >
> >
> >>>If I play with the package some more and like it, I could provide a DTD
> >>>
> >>>
> >for
> >
> >
> >>>the XML file and documentation for it.  That should save Craig and Ted
> >>>
> >>>
> >from
> >
> >
> >>>some boring work :)
> >>>
> >>>
> >>While we definitely appreciate the help :-), I don't think a DTD (or a
> >>schema) that captures all of the possible functionality of the XML based
> >>configuration.  Consider one of the examples in the unit test:
> >>
> >>    <!-- Configurable command with settable properties -->
> >>    <command   name="Configurable"
> >>          className="org.apache.commons.chain.config.TestCommand"
> >>                foo="Foo Value"
> >>                bar="Bar Value"/>
> >>
> >>Besides actually instantiating TestCommand and inserting it into the
> >>parent Catalog, this leverages Digester's "Set Properties Rule" ability
to
> >>match attributes to writeable propertes and configure them.  The entry
> >>above, then, calls setFoo() and setBar() on the instantiated bean -- but
> >>this is the same <command> element that is used to configure a different
> >>type of command, with different properties, later on:
> >>
> >>    <command      id="1"
> >>                 is2="a"
> >>           className="org.apache.commons.chain.impl.DelegatingFilter"/>
> >>
> >>I'm not a total guru on XML, but I don't see how one can define a DTD
that
> >>covers this case, since the set of possible attributes is not limited.
> >>
> >>
> >
> >Yeah, you can't have a DTD verify the attributes for commands since they
are
> >not set.  However, we can specify that the className attribute for
<command>
> >is required and that the <command> element must be empty.
> >
> Why should it be empty?  You're perfectly free to add your own rules to
> the ones returned by the ConfigRuleSet, and process the innards yourself.
>
> In addition, if you're not going to support configuring JavaBean
> properties on the command instances with arbitrary attributes, you will
> certainly want something like a <set-property> element inside to
> accomplish this goal.  So an empty command is probably not the right
answer.
>
> >  I think these are
> >two very useful things to have the digester automatically check.  It
would
> >certainly beat a random NullPointerException :)  In fact, the attached
DTD
> >can take care of the items listed below.  This would certainly avoid lots
of
> >painful debugging sessions when <command> was actually typed <Command>
and
> >other stuff like that.
> >
> >- Ensure there are 1 or more <chain> elements inside <chains>
> >
> If you want to register single-command "chains" in the catalog, you
> probably won't want this.
>
> >- Ensure there are 1 or more <command> elements inside <chain>
> >
> No "placeholder" chains for future fleshing out?
>
> >- Ensure each <chain> has a name
> >- Ensure each <command> has a className specified
> >
> >- Ensure each <command> element is empty
> >
> As above, I don't buy into this one.
>
> >- Limit the XML file to only <chains>, <chain>, and <command> elements
with
> >the proper nesting.
> >
> If a person wants to define their command chains in the same document
> that they are using for other aspects of the operation (for example, if
> Struts wanted to let you put this stuff into a struts-config.xml file),
> you'd want the ability to just pull out the elements you care about and
> ignore the rest.  That's the beauty of the rules-based matching patterns
> that Digester supports -- you specify the patterns you are interested
> in, and that's all your rules have to deal with.
>
> >
> >The attached DTD is just a first pass at a DTD.  I know it isn't pretty,
and
> >would follow the format used in struts-config_1_0.dtd before recommending
it
> >for checkin.  Before I go any further though, I would actually like to
see
> >the XML file get a little more sophisticated.  Once we settle on the
format
> >of the XML file I can update ConfigRuleSet and finish up the DTD (and
> >provide test cases for ConfigRuleSet... ugh I hate writing test cases!)
> >Here's what I was thinking:
> >
> ><chains>
> >    <global-commands>
> >        <global-command
> >            name="globalCommand1"
> >            className="something"
> >            otherAttribute1="hi"/>
> >    </global-commands>
> >    <chain name="myChain">
> >        <!-- here otherAttribute1="hi" and className="something" are
> >        implied since the command was defined earlier -->
> >        <command name="globalCommand1"/>
> >        <!-- this is a local command -->
> >        <command className="something"/>
> >    </chain>
> ></chains>
> >
> >One cool thing we can do is ensure that each <command> that is actually a
> >reference to a <global-command> has a name attribute which corresponds to
> >one of the names of a global command.  This is actually something
supported
> >directly by DTDs, so we don't have to do anything fancy to get this
> >automatic validation :)
> >
> >
> How do you propose to set individual configurable properties on the
> command classes?  My experience so far on real ones (as opposed to toy
> ones) is that this is a mission critical requirement.
>
> >Matt
> >
> >
> Craig
>
> >------------------------------------------------------------------------
> >
> ><!--
> >     DTD for the optional Chain of Responsibility Configuration File,
> > Version 1.0
> >
> >     To support validation of your configuration file, include the
following
> >     DOCTYPE element at the beginning (after the "xml" declaration):
> >
> >     <!DOCTYPE chains PUBLIC
> >       "-//Apache Software Foundation//DTD Chain Configuration 1.0//EN"
> >       "http://jakarta.apache.org/commons/chain/dtds/chains_1_0.dtd">
> >-->
> >
> ><!-- The "chains" element is the root of the configuration file
hierarchy, and
> >     contains one or more nested chain elements.
> >-->
> ><!ELEMENT chains (chain+)>
> >
> ><!-- The "chain" element represents a class which implements the
> >     org.apache.commons.chain.Chain interface.  Thus it represents a
configured
> > list of Commands that will be executed in order to perform processing on
a
> > specified Context.  If no className is specified for the chain, the
chain
> > will be an instance of the class
org.apache.commons.chain.impl.ChainBase.
> >-->
> ><!ELEMENT chain (command+)>
> ><!ATTLIST chain
> > name CDATA #REQUIRED
> >
> >
> ><!ATTLIST chain
> > className CDATA #IMPLIED
> >
> >
> ><!ELEMENT command EMPTY>
> ><!ATTLIST command
> > className CDATA #REQUIRED
> >>
> >
> >
> >
> >------------------------------------------------------------------------
> >
> >---------------------------------------------------------------------
> >To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> >For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
 > As I've thought more about the package, I don't understand why some
 > design decisions were made.  First let me say that I think of Chains
 > as being an OO way to simulate procedural logic.  Many of my comments
 > will basically be concerning why some of the standard control flow
 > abilities (if/then statements, loops, exception handling, etc) in Java
 > aren't more easily done/simulated using the Chain package.

Have you reviewed the pattern descriptions for Chain of Responsibility, 
Composite, and Command from the Design Patterns book? I believe the 
scope of this package is provide a flexible, concrete implementation of 
these patterns. The alternatives you mentioned are certainly doable, but 
  don't seem to be in line with the patterns this package is meant to 
realize.

As for the second point, it's certainly possible that we will see a need 
for a catchException method, but I'd suggest we put some more use-cases 
on the table first. Once an extension point is added to the interface 
it's very difficult to take it back, so it can be better to let usage 
steer the implementation.

-Ted.


Sgarlata Matt wrote:
> The conversation threads are getting kind of crazy, so I'm going to skip
> inline quotes for parts of this.
> 
> Craig, now I do see your point about using the ConfigRuleSet to digest a
> portion of
> an arbitrary XML file.  That is very cool, and now I understand why the
> names of the XML elements are configurable.  I always understood the value
> of letting attributes to the <command> element (and other elements).  This
> is a much slicker approach than creating nested <set-property> elements.
> Still, I think it could be useful to have a DTD for the *default* behavior
> of the ConfigRuleSet.  I think in general users will start off using the
> default behavior, and then may at a later date decide to fold their commands
> into some other file, so a DTD will be nice to get people started with the
> Chain package.  I agree with most your points about the constraints I placed
> in the DTD being inappropriate, and will explicitly address each if we ever
> decide to make a DTD.
> 
> As I've thought more about the package, I don't understand why some design
> decisions were made.  First let me say that I think of Chains as being an OO
> way to simulate procedural logic.  Many of my comments will basically be
> concerning why some of the standard control flow abilities (if/then
> statements, loops, exception handling, etc) in Java aren't more easily
> done/simulated using the Chain package.  So, here I go with questions:
> 1) How come Chains have a static structure?  Related to this, how come
> Command.execute returns boolean instead of returning Command?  If it
> returned Command this would basically eliminate the need for a Chain
> interface altogether.  Chain would become a concrete implementation of
> Command that repeatedly executed Commands until the last command executed
> returned null (which would be the new value to indicate the end of a chain).
> Static chains (such as those configured using an XML file) would easily be
> supported by another concrete implementation of Command which executed a
> series of commands in order, completely ignoring their return values.
> 2) How come Filters have a postprocess method but no catchexception method?
> The postprocess block can deal with exceptions, but it seems to me like it
> would be more natural for exceptions to be dealt with in a catchexception
> block and for postprocess to be strictly for freeing resources that the
> Command acquired when its execute method was called.





---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Greg Reddin <gr...@fnf.com>.
Sgarlata Matt wrote:
> Related to this, how come
> Command.execute returns boolean instead of returning Command?  If it
> returned Command this would basically eliminate the need for a Chain
> interface altogether.  Chain would become a concrete implementation of
> Command that repeatedly executed Commands until the last command executed
> returned null (which would be the new value to indicate the end of a chain).

If Command returned a Command reference, each Command would have to know 
what the next Command in the chain is, which, IMO, would introduce too 
tight coupling between Commands.  Why use configurable chains if you're 
going to programatically hardwire the next step in the process.  The 
Chain interface exists to signify separately from the Commands 
themselves the set of commands that are to be run in a process.  The 
Command returns boolean so that you can "break" execution at any point 
in the chain.  Look at the current RequestProcessor interface in Struts. 
  Some of the processing methods return boolean to indicate that 
processing should not continue to the next "link."

If the interface was changed from what it is now, I'd prefer an approach 
that looks more like Servlet Filters where you call doNextCommand() 
without regard to what the next command is over an approach where you 
determine what the next command is, but I'm cool with the interface the 
way it exists now as well.

Greg



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
 > As I've thought more about the package, I don't understand why some
 > design decisions were made.  First let me say that I think of Chains
 > as being an OO way to simulate procedural logic.  Many of my comments
 > will basically be concerning why some of the standard control flow
 > abilities (if/then statements, loops, exception handling, etc) in Java
 > aren't more easily done/simulated using the Chain package.

Have you reviewed the pattern descriptions for Chain of Responsibility, 
Composite, and Command from the Design Patterns book? I believe the 
scope of this package is provide a flexible, concrete implementation of 
these patterns. The alternatives you mentioned are certainly doable, but 
  don't seem to be in line with the patterns this package is meant to 
realize.

As for the second point, it's certainly possible that we will see a need 
for a catchException method, but I'd suggest we put some more use-cases 
on the table first. Once an extension point is added to the interface 
it's very difficult to take it back, so it can be better to let usage 
steer the implementation.

-Ted.


Sgarlata Matt wrote:
> The conversation threads are getting kind of crazy, so I'm going to skip
> inline quotes for parts of this.
> 
> Craig, now I do see your point about using the ConfigRuleSet to digest a
> portion of
> an arbitrary XML file.  That is very cool, and now I understand why the
> names of the XML elements are configurable.  I always understood the value
> of letting attributes to the <command> element (and other elements).  This
> is a much slicker approach than creating nested <set-property> elements.
> Still, I think it could be useful to have a DTD for the *default* behavior
> of the ConfigRuleSet.  I think in general users will start off using the
> default behavior, and then may at a later date decide to fold their commands
> into some other file, so a DTD will be nice to get people started with the
> Chain package.  I agree with most your points about the constraints I placed
> in the DTD being inappropriate, and will explicitly address each if we ever
> decide to make a DTD.
> 
> As I've thought more about the package, I don't understand why some design
> decisions were made.  First let me say that I think of Chains as being an OO
> way to simulate procedural logic.  Many of my comments will basically be
> concerning why some of the standard control flow abilities (if/then
> statements, loops, exception handling, etc) in Java aren't more easily
> done/simulated using the Chain package.  So, here I go with questions:
> 1) How come Chains have a static structure?  Related to this, how come
> Command.execute returns boolean instead of returning Command?  If it
> returned Command this would basically eliminate the need for a Chain
> interface altogether.  Chain would become a concrete implementation of
> Command that repeatedly executed Commands until the last command executed
> returned null (which would be the new value to indicate the end of a chain).
> Static chains (such as those configured using an XML file) would easily be
> supported by another concrete implementation of Command which executed a
> series of commands in order, completely ignoring their return values.
> 2) How come Filters have a postprocess method but no catchexception method?
> The postprocess block can deal with exceptions, but it seems to me like it
> would be more natural for exceptions to be dealt with in a catchexception
> block and for postprocess to be strictly for freeing resources that the
> Command acquired when its execute method was called.





Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>>  - If a user attempts to remove() the key corresponding to a property,
>>    throw IllegalArgumentException.
>
>
> Can we make this an optional behavior?

Only if we make attribute-property transparency optional.  That's what 
the contract for org.apache.commons.chain.Context still says right now, 
but I'm currently believing that this is needlessly complicated.  If we 
want to keep it, though, we'll probably want two base classes -- one 
without transparency and a second one (built on top) with transparency, 
rather than a switchable behavior.  There are ***lots*** more 
transparency issues than just this one.

>
> The contact for Map.get and Map.remove says that they will return null 
> if the entry is not present or if the value is null. This implies an 
> alternate way to fulfill the Map.remove contract would be to set a 
> local property to null. 

The contract also says you can do things like unmodifiable Maps, in 
which case you're supposed to return UnsupportedOperationException.

>
>
>         // Case 2 -- this is a local property
>         if (key != null) {
> +            if (removeLocal) {
> +               return put(key,null);
> +            }
> +            } else {
>                 PropertyDescriptor descriptor =
>                     (PropertyDescriptor) descriptors.get(key);
>
> I'd like to apply this and add constructors that can be used to set 
> "removeLocal". The default could be false, which provices the original 
> behavior, and throws the exception.
>
> I do have a use-case for this involving a working component that does 
> try to use remove.
>
> IMHO, part of our API contract for BaseContext should be that the 
> local properties can be made transparent to a caller of the Map, and 
> that a context should be able to use entries or fields with 
> zero-changes to callers.

As above, if we're going to have two supported behaviors, I'd rather do 
it with two base classes.  My preference would be that we don't make it 
optional, though, on the following grounds:

* It's simpler to just explain one behavior, than two.

* If you turn off transparency, why does Context exist
  at all?  Why not just use a Map directly?

>
>
> -Ted. 

Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>>  - If a user attempts to remove() the key corresponding to a property,
>>    throw IllegalArgumentException.
>
>
> Can we make this an optional behavior?

Only if we make attribute-property transparency optional.  That's what 
the contract for org.apache.commons.chain.Context still says right now, 
but I'm currently believing that this is needlessly complicated.  If we 
want to keep it, though, we'll probably want two base classes -- one 
without transparency and a second one (built on top) with transparency, 
rather than a switchable behavior.  There are ***lots*** more 
transparency issues than just this one.

>
> The contact for Map.get and Map.remove says that they will return null 
> if the entry is not present or if the value is null. This implies an 
> alternate way to fulfill the Map.remove contract would be to set a 
> local property to null. 

The contract also says you can do things like unmodifiable Maps, in 
which case you're supposed to return UnsupportedOperationException.

>
>
>         // Case 2 -- this is a local property
>         if (key != null) {
> +            if (removeLocal) {
> +               return put(key,null);
> +            }
> +            } else {
>                 PropertyDescriptor descriptor =
>                     (PropertyDescriptor) descriptors.get(key);
>
> I'd like to apply this and add constructors that can be used to set 
> "removeLocal". The default could be false, which provices the original 
> behavior, and throws the exception.
>
> I do have a use-case for this involving a working component that does 
> try to use remove.
>
> IMHO, part of our API contract for BaseContext should be that the 
> local properties can be made transparent to a caller of the Map, and 
> that a context should be able to use entries or fields with 
> zero-changes to callers.

As above, if we're going to have two supported behaviors, I'd rather do 
it with two base classes.  My preference would be that we don't make it 
optional, though, on the following grounds:

* It's simpler to just explain one behavior, than two.

* If you turn off transparency, why does Context exist
  at all?  Why not just use a Map directly?

>
>
> -Ted. 

Craig



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
>  - If a user attempts to remove() the key corresponding to a property,
>    throw IllegalArgumentException.

Can we make this an optional behavior?

The contact for Map.get and Map.remove says that they will return null 
if the entry is not present or if the value is null. This implies an 
alternate way to fulfill the Map.remove contract would be to set a local 
property to null.

         // Case 2 -- this is a local property
         if (key != null) {
+            if (removeLocal) {
+               return put(key,null);
+            }
+            } else {
                 PropertyDescriptor descriptor =
                     (PropertyDescriptor) descriptors.get(key);

I'd like to apply this and add constructors that can be used to set 
"removeLocal". The default could be false, which provices the original 
behavior, and throws the exception.

I do have a use-case for this involving a working component that does 
try to use remove.

IMHO, part of our API contract for BaseContext should be that the local 
properties can be made transparent to a caller of the Map, and that a 
context should be able to use entries or fields with zero-changes to 
callers.


-Ted.



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
>  - If a user attempts to remove() the key corresponding to a property,
>    throw IllegalArgumentException.

Can we make this an optional behavior?

The contact for Map.get and Map.remove says that they will return null 
if the entry is not present or if the value is null. This implies an 
alternate way to fulfill the Map.remove contract would be to set a local 
property to null.

         // Case 2 -- this is a local property
         if (key != null) {
+            if (removeLocal) {
+               return put(key,null);
+            }
+            } else {
                 PropertyDescriptor descriptor =
                     (PropertyDescriptor) descriptors.get(key);

I'd like to apply this and add constructors that can be used to set 
"removeLocal". The default could be false, which provices the original 
behavior, and throws the exception.

I do have a use-case for this involving a working component that does 
try to use remove.

IMHO, part of our API contract for BaseContext should be that the local 
properties can be made transparent to a caller of the Map, and that a 
context should be able to use entries or fields with zero-changes to 
callers.


-Ted.



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Sgarlata Matt wrote:

>I like the way this discussion is going.  My 2 cents would be we should test
>this approach with tools like Velocity, the JSTL EL, and BeanUtils to make
>sure these tools don't get confused by the Context object being both a map
>and having real getters/setters for the same property.  Do you foresee any
>problems with this?
>  
>
For the properties of the Context implementation class, it will not 
matter whether a library considers them to be a JavaBean or a Map -- 
they'll get the same results either way.

For attributes that are not JavaBean properties:

* BeanUtils will always treat it as a Map, so things will work as expected

* For JSTL and JSP 2.0 expressions, the expression evaluation rules
  require checking for Map-ness before checking for JavaBean properties,
  so things will work as expected.

* For any other library, you'll have to check it yourself, but I would be
  surprised if there were any cases where you'd want to check for
  JavaBeans properties before doing an "instanceof Map" check.


Craig

>Matt
>----- Original Message ----- 
>From: "Craig R. McClanahan" <cr...@apache.org>
>To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
>Sent: Saturday, September 27, 2003 2:37 PM
>Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
>examples XML file available?)
>
>
>  
>
>>Ted Husted wrote:
>>
>>    
>>
>>>Craig R. McClanahan wrote:
>>>
>>>      
>>>
>>>>We haven't released anything yet ... why not just check it in to the
>>>>o.a.c.c.impl package so we can all take a look.  We need to
>>>>completely fulfill the Map contracts if we go this way, and I have
>>>>some concerns about that.
>>>>        
>>>>
>>>It's there. This one just delegates the Map methods to getAttributes,
>>>so the Context object can be used in places that already expect a Map.
>>>      
>>>
>>OK, I can buy into Context is-a Map.  Here's one way to approach making
>>this change:
>>
>>* Context becomes a marker interface:
>>
>>    public interface Context extends Map { }
>>
>>  The getAttributes() method is removed.
>>
>>* In order to fulfill the Map contract for things like equals() and
>>hashCode()
>>  more directly, ContextBase can extend HashMap instead of implement Map
>>  with a delegated-to HashMap instance variable like ContextBaseAttributes
>>  does now.
>>
>>* For the property transparency thing:
>>
>>  - In the ContextBase constructor, introspect the list of properties,
>>    and add key-value pairs for all of them to the superclass Map.
>>    The values in this case are actually irrelevant, because they won't
>>    be used -- all the accessors will need to know to call the
>>    underlying property getter/setter.
>>
>>  - get() and put() call the right getter or setter, which can be
>>implemented
>>    however they want (I don't see any reason they should want to store
>>    the values in the superclass HashMap, but they could by just calling
>>    super.get() and super.put()).
>>
>>  - If a user attempts to remove() the key corresponding to a property,
>>    throw IllegalArgumentException.
>>
>>Doing things this way means we don't need getField()/putField() to
>>accomplish your desire to (optionally) keep all the values in the
>>internal map.
>>
>>Does this sound like a reasonable strategy?
>>
>>    
>>
>>>-T.
>>>      
>>>
>>Craig
>>
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>>For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>>
>>    
>>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>  
>


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
I like the way this discussion is going.  My 2 cents would be we should test
this approach with tools like Velocity, the JSTL EL, and BeanUtils to make
sure these tools don't get confused by the Context object being both a map
and having real getters/setters for the same property.  Do you foresee any
problems with this?

Matt
----- Original Message ----- 
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Saturday, September 27, 2003 2:37 PM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Ted Husted wrote:
>
> > Craig R. McClanahan wrote:
> >
> >> We haven't released anything yet ... why not just check it in to the
> >> o.a.c.c.impl package so we can all take a look.  We need to
> >> completely fulfill the Map contracts if we go this way, and I have
> >> some concerns about that.
> >
> >
> > It's there. This one just delegates the Map methods to getAttributes,
> > so the Context object can be used in places that already expect a Map.
>
> OK, I can buy into Context is-a Map.  Here's one way to approach making
> this change:
>
> * Context becomes a marker interface:
>
>     public interface Context extends Map { }
>
>   The getAttributes() method is removed.
>
> * In order to fulfill the Map contract for things like equals() and
> hashCode()
>   more directly, ContextBase can extend HashMap instead of implement Map
>   with a delegated-to HashMap instance variable like ContextBaseAttributes
>   does now.
>
> * For the property transparency thing:
>
>   - In the ContextBase constructor, introspect the list of properties,
>     and add key-value pairs for all of them to the superclass Map.
>     The values in this case are actually irrelevant, because they won't
>     be used -- all the accessors will need to know to call the
>     underlying property getter/setter.
>
>   - get() and put() call the right getter or setter, which can be
> implemented
>     however they want (I don't see any reason they should want to store
>     the values in the superclass HashMap, but they could by just calling
>     super.get() and super.put()).
>
>   - If a user attempts to remove() the key corresponding to a property,
>     throw IllegalArgumentException.
>
> Doing things this way means we don't need getField()/putField() to
> accomplish your desire to (optionally) keep all the values in the
> internal map.
>
> Does this sound like a reasonable strategy?
>
> >
> > -T.
>
> Craig
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
I like the way this discussion is going.  My 2 cents would be we should test
this approach with tools like Velocity, the JSTL EL, and BeanUtils to make
sure these tools don't get confused by the Context object being both a map
and having real getters/setters for the same property.  Do you foresee any
problems with this?

Matt
----- Original Message ----- 
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Saturday, September 27, 2003 2:37 PM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Ted Husted wrote:
>
> > Craig R. McClanahan wrote:
> >
> >> We haven't released anything yet ... why not just check it in to the
> >> o.a.c.c.impl package so we can all take a look.  We need to
> >> completely fulfill the Map contracts if we go this way, and I have
> >> some concerns about that.
> >
> >
> > It's there. This one just delegates the Map methods to getAttributes,
> > so the Context object can be used in places that already expect a Map.
>
> OK, I can buy into Context is-a Map.  Here's one way to approach making
> this change:
>
> * Context becomes a marker interface:
>
>     public interface Context extends Map { }
>
>   The getAttributes() method is removed.
>
> * In order to fulfill the Map contract for things like equals() and
> hashCode()
>   more directly, ContextBase can extend HashMap instead of implement Map
>   with a delegated-to HashMap instance variable like ContextBaseAttributes
>   does now.
>
> * For the property transparency thing:
>
>   - In the ContextBase constructor, introspect the list of properties,
>     and add key-value pairs for all of them to the superclass Map.
>     The values in this case are actually irrelevant, because they won't
>     be used -- all the accessors will need to know to call the
>     underlying property getter/setter.
>
>   - get() and put() call the right getter or setter, which can be
> implemented
>     however they want (I don't see any reason they should want to store
>     the values in the superclass HashMap, but they could by just calling
>     super.get() and super.put()).
>
>   - If a user attempts to remove() the key corresponding to a property,
>     throw IllegalArgumentException.
>
> Doing things this way means we don't need getField()/putField() to
> accomplish your desire to (optionally) keep all the values in the
> internal map.
>
> Does this sound like a reasonable strategy?
>
> >
> > -T.
>
> Craig
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> We haven't released anything yet ... why not just check it in to the 
>> o.a.c.c.impl package so we can all take a look.  We need to 
>> completely fulfill the Map contracts if we go this way, and I have 
>> some concerns about that.
>
>
> It's there. This one just delegates the Map methods to getAttributes, 
> so the Context object can be used in places that already expect a Map.

OK, I can buy into Context is-a Map.  Here's one way to approach making 
this change:

* Context becomes a marker interface:

    public interface Context extends Map { }

  The getAttributes() method is removed.

* In order to fulfill the Map contract for things like equals() and 
hashCode()
  more directly, ContextBase can extend HashMap instead of implement Map
  with a delegated-to HashMap instance variable like ContextBaseAttributes
  does now.

* For the property transparency thing:

  - In the ContextBase constructor, introspect the list of properties,
    and add key-value pairs for all of them to the superclass Map.
    The values in this case are actually irrelevant, because they won't
    be used -- all the accessors will need to know to call the
    underlying property getter/setter.

  - get() and put() call the right getter or setter, which can be 
implemented
    however they want (I don't see any reason they should want to store
    the values in the superclass HashMap, but they could by just calling
    super.get() and super.put()).

  - If a user attempts to remove() the key corresponding to a property,
    throw IllegalArgumentException.

Doing things this way means we don't need getField()/putField() to 
accomplish your desire to (optionally) keep all the values in the 
internal map.

Does this sound like a reasonable strategy?

>
> -T.

Craig



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> We haven't released anything yet ... why not just check it in to the 
>> o.a.c.c.impl package so we can all take a look.  We need to 
>> completely fulfill the Map contracts if we go this way, and I have 
>> some concerns about that.
>
>
> It's there. This one just delegates the Map methods to getAttributes, 
> so the Context object can be used in places that already expect a Map.

OK, I can buy into Context is-a Map.  Here's one way to approach making 
this change:

* Context becomes a marker interface:

    public interface Context extends Map { }

  The getAttributes() method is removed.

* In order to fulfill the Map contract for things like equals() and 
hashCode()
  more directly, ContextBase can extend HashMap instead of implement Map
  with a delegated-to HashMap instance variable like ContextBaseAttributes
  does now.

* For the property transparency thing:

  - In the ContextBase constructor, introspect the list of properties,
    and add key-value pairs for all of them to the superclass Map.
    The values in this case are actually irrelevant, because they won't
    be used -- all the accessors will need to know to call the
    underlying property getter/setter.

  - get() and put() call the right getter or setter, which can be 
implemented
    however they want (I don't see any reason they should want to store
    the values in the superclass HashMap, but they could by just calling
    super.get() and super.put()).

  - If a user attempts to remove() the key corresponding to a property,
    throw IllegalArgumentException.

Doing things this way means we don't need getField()/putField() to 
accomplish your desire to (optionally) keep all the values in the 
internal map.

Does this sound like a reasonable strategy?

>
> -T.

Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> We haven't released anything yet ... why not just check it in to the 
> o.a.c.c.impl package so we can all take a look.  We need to completely 
> fulfill the Map contracts if we go this way, and I have some concerns 
> about that.

It's there. This one just delegates the Map methods to getAttributes, so 
the Context object can be used in places that already expect a Map.

-T.



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> We haven't released anything yet ... why not just check it in to the 
> o.a.c.c.impl package so we can all take a look.  We need to completely 
> fulfill the Map contracts if we go this way, and I have some concerns 
> about that.

It's there. This one just delegates the Map methods to getAttributes, so 
the Context object can be used in places that already expect a Map.

-T.



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> The latter lets any Command lets any Context implementation be passed 
>> in, but still provide generic access to the specialized properties 
>> without casting.  For example, if your Command is passed in a 
>> ServletWebContext you can try:
>>
>>  Map map = (Map) context.getAttributes().get("requestScope");
>>
>> without having to know what Context implementation was used.  The 
>> things that are accessed through the typesafe property getters and 
>> setters are *not* hidden; and you can program solely to the generic 
>> Context API if you want to avoid creating dependencies on external 
>> Context implementation classes that may or may not be present.
>
>
> It still doesn't seem like we're answering the question of why does 
> the context have-a-map instead of being-a-map. If Context extended 
> Map, rather than specify a Map property, could not the BaseContext 
> implement the ContextBaseAttributes code directly, instead of as a 
> property? Why is it
>
> context.getAttributes().get("attribute);
>
> instead of
>
> context.get("attribute");
>
> As you've said, we already have a standard interface for a Context ... 
> Map =:) Why are we creating another? (An object with a Map.) Are we 
> just following the example set by ServletContext? That in itself is a 
> fair-enough reason, but I wondered if there were another.
>
> (Another reason might be that isEmpty could conflict with a client 
> attribute (but, conceivably, so could getAttributes)).
>
> Of course, it's not hard to have it both ways. I've been using a 
> ContextMap class as a base, which I'll post as another experimental 
> class. It just implements the Map interface by calling getAttributes. 
> (Should we setup a "whiteboard" or "opt" package for these?)

We haven't released anything yet ... why not just check it in to the 
o.a.c.c.impl package so we can all take a look.  We need to completely 
fulfill the Map contracts if we go this way, and I have some concerns 
about that.

>
>
>> My problem with this is what it does to implementors of subclasses of 
>> such a BaseContext2.
>>
>> Lots of people can type the idiom for creating a new property on a 
>> JavaBean without even thinking about it:
>>
>>    private String foo;
>>    public String getFoo() { return this.foo; }
>>    public void setFoo(String foo) { this.foo = foo; }
>>
>> and there are lots of IDEs that will do it for you too.  
>> Unfortunately, such code won't work in a BaseContext2 subclass; you'd 
>> have to change it to:
>>
>>    public String getFoo() { return ((String) 
>> getAttributes().get("foo")); }
>>    public void setFoo(String foo) { getAttributes().put("foo", foo); }
>>
>> I can guarantee you that this kind of code doesn't roll straight off 
>> your fingertips :-).
>
>
> Either approach works with Base2. You can mix and match member fields 
> with Map entries. I definitely wouldn't suggest obviating member 
> fields, since it's such a common strategy.
>
> The code I use now to access the Map entries as property values looks 
> like this:
>
>     public String getApplicant() {
>         return (String) getField(Tokens.PN_APPLICANT);
>     }
>
>     public void setApplicant(String property) {
>         putField(Tokens.PN_APPLICANT, property);
>     }
>
> And I've the IDE programed to prompt me for the Property and Token 
> names when I need to create one of these, so it's not so hard. 
> (Though, just telling it to encapsulate a field is even easier.)
>
> As it stands, I'm not declaring properties for simple String fields, 
> but only for key fields that are often used in API class and those 
> that need type-safety. So like 80% of the attributes don't need 
> properties anyway.
>
> What I don't like is that getField and putField bypass the reflection 
> mechanism, and so become a backdoor that accesses the underlying 
> attribute map directly. At the very least, this seems to bend 
> encapsulation.
>
> I do believe that it would be better if we didn't compel people to use 
> member fields when there's a perfectly good Map sitting there, but I'm 
> still not thrilled with my implementation.
>
>
>> The other complication would be you can't do this for primitive 
>> properties, since  you can't store them in the real Map.
>
>
> I suppose the properties could store them in the wrapper classes and 
> turn them back to primitives on the way back. Since most data access 
> tools don't like primitives, I rarely use them as attributes myself.

But they are commonly used as properties ... which is what the typesafe 
attributes look like to a user of a Context.  On the other hand, if 
Context is-a Map then people will be used to using the wrapper classes 
around these things anyway.

>
> -Ted.

Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> The latter lets any Command lets any Context implementation be passed 
>> in, but still provide generic access to the specialized properties 
>> without casting.  For example, if your Command is passed in a 
>> ServletWebContext you can try:
>>
>>  Map map = (Map) context.getAttributes().get("requestScope");
>>
>> without having to know what Context implementation was used.  The 
>> things that are accessed through the typesafe property getters and 
>> setters are *not* hidden; and you can program solely to the generic 
>> Context API if you want to avoid creating dependencies on external 
>> Context implementation classes that may or may not be present.
>
>
> It still doesn't seem like we're answering the question of why does 
> the context have-a-map instead of being-a-map. If Context extended 
> Map, rather than specify a Map property, could not the BaseContext 
> implement the ContextBaseAttributes code directly, instead of as a 
> property? Why is it
>
> context.getAttributes().get("attribute);
>
> instead of
>
> context.get("attribute");
>
> As you've said, we already have a standard interface for a Context ... 
> Map =:) Why are we creating another? (An object with a Map.) Are we 
> just following the example set by ServletContext? That in itself is a 
> fair-enough reason, but I wondered if there were another.
>
> (Another reason might be that isEmpty could conflict with a client 
> attribute (but, conceivably, so could getAttributes)).
>
> Of course, it's not hard to have it both ways. I've been using a 
> ContextMap class as a base, which I'll post as another experimental 
> class. It just implements the Map interface by calling getAttributes. 
> (Should we setup a "whiteboard" or "opt" package for these?)

We haven't released anything yet ... why not just check it in to the 
o.a.c.c.impl package so we can all take a look.  We need to completely 
fulfill the Map contracts if we go this way, and I have some concerns 
about that.

>
>
>> My problem with this is what it does to implementors of subclasses of 
>> such a BaseContext2.
>>
>> Lots of people can type the idiom for creating a new property on a 
>> JavaBean without even thinking about it:
>>
>>    private String foo;
>>    public String getFoo() { return this.foo; }
>>    public void setFoo(String foo) { this.foo = foo; }
>>
>> and there are lots of IDEs that will do it for you too.  
>> Unfortunately, such code won't work in a BaseContext2 subclass; you'd 
>> have to change it to:
>>
>>    public String getFoo() { return ((String) 
>> getAttributes().get("foo")); }
>>    public void setFoo(String foo) { getAttributes().put("foo", foo); }
>>
>> I can guarantee you that this kind of code doesn't roll straight off 
>> your fingertips :-).
>
>
> Either approach works with Base2. You can mix and match member fields 
> with Map entries. I definitely wouldn't suggest obviating member 
> fields, since it's such a common strategy.
>
> The code I use now to access the Map entries as property values looks 
> like this:
>
>     public String getApplicant() {
>         return (String) getField(Tokens.PN_APPLICANT);
>     }
>
>     public void setApplicant(String property) {
>         putField(Tokens.PN_APPLICANT, property);
>     }
>
> And I've the IDE programed to prompt me for the Property and Token 
> names when I need to create one of these, so it's not so hard. 
> (Though, just telling it to encapsulate a field is even easier.)
>
> As it stands, I'm not declaring properties for simple String fields, 
> but only for key fields that are often used in API class and those 
> that need type-safety. So like 80% of the attributes don't need 
> properties anyway.
>
> What I don't like is that getField and putField bypass the reflection 
> mechanism, and so become a backdoor that accesses the underlying 
> attribute map directly. At the very least, this seems to bend 
> encapsulation.
>
> I do believe that it would be better if we didn't compel people to use 
> member fields when there's a perfectly good Map sitting there, but I'm 
> still not thrilled with my implementation.
>
>
>> The other complication would be you can't do this for primitive 
>> properties, since  you can't store them in the real Map.
>
>
> I suppose the properties could store them in the wrapper classes and 
> turn them back to primitives on the way back. Since most data access 
> tools don't like primitives, I rarely use them as attributes myself.

But they are commonly used as properties ... which is what the typesafe 
attributes look like to a user of a Context.  On the other hand, if 
Context is-a Map then people will be used to using the wrapper classes 
around these things anyway.

>
> -Ted.

Craig



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> The latter lets any Command lets any Context implementation be passed 
> in, but still provide generic access to the specialized properties 
> without casting.  For example, if your Command is passed in a 
> ServletWebContext you can try:
> 
>  Map map = (Map) context.getAttributes().get("requestScope");
> 
> without having to know what Context implementation was used.  The things 
> that are accessed through the typesafe property getters and setters are 
> *not* hidden; and you can program solely to the generic Context API if 
> you want to avoid creating dependencies on external Context 
> implementation classes that may or may not be present.

It still doesn't seem like we're answering the question of why does the 
context have-a-map instead of being-a-map. If Context extended Map, 
rather than specify a Map property, could not the BaseContext implement 
the ContextBaseAttributes code directly, instead of as a property? Why is it

context.getAttributes().get("attribute);

instead of

context.get("attribute");

As you've said, we already have a standard interface for a Context ... 
Map =:) Why are we creating another? (An object with a Map.) Are we just 
following the example set by ServletContext? That in itself is a 
fair-enough reason, but I wondered if there were another.

(Another reason might be that isEmpty could conflict with a client 
attribute (but, conceivably, so could getAttributes)).

Of course, it's not hard to have it both ways. I've been using a 
ContextMap class as a base, which I'll post as another experimental 
class. It just implements the Map interface by calling getAttributes. 
(Should we setup a "whiteboard" or "opt" package for these?)


> My problem with this is what it does to implementors of subclasses of 
> such a BaseContext2.
> 
> Lots of people can type the idiom for creating a new property on a 
> JavaBean without even thinking about it:
> 
>    private String foo;
>    public String getFoo() { return this.foo; }
>    public void setFoo(String foo) { this.foo = foo; }
> 
> and there are lots of IDEs that will do it for you too.  Unfortunately, 
> such code won't work in a BaseContext2 subclass; you'd have to change it 
> to:
> 
>    public String getFoo() { return ((String) getAttributes().get("foo")); }
>    public void setFoo(String foo) { getAttributes().put("foo", foo); }
> 
> I can guarantee you that this kind of code doesn't roll straight off 
> your fingertips :-).

Either approach works with Base2. You can mix and match member fields 
with Map entries. I definitely wouldn't suggest obviating member fields, 
since it's such a common strategy.

The code I use now to access the Map entries as property values looks 
like this:

     public String getApplicant() {
         return (String) getField(Tokens.PN_APPLICANT);
     }

     public void setApplicant(String property) {
         putField(Tokens.PN_APPLICANT, property);
     }

And I've the IDE programed to prompt me for the Property and Token names 
when I need to create one of these, so it's not so hard. (Though, just 
telling it to encapsulate a field is even easier.)

As it stands, I'm not declaring properties for simple String fields, but 
only for key fields that are often used in API class and those that need 
type-safety. So like 80% of the attributes don't need properties anyway.

What I don't like is that getField and putField bypass the reflection 
mechanism, and so become a backdoor that accesses the underlying 
attribute map directly. At the very least, this seems to bend 
encapsulation.

I do believe that it would be better if we didn't compel people to use 
member fields when there's a perfectly good Map sitting there, but I'm 
still not thrilled with my implementation.


> The other complication would be you can't do this for primitive 
> properties, since  you can't store them in the real Map.

I suppose the properties could store them in the wrapper classes and 
turn them back to primitives on the way back. Since most data access 
tools don't like primitives, I rarely use them as attributes myself.

-Ted.




Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> The latter lets any Command lets any Context implementation be passed 
> in, but still provide generic access to the specialized properties 
> without casting.  For example, if your Command is passed in a 
> ServletWebContext you can try:
> 
>  Map map = (Map) context.getAttributes().get("requestScope");
> 
> without having to know what Context implementation was used.  The things 
> that are accessed through the typesafe property getters and setters are 
> *not* hidden; and you can program solely to the generic Context API if 
> you want to avoid creating dependencies on external Context 
> implementation classes that may or may not be present.

It still doesn't seem like we're answering the question of why does the 
context have-a-map instead of being-a-map. If Context extended Map, 
rather than specify a Map property, could not the BaseContext implement 
the ContextBaseAttributes code directly, instead of as a property? Why is it

context.getAttributes().get("attribute);

instead of

context.get("attribute");

As you've said, we already have a standard interface for a Context ... 
Map =:) Why are we creating another? (An object with a Map.) Are we just 
following the example set by ServletContext? That in itself is a 
fair-enough reason, but I wondered if there were another.

(Another reason might be that isEmpty could conflict with a client 
attribute (but, conceivably, so could getAttributes)).

Of course, it's not hard to have it both ways. I've been using a 
ContextMap class as a base, which I'll post as another experimental 
class. It just implements the Map interface by calling getAttributes. 
(Should we setup a "whiteboard" or "opt" package for these?)


> My problem with this is what it does to implementors of subclasses of 
> such a BaseContext2.
> 
> Lots of people can type the idiom for creating a new property on a 
> JavaBean without even thinking about it:
> 
>    private String foo;
>    public String getFoo() { return this.foo; }
>    public void setFoo(String foo) { this.foo = foo; }
> 
> and there are lots of IDEs that will do it for you too.  Unfortunately, 
> such code won't work in a BaseContext2 subclass; you'd have to change it 
> to:
> 
>    public String getFoo() { return ((String) getAttributes().get("foo")); }
>    public void setFoo(String foo) { getAttributes().put("foo", foo); }
> 
> I can guarantee you that this kind of code doesn't roll straight off 
> your fingertips :-).

Either approach works with Base2. You can mix and match member fields 
with Map entries. I definitely wouldn't suggest obviating member fields, 
since it's such a common strategy.

The code I use now to access the Map entries as property values looks 
like this:

     public String getApplicant() {
         return (String) getField(Tokens.PN_APPLICANT);
     }

     public void setApplicant(String property) {
         putField(Tokens.PN_APPLICANT, property);
     }

And I've the IDE programed to prompt me for the Property and Token names 
when I need to create one of these, so it's not so hard. (Though, just 
telling it to encapsulate a field is even easier.)

As it stands, I'm not declaring properties for simple String fields, but 
only for key fields that are often used in API class and those that need 
type-safety. So like 80% of the attributes don't need properties anyway.

What I don't like is that getField and putField bypass the reflection 
mechanism, and so become a backdoor that accesses the underlying 
attribute map directly. At the very least, this seems to bend 
encapsulation.

I do believe that it would be better if we didn't compel people to use 
member fields when there's a perfectly good Map sitting there, but I'm 
still not thrilled with my implementation.


> The other complication would be you can't do this for primitive 
> properties, since  you can't store them in the real Map.

I suppose the properties could store them in the wrapper classes and 
turn them back to primitives on the way back. Since most data access 
tools don't like primitives, I rarely use them as attributes myself.

-Ted.




---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> Do you think we should make a Catalog an optional property of a 
>> Context?  A lot of use cases would like to have a default spot to go 
>> find one, and you can always have private conventions about what 
>> other attribute keys might also point at other Catalogs.
>
>
> If we are talking about the Context interface, it might be 
> problematic, since it would seem that any property we define there 
> would steal it from the application. So, they could not have a 
> "context" attribute of their own, even if they were using context in, 
> well, a different context =:)

Yep :-).

>
> But if by optional we mean a property on a base implementation, then 
> that would seem all right. Worst case, they implement their own base. 
> I like the loosely knit relationships between the three interfaces, 
> but at some point implementations do need to start to nail things down 
> for people.

Agreed.  We want the right balance of ease-of-use and flexibility.

>
> Of course, once we do that, a question someone is going to ask 
> sometime is "Why doesn't the Command just have a pointer to its 
> Catalog?" I'm not convinced it would be a good idea, but it's 
> something we should ask and answer.

Thinking out loud to get my initial answers down for posterity, I don't 
think we want to require the use of Catalogs at all.  I *certainly* 
don't think we should constrain a Command (or Chain) instance to be 
associated with a single Catalog.

>
> Another popular question will be, "Why isn't the Context itself a Map?"

Well, it is-a Map of sorts (or more precisely, it has-a Map as its data 
representation).  But what it also offers is a couple of interesting things:

* Ability to have type-safe accessors like any JavaBean.

* Attribute-property transparency (at least if you implement the Javadoc
  contracts for Context, or use ContextBase to do the hard part for you).

The latter lets any Command lets any Context implementation be passed 
in, but still provide generic access to the specialized properties 
without casting.  For example, if your Command is passed in a 
ServletWebContext you can try:

  Map map = (Map) context.getAttributes().get("requestScope");

without having to know what Context implementation was used.  The things 
that are accessed through the typesafe property getters and setters are 
*not* hidden; and you can program solely to the generic Context API if 
you want to avoid creating dependencies on external Context 
implementation classes that may or may not be present.

>
> In my own base class, I needed to make it a Map (through composition - 
> the Map methods just call back to getAttributes) so it could mesh with 
> other parts of the application. It's going to be a FAQ, so we might 
> want to deal with it now.

As pointed out in the discussion below, it's not necessarily trivial to 
do this.

>
> I think the answer is going to be extensibility, but we might consider 
> an optional implementation that provides a Map interface for people to 
> use.
>
> On a related subject, how do we feel about the BaseContext2 class that 
> allows property fields to be stored in the attribute Map? I have mixed 
> feelings about the implementation, since it bends encapsulation, but I 
> *really* like the idea of keeping all my fields and attributes together.

My problem with this is what it does to implementors of subclasses of 
such a BaseContext2.

Lots of people can type the idiom for creating a new property on a 
JavaBean without even thinking about it:

    private String foo;
    public String getFoo() { return this.foo; }
    public void setFoo(String foo) { this.foo = foo; }

and there are lots of IDEs that will do it for you too.  Unfortunately, 
such code won't work in a BaseContext2 subclass; you'd have to change it to:

    public String getFoo() { return ((String) getAttributes().get("foo")); }
    public void setFoo(String foo) { getAttributes().put("foo", foo); }

I can guarantee you that this kind of code doesn't roll straight off 
your fingertips :-).

A different approach to meet your desire might be to actually store the 
property names in the existing Map, with the values pointing back at the 
actual instance variables.  We'd probably want to make remove() throw 
IllegalArgumentException on attempts to remove them.  The other 
complication would be you can't do this for primitive properties, since 
you can't store them in the real Map.

>
> -Ted.

Craig

>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> Do you think we should make a Catalog an optional property of a 
>> Context?  A lot of use cases would like to have a default spot to go 
>> find one, and you can always have private conventions about what 
>> other attribute keys might also point at other Catalogs.
>
>
> If we are talking about the Context interface, it might be 
> problematic, since it would seem that any property we define there 
> would steal it from the application. So, they could not have a 
> "context" attribute of their own, even if they were using context in, 
> well, a different context =:)

Yep :-).

>
> But if by optional we mean a property on a base implementation, then 
> that would seem all right. Worst case, they implement their own base. 
> I like the loosely knit relationships between the three interfaces, 
> but at some point implementations do need to start to nail things down 
> for people.

Agreed.  We want the right balance of ease-of-use and flexibility.

>
> Of course, once we do that, a question someone is going to ask 
> sometime is "Why doesn't the Command just have a pointer to its 
> Catalog?" I'm not convinced it would be a good idea, but it's 
> something we should ask and answer.

Thinking out loud to get my initial answers down for posterity, I don't 
think we want to require the use of Catalogs at all.  I *certainly* 
don't think we should constrain a Command (or Chain) instance to be 
associated with a single Catalog.

>
> Another popular question will be, "Why isn't the Context itself a Map?"

Well, it is-a Map of sorts (or more precisely, it has-a Map as its data 
representation).  But what it also offers is a couple of interesting things:

* Ability to have type-safe accessors like any JavaBean.

* Attribute-property transparency (at least if you implement the Javadoc
  contracts for Context, or use ContextBase to do the hard part for you).

The latter lets any Command lets any Context implementation be passed 
in, but still provide generic access to the specialized properties 
without casting.  For example, if your Command is passed in a 
ServletWebContext you can try:

  Map map = (Map) context.getAttributes().get("requestScope");

without having to know what Context implementation was used.  The things 
that are accessed through the typesafe property getters and setters are 
*not* hidden; and you can program solely to the generic Context API if 
you want to avoid creating dependencies on external Context 
implementation classes that may or may not be present.

>
> In my own base class, I needed to make it a Map (through composition - 
> the Map methods just call back to getAttributes) so it could mesh with 
> other parts of the application. It's going to be a FAQ, so we might 
> want to deal with it now.

As pointed out in the discussion below, it's not necessarily trivial to 
do this.

>
> I think the answer is going to be extensibility, but we might consider 
> an optional implementation that provides a Map interface for people to 
> use.
>
> On a related subject, how do we feel about the BaseContext2 class that 
> allows property fields to be stored in the attribute Map? I have mixed 
> feelings about the implementation, since it bends encapsulation, but I 
> *really* like the idea of keeping all my fields and attributes together.

My problem with this is what it does to implementors of subclasses of 
such a BaseContext2.

Lots of people can type the idiom for creating a new property on a 
JavaBean without even thinking about it:

    private String foo;
    public String getFoo() { return this.foo; }
    public void setFoo(String foo) { this.foo = foo; }

and there are lots of IDEs that will do it for you too.  Unfortunately, 
such code won't work in a BaseContext2 subclass; you'd have to change it to:

    public String getFoo() { return ((String) getAttributes().get("foo")); }
    public void setFoo(String foo) { getAttributes().put("foo", foo); }

I can guarantee you that this kind of code doesn't roll straight off 
your fingertips :-).

A different approach to meet your desire might be to actually store the 
property names in the existing Map, with the values pointing back at the 
actual instance variables.  We'd probably want to make remove() throw 
IllegalArgumentException on attempts to remove them.  The other 
complication would be you can't do this for primitive properties, since 
you can't store them in the real Map.

>
> -Ted.

Craig

>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org




Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> Do you think we should make a Catalog an optional property of a 
> Context?  A lot of use cases would like to have a default spot to go 
> find one, and you can always have private conventions about what other 
> attribute keys might also point at other Catalogs.

If we are talking about the Context interface, it might be problematic, 
since it would seem that any property we define there would steal it 
from the application. So, they could not have a "context" attribute of 
their own, even if they were using context in, well, a different context =:)

But if by optional we mean a property on a base implementation, then 
that would seem all right. Worst case, they implement their own base. I 
like the loosely knit relationships between the three interfaces, but at 
some point implementations do need to start to nail things down for people.

Of course, once we do that, a question someone is going to ask sometime 
is "Why doesn't the Command just have a pointer to its Catalog?" I'm not 
convinced it would be a good idea, but it's something we should ask and 
answer.

Another popular question will be, "Why isn't the Context itself a Map?"

In my own base class, I needed to make it a Map (through composition - 
the Map methods just call back to getAttributes) so it could mesh with 
other parts of the application. It's going to be a FAQ, so we might want 
to deal with it now.

I think the answer is going to be extensibility, but we might consider 
an optional implementation that provides a Map interface for people to use.

On a related subject, how do we feel about the BaseContext2 class that 
allows property fields to be stored in the attribute Map? I have mixed 
feelings about the implementation, since it bends encapsulation, but I 
*really* like the idea of keeping all my fields and attributes together.

-Ted.



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> Do you think we should make a Catalog an optional property of a 
> Context?  A lot of use cases would like to have a default spot to go 
> find one, and you can always have private conventions about what other 
> attribute keys might also point at other Catalogs.

If we are talking about the Context interface, it might be problematic, 
since it would seem that any property we define there would steal it 
from the application. So, they could not have a "context" attribute of 
their own, even if they were using context in, well, a different context =:)

But if by optional we mean a property on a base implementation, then 
that would seem all right. Worst case, they implement their own base. I 
like the loosely knit relationships between the three interfaces, but at 
some point implementations do need to start to nail things down for people.

Of course, once we do that, a question someone is going to ask sometime 
is "Why doesn't the Command just have a pointer to its Catalog?" I'm not 
convinced it would be a good idea, but it's something we should ask and 
answer.

Another popular question will be, "Why isn't the Context itself a Map?"

In my own base class, I needed to make it a Map (through composition - 
the Map methods just call back to getAttributes) so it could mesh with 
other parts of the application. It's going to be a FAQ, so we might want 
to deal with it now.

I think the answer is going to be extensibility, but we might consider 
an optional implementation that provides a Map interface for people to use.

On a related subject, how do we feel about the BaseContext2 class that 
allows property fields to be stored in the attribute Map? I have mixed 
feelings about the implementation, since it bends encapsulation, but I 
*really* like the idea of keeping all my fields and attributes together.

-Ted.



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> Far better would be to divide the procedural flow into small steps 
>> that are externally configurable.  And, let each step have its own 
>> arbitrarily complex internal structure (by virtue of the fact that it 
>> can be a Command or a Chain of its own).  Oh, by the way, the 
>> procedural steps become small enough and narrowly focused enough to 
>> write high quality unit tests for.  And, because commands interact 
>> with each other *solely* through a Context, you can easily create 
>> mock objects (like a ServletContext or an HttpSession, in a chain 
>> destined for a web applicaton) that let you thoroughly test things in 
>> a standalone environment (in case it's not obvious, I'm a *huge* fan 
>> of JUnit :-).
>
>
> Me too. =:) Right now, I've got my DAO layer (which also uses a XML 
> config) running under the JUnit applet or as an Ant task. I can't seem 
> to get Chain running that way. It's fine as an Ant task, but when I 
> try to run it under the applet, my Commands table comes up empty =:(
>
> Obviously, I need to define this better, provide a demnstration 
> environment, but I thought I'd bring this up in case anyone had a clue 
> for a quick fix. [That green bar is soooo addictive :)]

Doesn't sound familiar, but use the Ant task variant myself.  Perhaps a 
class loader problem; perhaps related to the XML parsing?

>
> Though, my unit tests for the Commands don't utilize mocks. They just 
> populate the Context directly and pass it up. Of course, there's the 
> part where the Context is created from the request paramenters, but 
> that's a separate test suite that isn't coupled to the Commands.

That's the approach I take as well.

>
> For end-to-end integration, Cannoo Webtest pulls it all together 
> nicely. Need to run the container running for that one, but it doesn't 
> involve loading Cactus or anything like that, so those run very quickly.

For web stuff in particular, I've also found HtmlUnit to be quite 
helpful -- it lets you treat the response page as a DOM and look for 
various things, without the fragility of comparisons to a static golden 
file that is sensitive to changes in whitespace that are not usually 
important.

>
>
>> Indeed, the only reason that Catalog exists is to allow chains to 
>> refer to other chains in an organized way.  One could argue that even 
>> this is out of scope; however, it's very useful to be able to write a 
>> Command that uses complex processing logic to decide which other 
>> commands (or chains, since you can't tell in the catalog what 
>> something is) should be used to actually perform a task.
>
>
> IMHO, the Catalog construct places a key role in decoupling the sender 
> from receiver, as specified by the CoR pattern. Right now, I have a 
> command-name coming up from the web tier. The presentation framework 
> requesting the command has no idea how it will be handled. It just 
> knows how to create a given Context for a given Command, according to 
> a high-level API contract. All it really knows is the logical name and 
> parameters required. The Catalog takes care of selecting the 
> Command/Chain to process, in much the same way a framework like Struts 
> takes care of selecting the Action class to execute.
>
> If an implementation exposes the Catalog to the Command/Chains, then 
> another usage is to allow Commands to call one another through the 
> Catalog. As mentioned, this allows any number of clever strategies for 
> creating "framework" chains that can be reused in different ways under 
> different circumstances. This usage can also make the Catalogs more 
> testable, since a test could substitute a "mock" Command, if such a 
> thing were desired.

Do you think we should make a Catalog an optional property of a 
Context?  A lot of use cases would like to have a default spot to go 
find one, and you can always have private conventions about what other 
attribute keys might also point at other Catalogs.

>
> But, I would argue that these benefits are still secondary to the core 
> need to cleanly decouple sender from the receiver.
>
> -Ted.
>
>
>
Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> Far better would be to divide the procedural flow into small steps 
>> that are externally configurable.  And, let each step have its own 
>> arbitrarily complex internal structure (by virtue of the fact that it 
>> can be a Command or a Chain of its own).  Oh, by the way, the 
>> procedural steps become small enough and narrowly focused enough to 
>> write high quality unit tests for.  And, because commands interact 
>> with each other *solely* through a Context, you can easily create 
>> mock objects (like a ServletContext or an HttpSession, in a chain 
>> destined for a web applicaton) that let you thoroughly test things in 
>> a standalone environment (in case it's not obvious, I'm a *huge* fan 
>> of JUnit :-).
>
>
> Me too. =:) Right now, I've got my DAO layer (which also uses a XML 
> config) running under the JUnit applet or as an Ant task. I can't seem 
> to get Chain running that way. It's fine as an Ant task, but when I 
> try to run it under the applet, my Commands table comes up empty =:(
>
> Obviously, I need to define this better, provide a demnstration 
> environment, but I thought I'd bring this up in case anyone had a clue 
> for a quick fix. [That green bar is soooo addictive :)]

Doesn't sound familiar, but use the Ant task variant myself.  Perhaps a 
class loader problem; perhaps related to the XML parsing?

>
> Though, my unit tests for the Commands don't utilize mocks. They just 
> populate the Context directly and pass it up. Of course, there's the 
> part where the Context is created from the request paramenters, but 
> that's a separate test suite that isn't coupled to the Commands.

That's the approach I take as well.

>
> For end-to-end integration, Cannoo Webtest pulls it all together 
> nicely. Need to run the container running for that one, but it doesn't 
> involve loading Cactus or anything like that, so those run very quickly.

For web stuff in particular, I've also found HtmlUnit to be quite 
helpful -- it lets you treat the response page as a DOM and look for 
various things, without the fragility of comparisons to a static golden 
file that is sensitive to changes in whitespace that are not usually 
important.

>
>
>> Indeed, the only reason that Catalog exists is to allow chains to 
>> refer to other chains in an organized way.  One could argue that even 
>> this is out of scope; however, it's very useful to be able to write a 
>> Command that uses complex processing logic to decide which other 
>> commands (or chains, since you can't tell in the catalog what 
>> something is) should be used to actually perform a task.
>
>
> IMHO, the Catalog construct places a key role in decoupling the sender 
> from receiver, as specified by the CoR pattern. Right now, I have a 
> command-name coming up from the web tier. The presentation framework 
> requesting the command has no idea how it will be handled. It just 
> knows how to create a given Context for a given Command, according to 
> a high-level API contract. All it really knows is the logical name and 
> parameters required. The Catalog takes care of selecting the 
> Command/Chain to process, in much the same way a framework like Struts 
> takes care of selecting the Action class to execute.
>
> If an implementation exposes the Catalog to the Command/Chains, then 
> another usage is to allow Commands to call one another through the 
> Catalog. As mentioned, this allows any number of clever strategies for 
> creating "framework" chains that can be reused in different ways under 
> different circumstances. This usage can also make the Catalogs more 
> testable, since a test could substitute a "mock" Command, if such a 
> thing were desired.

Do you think we should make a Catalog an optional property of a 
Context?  A lot of use cases would like to have a default spot to go 
find one, and you can always have private conventions about what other 
attribute keys might also point at other Catalogs.

>
> But, I would argue that these benefits are still secondary to the core 
> need to cleanly decouple sender from the receiver.
>
> -Ted.
>
>
>
Craig



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> Far better would be to divide the procedural flow into small steps that 
> are externally configurable.  And, let each step have its own 
> arbitrarily complex internal structure (by virtue of the fact that it 
> can be a Command or a Chain of its own).  Oh, by the way, the procedural 
> steps become small enough and narrowly focused enough to write high 
> quality unit tests for.  And, because commands interact with each other 
> *solely* through a Context, you can easily create mock objects (like a 
> ServletContext or an HttpSession, in a chain destined for a web 
> applicaton) that let you thoroughly test things in a standalone 
> environment (in case it's not obvious, I'm a *huge* fan of JUnit :-).

Me too. =:) Right now, I've got my DAO layer (which also uses a XML 
config) running under the JUnit applet or as an Ant task. I can't seem 
to get Chain running that way. It's fine as an Ant task, but when I try 
to run it under the applet, my Commands table comes up empty =:(

Obviously, I need to define this better, provide a demnstration 
environment, but I thought I'd bring this up in case anyone had a clue 
for a quick fix. [That green bar is soooo addictive :)]

Though, my unit tests for the Commands don't utilize mocks. They just 
populate the Context directly and pass it up. Of course, there's the 
part where the Context is created from the request paramenters, but 
that's a separate test suite that isn't coupled to the Commands.

For end-to-end integration, Cannoo Webtest pulls it all together nicely. 
Need to run the container running for that one, but it doesn't involve 
loading Cactus or anything like that, so those run very quickly.


> Indeed, the only reason that Catalog exists is to allow chains to refer 
> to other chains in an organized way.  One could argue that even this is 
> out of scope; however, it's very useful to be able to write a Command 
> that uses complex processing logic to decide which other commands (or 
> chains, since you can't tell in the catalog what something is) should be 
> used to actually perform a task.

IMHO, the Catalog construct places a key role in decoupling the sender 
from receiver, as specified by the CoR pattern. Right now, I have a 
command-name coming up from the web tier. The presentation framework 
requesting the command has no idea how it will be handled. It just knows 
how to create a given Context for a given Command, according to a 
high-level API contract. All it really knows is the logical name and 
parameters required. The Catalog takes care of selecting the 
Command/Chain to process, in much the same way a framework like Struts 
takes care of selecting the Action class to execute.

If an implementation exposes the Catalog to the Command/Chains, then 
another usage is to allow Commands to call one another through the 
Catalog. As mentioned, this allows any number of clever strategies for 
creating "framework" chains that can be reused in different ways under 
different circumstances. This usage can also make the Catalogs more 
testable, since a test could substitute a "mock" Command, if such a 
thing were desired.

But, I would argue that these benefits are still secondary to the core 
need to cleanly decouple sender from the receiver.

-Ted.



-- 
Ted Husted,
   Junit in Action  - <http://www.manning.com/massol/>,
   Struts in Action - <http://husted.com/struts/book.html>,
   JSP Site Design  - <http://www.amazon.com/exec/obidos/ISBN=1861005512>.

"Get Ready, We're Moving Out!!" - <http://www.clark04.com>



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Craig R. McClanahan wrote:
> Far better would be to divide the procedural flow into small steps that 
> are externally configurable.  And, let each step have its own 
> arbitrarily complex internal structure (by virtue of the fact that it 
> can be a Command or a Chain of its own).  Oh, by the way, the procedural 
> steps become small enough and narrowly focused enough to write high 
> quality unit tests for.  And, because commands interact with each other 
> *solely* through a Context, you can easily create mock objects (like a 
> ServletContext or an HttpSession, in a chain destined for a web 
> applicaton) that let you thoroughly test things in a standalone 
> environment (in case it's not obvious, I'm a *huge* fan of JUnit :-).

Me too. =:) Right now, I've got my DAO layer (which also uses a XML 
config) running under the JUnit applet or as an Ant task. I can't seem 
to get Chain running that way. It's fine as an Ant task, but when I try 
to run it under the applet, my Commands table comes up empty =:(

Obviously, I need to define this better, provide a demnstration 
environment, but I thought I'd bring this up in case anyone had a clue 
for a quick fix. [That green bar is soooo addictive :)]

Though, my unit tests for the Commands don't utilize mocks. They just 
populate the Context directly and pass it up. Of course, there's the 
part where the Context is created from the request paramenters, but 
that's a separate test suite that isn't coupled to the Commands.

For end-to-end integration, Cannoo Webtest pulls it all together nicely. 
Need to run the container running for that one, but it doesn't involve 
loading Cactus or anything like that, so those run very quickly.


> Indeed, the only reason that Catalog exists is to allow chains to refer 
> to other chains in an organized way.  One could argue that even this is 
> out of scope; however, it's very useful to be able to write a Command 
> that uses complex processing logic to decide which other commands (or 
> chains, since you can't tell in the catalog what something is) should be 
> used to actually perform a task.

IMHO, the Catalog construct places a key role in decoupling the sender 
from receiver, as specified by the CoR pattern. Right now, I have a 
command-name coming up from the web tier. The presentation framework 
requesting the command has no idea how it will be handled. It just knows 
how to create a given Context for a given Command, according to a 
high-level API contract. All it really knows is the logical name and 
parameters required. The Catalog takes care of selecting the 
Command/Chain to process, in much the same way a framework like Struts 
takes care of selecting the Action class to execute.

If an implementation exposes the Catalog to the Command/Chains, then 
another usage is to allow Commands to call one another through the 
Catalog. As mentioned, this allows any number of clever strategies for 
creating "framework" chains that can be reused in different ways under 
different circumstances. This usage can also make the Catalogs more 
testable, since a test could substitute a "mock" Command, if such a 
thing were desired.

But, I would argue that these benefits are still secondary to the core 
need to cleanly decouple sender from the receiver.

-Ted.



-- 
Ted Husted,
   Junit in Action  - <http://www.manning.com/massol/>,
   Struts in Action - <http://husted.com/struts/book.html>,
   JSP Site Design  - <http://www.amazon.com/exec/obidos/ISBN=1861005512>.

"Get Ready, We're Moving Out!!" - <http://www.clark04.com>



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Jelly] is this the main Jelly list ?

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Tony Pelton wrote:

>hi,
>
>new guy here.
>
>is this the Jelly list in addition to obviously being the list for a bunch of 
>other stuff ?
>
>i just wasn't sure if i had actually subscribed to the correct list.
>
>tia,
>Tony
>
>  
>
This is the list where the developers of the various jakarta-commons 
packages hang out, and that includes Jelly.  You'll find a corresponding 
list (commons-user@jakarta.apache.org) for more user-oriented questions; 
again for all of the commons packages.

You'll find a common convention is to do what you did -- decorate your 
subject like with [Jelly], or whatever other package you're interested 
in talking about.  This helps readers filter out whether they are 
interested in that particular message or not.

Craig



Re: [Jelly] is this the main Jelly list ?

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Tony Pelton wrote:

>hi,
>
>new guy here.
>
>is this the Jelly list in addition to obviously being the list for a bunch of 
>other stuff ?
>
>i just wasn't sure if i had actually subscribed to the correct list.
>
>tia,
>Tony
>
>  
>
This is the list where the developers of the various jakarta-commons 
packages hang out, and that includes Jelly.  You'll find a corresponding 
list (commons-user@jakarta.apache.org) for more user-oriented questions; 
again for all of the commons packages.

You'll find a common convention is to do what you did -- decorate your 
subject like with [Jelly], or whatever other package you're interested 
in talking about.  This helps readers filter out whether they are 
interested in that particular message or not.

Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Jelly] is this the main Jelly list ?

Posted by di...@multitask.com.au.
Yep,

this is it.
--
dIon Gillard, Multitask Consulting
Blog:      http://blogs.codehaus.org/people/dion/


Tony Pelton <ja...@dsrts.com> wrote on 27/09/2003 12:29:42 AM:

> hi,
> 
> new guy here.
> 
> is this the Jelly list in addition to obviously being the list for 
abunch of 
> other stuff ?
> 
> i just wasn't sure if i had actually subscribed to the correct list.
> 
> tia,
> Tony
> 
> -- 
> ===
> "They that can give up essential liberty
> to obtain a little temporary safety deserve
>  neither liberty nor safety."
>   -- Benjamin Franklin
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 


Re: [Jelly] is this the main Jelly list ?

Posted by di...@multitask.com.au.
Yep,

this is it.
--
dIon Gillard, Multitask Consulting
Blog:      http://blogs.codehaus.org/people/dion/


Tony Pelton <ja...@dsrts.com> wrote on 27/09/2003 12:29:42 AM:

> hi,
> 
> new guy here.
> 
> is this the Jelly list in addition to obviously being the list for 
abunch of 
> other stuff ?
> 
> i just wasn't sure if i had actually subscribed to the correct list.
> 
> tia,
> Tony
> 
> -- 
> ===
> "They that can give up essential liberty
> to obtain a little temporary safety deserve
>  neither liberty nor safety."
>   -- Benjamin Franklin
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[Jelly] is this the main Jelly list ?

Posted by Tony Pelton <ja...@dsrts.com>.
hi,

new guy here.

is this the Jelly list in addition to obviously being the list for a bunch of 
other stuff ?

i just wasn't sure if i had actually subscribed to the correct list.

tia,
Tony

-- 
===
"They that can give up essential liberty
to obtain a little temporary safety deserve
 neither liberty nor safety."
  -- Benjamin Franklin



[Jelly] is this the main Jelly list ?

Posted by Tony Pelton <ja...@dsrts.com>.
hi,

new guy here.

is this the Jelly list in addition to obviously being the list for a bunch of 
other stuff ?

i just wasn't sure if i had actually subscribed to the correct list.

tia,
Tony

-- 
===
"They that can give up essential liberty
to obtain a little temporary safety deserve
 neither liberty nor safety."
  -- Benjamin Franklin



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> Well my goal with this idea was to make applications less dependent on the
> environment in which they run.  The servlet environment can of course handle
> everything that this Registry can, but it is in the presentation tier.  I
> think the Registry for the business tier should reside in the business tier.
> What if I want to offer a command-line interface to my application for, say,
> unit testing with JUnit (which I can currently do in my app for my DAOs but
> not for my business tier).  If I use the servlet context as a registry then
> it is harder to write these tests.

Then the command-line program might want to use a Singleton. But that's 
up to the application. The key part is you can load the same Catalog 
into your command-line program or into a web application, without 
changing anything internal to the Chain and Command classes.

Right now, Chain is nicely scoped as a business layer framework that 
sits between the Controller and the Persistence Layer. This is a sweet 
spot, and I believe we shouldn't muddy it with trying to handle state.

Making "applications less dependent on the environment in which they 
run", would be the job of an application framework ("a semi-complete 
application"). All the presentation frameworks, including Struts, are 
working in this direction now, by moving towards a Context object that 
help to decouple components from the runtime environment. When they get 
there, Chain and its Context object, will be ready to hook up.


> Hehe, I am often guilty of this in my own work.  How do we get Chain out of
> the sandbox so we can start working on Agility? :)  Should I move over to
> Struts and work on the decomposable request processor that Craig started out
> instead?  I know one area Chain needs work is documentation, and I will be
> working on this in the coming weeks.

The two aren't codependent. But, again, frameworks are best created as 
abstractions of working applications. Without more working applications, 
it's too early to work on anything like a framework. I haven't even 
finished deploying it in one application yet. =:)

One thing that might be helpful is a ChainServlet, so people can plug 
Catalog into working web applications right away. I believe Craig, Greg, 
and I are all just using the Struts plugin right now, but that's only 
one place where it can be used.

Along the same lines, I suppose there could also be something like a 
generic ChainRegistry that was designed to load the Catalog and store it 
behind an interface as a Singleton. This might be something people would 
use in command-line or test programs, and so forth. But anything like 
this should also be strongly cast as optional or example component and 
not considered part of the core API. This is where we step over the line 
from "business layer framework" to "application framework", and I don't 
think that's a line we're ready to cross right now.

-Ted.




Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> Well my goal with this idea was to make applications less dependent on the
> environment in which they run.  The servlet environment can of course handle
> everything that this Registry can, but it is in the presentation tier.  I
> think the Registry for the business tier should reside in the business tier.
> What if I want to offer a command-line interface to my application for, say,
> unit testing with JUnit (which I can currently do in my app for my DAOs but
> not for my business tier).  If I use the servlet context as a registry then
> it is harder to write these tests.

Then the command-line program might want to use a Singleton. But that's 
up to the application. The key part is you can load the same Catalog 
into your command-line program or into a web application, without 
changing anything internal to the Chain and Command classes.

Right now, Chain is nicely scoped as a business layer framework that 
sits between the Controller and the Persistence Layer. This is a sweet 
spot, and I believe we shouldn't muddy it with trying to handle state.

Making "applications less dependent on the environment in which they 
run", would be the job of an application framework ("a semi-complete 
application"). All the presentation frameworks, including Struts, are 
working in this direction now, by moving towards a Context object that 
help to decouple components from the runtime environment. When they get 
there, Chain and its Context object, will be ready to hook up.


> Hehe, I am often guilty of this in my own work.  How do we get Chain out of
> the sandbox so we can start working on Agility? :)  Should I move over to
> Struts and work on the decomposable request processor that Craig started out
> instead?  I know one area Chain needs work is documentation, and I will be
> working on this in the coming weeks.

The two aren't codependent. But, again, frameworks are best created as 
abstractions of working applications. Without more working applications, 
it's too early to work on anything like a framework. I haven't even 
finished deploying it in one application yet. =:)

One thing that might be helpful is a ChainServlet, so people can plug 
Catalog into working web applications right away. I believe Craig, Greg, 
and I are all just using the Struts plugin right now, but that's only 
one place where it can be used.

Along the same lines, I suppose there could also be something like a 
generic ChainRegistry that was designed to load the Catalog and store it 
behind an interface as a Singleton. This might be something people would 
use in command-line or test programs, and so forth. But anything like 
this should also be strongly cast as optional or example component and 
not considered part of the core API. This is where we step over the line 
from "business layer framework" to "application framework", and I don't 
think that's a line we're ready to cross right now.

-Ted.




---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
----- Original Message ----- 
From: "Ted Husted" <hu...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Friday, September 26, 2003 8:10 AM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Sgarlata Matt wrote:
> > I understand this difficulty which is why I was thinking that if we make
it
> > an explicit part of the API that you are supposed to store things in
> > such-and-such place that we could be in good shape.  In the example I
gave,
> > I was trying to say that even if different apps used the same singleton,
> > they would all be isolated from each other by virtue of the fact that
the
> > API tells them that they need to store everything under their own unique
> > attribute name, like com.mycompany.myprogram or org.apache.struts.  This
is
> > like how Java can't guarantee two classes have the same name, but
hopefully
> > if people follow the guidelines they are supposed to in terms of naming
> > their packages then name collisions will be less frequent.
>
> IMHO, the API should leave state to the underlying platform. We can
> provide various examples of where you might store state for this
> platform and that platform. For the most part, if Commands need to refer
> to Commands, then the application can pass the Catalog up through the
> Context. The API defines a place to store things, the Context, another
> seems redundant.
>
> Whether the Context is backed by a Singleton, the Servlet Context, or
> something else, can be left to the application.

Well my goal with this idea was to make applications less dependent on the
environment in which they run.  The servlet environment can of course handle
everything that this Registry can, but it is in the presentation tier.  I
think the Registry for the business tier should reside in the business tier.
What if I want to offer a command-line interface to my application for, say,
unit testing with JUnit (which I can currently do in my app for my DAOs but
not for my business tier).  If I use the servlet context as a registry then
it is harder to write these tests.

> > Yeah, you're right.  I read WHITEBOARD.html and got very excited about
> > Agility, and really I think this type of registry idea might find a nice
> > home in Agility.  Who is working on this?  Is anything out there yet?
I'd
> > be very interested in contributing if so.
>
> Yes, something like Agility is a place were you might define concrete
> strategies for storing catalogs within an application. Right now, I'm
> still getting a feel for where Commons Chain is going to end. Frameworks
> like this are best built from working examples, so we'd need to
> implement Chain in a few applications before we could abstract common
> functionality into a framework like Agility. Otherwise, the tail starts
> wagging the dog =:)

Hehe, I am often guilty of this in my own work.  How do we get Chain out of
the sandbox so we can start working on Agility? :)  Should I move over to
Struts and work on the decomposable request processor that Craig started out
instead?  I know one area Chain needs work is documentation, and I will be
working on this in the coming weeks.

> -Ted.

Matt


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
----- Original Message ----- 
From: "Ted Husted" <hu...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Friday, September 26, 2003 8:10 AM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Sgarlata Matt wrote:
> > I understand this difficulty which is why I was thinking that if we make
it
> > an explicit part of the API that you are supposed to store things in
> > such-and-such place that we could be in good shape.  In the example I
gave,
> > I was trying to say that even if different apps used the same singleton,
> > they would all be isolated from each other by virtue of the fact that
the
> > API tells them that they need to store everything under their own unique
> > attribute name, like com.mycompany.myprogram or org.apache.struts.  This
is
> > like how Java can't guarantee two classes have the same name, but
hopefully
> > if people follow the guidelines they are supposed to in terms of naming
> > their packages then name collisions will be less frequent.
>
> IMHO, the API should leave state to the underlying platform. We can
> provide various examples of where you might store state for this
> platform and that platform. For the most part, if Commands need to refer
> to Commands, then the application can pass the Catalog up through the
> Context. The API defines a place to store things, the Context, another
> seems redundant.
>
> Whether the Context is backed by a Singleton, the Servlet Context, or
> something else, can be left to the application.

Well my goal with this idea was to make applications less dependent on the
environment in which they run.  The servlet environment can of course handle
everything that this Registry can, but it is in the presentation tier.  I
think the Registry for the business tier should reside in the business tier.
What if I want to offer a command-line interface to my application for, say,
unit testing with JUnit (which I can currently do in my app for my DAOs but
not for my business tier).  If I use the servlet context as a registry then
it is harder to write these tests.

> > Yeah, you're right.  I read WHITEBOARD.html and got very excited about
> > Agility, and really I think this type of registry idea might find a nice
> > home in Agility.  Who is working on this?  Is anything out there yet?
I'd
> > be very interested in contributing if so.
>
> Yes, something like Agility is a place were you might define concrete
> strategies for storing catalogs within an application. Right now, I'm
> still getting a feel for where Commons Chain is going to end. Frameworks
> like this are best built from working examples, so we'd need to
> implement Chain in a few applications before we could abstract common
> functionality into a framework like Agility. Otherwise, the tail starts
> wagging the dog =:)

Hehe, I am often guilty of this in my own work.  How do we get Chain out of
the sandbox so we can start working on Agility? :)  Should I move over to
Struts and work on the decomposable request processor that Craig started out
instead?  I know one area Chain needs work is documentation, and I will be
working on this in the coming weeks.

> -Ted.

Matt


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> (I'm less annoying in this email I promise...)

Not to worry. If we didn't want people asking about our new clothes, we 
wouldn't wear our code on our sleeve (so to speak).


> I understand this difficulty which is why I was thinking that if we make it
> an explicit part of the API that you are supposed to store things in
> such-and-such place that we could be in good shape.  In the example I gave,
> I was trying to say that even if different apps used the same singleton,
> they would all be isolated from each other by virtue of the fact that the
> API tells them that they need to store everything under their own unique
> attribute name, like com.mycompany.myprogram or org.apache.struts.  This is
> like how Java can't guarantee two classes have the same name, but hopefully
> if people follow the guidelines they are supposed to in terms of naming
> their packages then name collisions will be less frequent.

IMHO, the API should leave state to the underlying platform. We can 
provide various examples of where you might store state for this 
platform and that platform. For the most part, if Commands need to refer 
to Commands, then the application can pass the Catalog up through the 
Context. The API defines a place to store things, the Context, another 
seems redundant.

Whether the Context is backed by a Singleton, the Servlet Context, or 
something else, can be left to the application.


> Yeah, you're right.  I read WHITEBOARD.html and got very excited about
> Agility, and really I think this type of registry idea might find a nice
> home in Agility.  Who is working on this?  Is anything out there yet?  I'd
> be very interested in contributing if so.

Yes, something like Agility is a place were you might define concrete 
strategies for storing catalogs within an application. Right now, I'm 
still getting a feel for where Commons Chain is going to end. Frameworks 
like this are best built from working examples, so we'd need to 
implement Chain in a few applications before we could abstract common 
functionality into a framework like Agility. Otherwise, the tail starts 
wagging the dog =:)

In the meantime, it isn't hard to hook Chain up to existing frameworks. 
Most do not provide direct support for the business layer, which is 
where Chain plugs in. Regardless of whether something like Agility 
exists, people are going to want to use Chain with existing frameworks, 
like JPublish, Maverick, Struts, Tapestry, Turbine, and WebWork. 
(Though, there might be some overlap with XWork in the case of WebWork, 
... but choice is good.)


>>Class libraries should be narrowly focused on as few fundamental ideas
>>as possible, and then do them there.  They should not impose onerous
>>restrictions on applications that want to use them (which is why the
>>config package that uses Digester is optional -- you can compose chains
>>any way you like).  The fundamental APIs we've defined so far (Command,
>>Chain, Context, and Filter) are the minimum needed to implement the
>>desired design patterns.  Catalog is on the edge, but useful for
>>combining chains/commands in a controlled manner.  Registry is more
>>about how catalogs would be accessed, rather than what they do.  Indeed,
>>you don't even need such a thing in many environments; for example, a
>>web app's ServletContext attributes do exactly what your registry does
>>for that particular use case.
> 
> 
> Yeah, this is a good approach that I don't have a lot of experience with.
> I'm using BeanUtils and Digester freely without worrying about having
> certain portions of my API tied to Struts, so thank you! :)

Yes, this is the key. Chain is not about Struts, or about Servlets, it's 
about a coherent approach to managing the business end of an application.

-Ted.



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> (I'm less annoying in this email I promise...)

Not to worry. If we didn't want people asking about our new clothes, we 
wouldn't wear our code on our sleeve (so to speak).


> I understand this difficulty which is why I was thinking that if we make it
> an explicit part of the API that you are supposed to store things in
> such-and-such place that we could be in good shape.  In the example I gave,
> I was trying to say that even if different apps used the same singleton,
> they would all be isolated from each other by virtue of the fact that the
> API tells them that they need to store everything under their own unique
> attribute name, like com.mycompany.myprogram or org.apache.struts.  This is
> like how Java can't guarantee two classes have the same name, but hopefully
> if people follow the guidelines they are supposed to in terms of naming
> their packages then name collisions will be less frequent.

IMHO, the API should leave state to the underlying platform. We can 
provide various examples of where you might store state for this 
platform and that platform. For the most part, if Commands need to refer 
to Commands, then the application can pass the Catalog up through the 
Context. The API defines a place to store things, the Context, another 
seems redundant.

Whether the Context is backed by a Singleton, the Servlet Context, or 
something else, can be left to the application.


> Yeah, you're right.  I read WHITEBOARD.html and got very excited about
> Agility, and really I think this type of registry idea might find a nice
> home in Agility.  Who is working on this?  Is anything out there yet?  I'd
> be very interested in contributing if so.

Yes, something like Agility is a place were you might define concrete 
strategies for storing catalogs within an application. Right now, I'm 
still getting a feel for where Commons Chain is going to end. Frameworks 
like this are best built from working examples, so we'd need to 
implement Chain in a few applications before we could abstract common 
functionality into a framework like Agility. Otherwise, the tail starts 
wagging the dog =:)

In the meantime, it isn't hard to hook Chain up to existing frameworks. 
Most do not provide direct support for the business layer, which is 
where Chain plugs in. Regardless of whether something like Agility 
exists, people are going to want to use Chain with existing frameworks, 
like JPublish, Maverick, Struts, Tapestry, Turbine, and WebWork. 
(Though, there might be some overlap with XWork in the case of WebWork, 
... but choice is good.)


>>Class libraries should be narrowly focused on as few fundamental ideas
>>as possible, and then do them there.  They should not impose onerous
>>restrictions on applications that want to use them (which is why the
>>config package that uses Digester is optional -- you can compose chains
>>any way you like).  The fundamental APIs we've defined so far (Command,
>>Chain, Context, and Filter) are the minimum needed to implement the
>>desired design patterns.  Catalog is on the edge, but useful for
>>combining chains/commands in a controlled manner.  Registry is more
>>about how catalogs would be accessed, rather than what they do.  Indeed,
>>you don't even need such a thing in many environments; for example, a
>>web app's ServletContext attributes do exactly what your registry does
>>for that particular use case.
> 
> 
> Yeah, this is a good approach that I don't have a lot of experience with.
> I'm using BeanUtils and Digester freely without worrying about having
> certain portions of my API tied to Struts, so thank you! :)

Yes, this is the key. Chain is not about Struts, or about Servlets, it's 
about a coherent approach to managing the business end of an application.

-Ted.



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
(I'm less annoying in this email I promise...)
----- Original Message ----- 
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Wednesday, September 24, 2003 12:59 PM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Sgarlata Matt wrote:
>
> >The conversation threads are getting kind of crazy, so I'm going to skip
> >inline quotes for parts of this.
> >
> >Craig, now I do see your point about using the ConfigRuleSet to digest a
> >portion of
> >an arbitrary XML file.  That is very cool, and now I understand why the
> >names of the XML elements are configurable.  I always understood the
value
> >of letting attributes to the <command> element (and other elements).
This
> >is a much slicker approach than creating nested <set-property> elements.
> >Still, I think it could be useful to have a DTD for the *default*
behavior
> >of the ConfigRuleSet.  I think in general users will start off using the
> >default behavior, and then may at a later date decide to fold their
commands
> >into some other file, so a DTD will be nice to get people started with
the
> >Chain package.  I agree with most your points about the constraints I
placed
> >in the DTD being inappropriate, and will explicitly address each if we
ever
> >decide to make a DTD.
> >
>
> Unfortunately, none of the Command implementations I am interested in
> building into my Chains would be usable in a document parsed against
> such a DTD, for the technical reasons we discussed earlier.  Therefore,
> I'm not interested in any sort of DTD that someone would actually try to
> use in a validating parser.  If what you want is a more high level view
> of the typical structure of such a file (i.e. documentation), that's a
> different matter, and should be addressed with diagrams, examples, and
> how-to guides; minimally, to the level of detail you see in the "Package
> Description" docs for things like Digester and BeanUtils.

OK, maybe this weekend I'll submit a new package.html for review.  I give up
on the DTD ;)

> >How about making a Register class which is an implementation of Context
> >which stores only references to Catalogs?  We could make the registry
itself
> >a singleton, and write in design notes that since the registry is shared
> >between apps, each app should store its Catalog(s) in an
> >application-specific attribute like below:
> >
> >Registry
> >|
> >|---org.apache.struts
> >|---|---actions.RequestProcessor
> >|---|---somethingElse
> >|---com.bah.krm
> >|---org.apache.commons.something
> >
> >That's not explained incredibly well, but if each application component
> >reserves its own spot in the registry, we should be able to make the
> >registry a singleton everyone can share.  This keeps us from tying
ourselves
> >to the Servlet API, as was mentioned in the ChainServlet discussion
thread.
> >
> >
>
> It should be obvious that creating such a class is trivially simple, but
> you should first study how class loaders work in servlet containers, and
> then think about what happens if commons-chain were placed in a parent
> class loader (meaning that any singletons you try to create with static
> variables are shared across *all* webapps, not just the current one).
> The docs for Tomcat's class loader are specific to Tomcat, but typical
> of the architecture that most web containers offer:
>
>   http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

I understand this difficulty which is why I was thinking that if we make it
an explicit part of the API that you are supposed to store things in
such-and-such place that we could be in good shape.  In the example I gave,
I was trying to say that even if different apps used the same singleton,
they would all be isolated from each other by virtue of the fact that the
API tells them that they need to store everything under their own unique
attribute name, like com.mycompany.myprogram or org.apache.struts.  This is
like how Java can't guarantee two classes have the same name, but hopefully
if people follow the guidelines they are supposed to in terms of naming
their packages then name collisions will be less frequent.

> The other reason I didn't go here is that we're actually at the edge of
> the patterns that commons-chain was created to implement.  How it gets
> embedded into a particular application should be up to that application.
>
> Indeed, the only reason that Catalog exists is to allow chains to refer
> to other chains in an organized way.  One could argue that even this is
> out of scope; however, it's very useful to be able to write a Command
> that uses complex processing logic to decide which other commands (or
> chains, since you can't tell in the catalog what something is) should be
> used to actually perform a task.

Yeah, you're right.  I read WHITEBOARD.html and got very excited about
Agility, and really I think this type of registry idea might find a nice
home in Agility.  Who is working on this?  Is anything out there yet?  I'd
be very interested in contributing if so.

> Class libraries should be narrowly focused on as few fundamental ideas
> as possible, and then do them there.  They should not impose onerous
> restrictions on applications that want to use them (which is why the
> config package that uses Digester is optional -- you can compose chains
> any way you like).  The fundamental APIs we've defined so far (Command,
> Chain, Context, and Filter) are the minimum needed to implement the
> desired design patterns.  Catalog is on the edge, but useful for
> combining chains/commands in a controlled manner.  Registry is more
> about how catalogs would be accessed, rather than what they do.  Indeed,
> you don't even need such a thing in many environments; for example, a
> web app's ServletContext attributes do exactly what your registry does
> for that particular use case.

Yeah, this is a good approach that I don't have a lot of experience with.
I'm using BeanUtils and Digester freely without worrying about having
certain portions of my API tied to Struts, so thank you! :)

> >
> Craig
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Sgarlata Matt <sg...@bah.com>.
(I'm less annoying in this email I promise...)
----- Original Message ----- 
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Wednesday, September 24, 2003 12:59 PM
Subject: Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain]
examples XML file available?)


> Sgarlata Matt wrote:
>
> >The conversation threads are getting kind of crazy, so I'm going to skip
> >inline quotes for parts of this.
> >
> >Craig, now I do see your point about using the ConfigRuleSet to digest a
> >portion of
> >an arbitrary XML file.  That is very cool, and now I understand why the
> >names of the XML elements are configurable.  I always understood the
value
> >of letting attributes to the <command> element (and other elements).
This
> >is a much slicker approach than creating nested <set-property> elements.
> >Still, I think it could be useful to have a DTD for the *default*
behavior
> >of the ConfigRuleSet.  I think in general users will start off using the
> >default behavior, and then may at a later date decide to fold their
commands
> >into some other file, so a DTD will be nice to get people started with
the
> >Chain package.  I agree with most your points about the constraints I
placed
> >in the DTD being inappropriate, and will explicitly address each if we
ever
> >decide to make a DTD.
> >
>
> Unfortunately, none of the Command implementations I am interested in
> building into my Chains would be usable in a document parsed against
> such a DTD, for the technical reasons we discussed earlier.  Therefore,
> I'm not interested in any sort of DTD that someone would actually try to
> use in a validating parser.  If what you want is a more high level view
> of the typical structure of such a file (i.e. documentation), that's a
> different matter, and should be addressed with diagrams, examples, and
> how-to guides; minimally, to the level of detail you see in the "Package
> Description" docs for things like Digester and BeanUtils.

OK, maybe this weekend I'll submit a new package.html for review.  I give up
on the DTD ;)

> >How about making a Register class which is an implementation of Context
> >which stores only references to Catalogs?  We could make the registry
itself
> >a singleton, and write in design notes that since the registry is shared
> >between apps, each app should store its Catalog(s) in an
> >application-specific attribute like below:
> >
> >Registry
> >|
> >|---org.apache.struts
> >|---|---actions.RequestProcessor
> >|---|---somethingElse
> >|---com.bah.krm
> >|---org.apache.commons.something
> >
> >That's not explained incredibly well, but if each application component
> >reserves its own spot in the registry, we should be able to make the
> >registry a singleton everyone can share.  This keeps us from tying
ourselves
> >to the Servlet API, as was mentioned in the ChainServlet discussion
thread.
> >
> >
>
> It should be obvious that creating such a class is trivially simple, but
> you should first study how class loaders work in servlet containers, and
> then think about what happens if commons-chain were placed in a parent
> class loader (meaning that any singletons you try to create with static
> variables are shared across *all* webapps, not just the current one).
> The docs for Tomcat's class loader are specific to Tomcat, but typical
> of the architecture that most web containers offer:
>
>   http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

I understand this difficulty which is why I was thinking that if we make it
an explicit part of the API that you are supposed to store things in
such-and-such place that we could be in good shape.  In the example I gave,
I was trying to say that even if different apps used the same singleton,
they would all be isolated from each other by virtue of the fact that the
API tells them that they need to store everything under their own unique
attribute name, like com.mycompany.myprogram or org.apache.struts.  This is
like how Java can't guarantee two classes have the same name, but hopefully
if people follow the guidelines they are supposed to in terms of naming
their packages then name collisions will be less frequent.

> The other reason I didn't go here is that we're actually at the edge of
> the patterns that commons-chain was created to implement.  How it gets
> embedded into a particular application should be up to that application.
>
> Indeed, the only reason that Catalog exists is to allow chains to refer
> to other chains in an organized way.  One could argue that even this is
> out of scope; however, it's very useful to be able to write a Command
> that uses complex processing logic to decide which other commands (or
> chains, since you can't tell in the catalog what something is) should be
> used to actually perform a task.

Yeah, you're right.  I read WHITEBOARD.html and got very excited about
Agility, and really I think this type of registry idea might find a nice
home in Agility.  Who is working on this?  Is anything out there yet?  I'd
be very interested in contributing if so.

> Class libraries should be narrowly focused on as few fundamental ideas
> as possible, and then do them there.  They should not impose onerous
> restrictions on applications that want to use them (which is why the
> config package that uses Digester is optional -- you can compose chains
> any way you like).  The fundamental APIs we've defined so far (Command,
> Chain, Context, and Filter) are the minimum needed to implement the
> desired design patterns.  Catalog is on the edge, but useful for
> combining chains/commands in a controlled manner.  Registry is more
> about how catalogs would be accessed, rather than what they do.  Indeed,
> you don't even need such a thing in many environments; for example, a
> web app's ServletContext attributes do exactly what your registry does
> for that particular use case.

Yeah, this is a good approach that I don't have a lot of experience with.
I'm using BeanUtils and Digester freely without worrying about having
certain portions of my API tied to Struts, so thank you! :)

> >
> Craig
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Sgarlata Matt wrote:

>The conversation threads are getting kind of crazy, so I'm going to skip
>inline quotes for parts of this.
>
>Craig, now I do see your point about using the ConfigRuleSet to digest a
>portion of
>an arbitrary XML file.  That is very cool, and now I understand why the
>names of the XML elements are configurable.  I always understood the value
>of letting attributes to the <command> element (and other elements).  This
>is a much slicker approach than creating nested <set-property> elements.
>Still, I think it could be useful to have a DTD for the *default* behavior
>of the ConfigRuleSet.  I think in general users will start off using the
>default behavior, and then may at a later date decide to fold their commands
>into some other file, so a DTD will be nice to get people started with the
>Chain package.  I agree with most your points about the constraints I placed
>in the DTD being inappropriate, and will explicitly address each if we ever
>decide to make a DTD.
>

Unfortunately, none of the Command implementations I am interested in 
building into my Chains would be usable in a document parsed against 
such a DTD, for the technical reasons we discussed earlier.  Therefore, 
I'm not interested in any sort of DTD that someone would actually try to 
use in a validating parser.  If what you want is a more high level view 
of the typical structure of such a file (i.e. documentation), that's a 
different matter, and should be addressed with diagrams, examples, and 
how-to guides; minimally, to the level of detail you see in the "Package 
Description" docs for things like Digester and BeanUtils.

>As I've thought more about the package, I don't understand why some design
>decisions were made.
>

Ted points out the GoF patterns this package was created to realize.  I 
discuss below some of my motivations, upon observing limitations in the 
extensibility of Struts based on the design decisions we made.

>  First let me say that I think of Chains as being an OO
>way to simulate procedural logic.
>

It is actually intended to *compose* procedural logic, not to *simulate* it.

In an O-O world, you often compose complex things out of simple things 
by encapsulating the result in a "black box" method that can be called 
by your user.  Ideally, the user doesn't have to know much about what 
happens inside the box -- they just use it.  But, sometimes, the default 
behavior is not enough and you need to specialize.  A typical approach 
to specializing in O-O languages is to subclass, and then override the 
appropriate methods.

Now, it's real easy to add some logic at the beginning, then call 
super.foo(), and perhaps add some logic at the end.  But what happens if 
you need to add a bunch of stuff in the middle?  Or replace one of the 
method calls performed inside the black box with one that does something 
slightly different.  You're often stuck with having to cut-n-paste the 
logic of the method you're specializing, then change the calls you want, 
and hope you notice whenever the class you copied has changed so that 
you can replicate those changes in your version.  Yuck.

One approach to making this work better was tried in Struts 1.1, where 
the RequestProcessor has a single public process() method to process 
each request.  In turn, the process() method called a bunch of protected 
processFoo() and processBar() methods that performed a single step.  
People who wanted to specialize only that step needed to subclass 
RequestProcessor and then just override that single step.  Because the 
steps were fairly fine-grained, this was a big improvement, and lots of 
innovative things were done to extend Struts.  However, there's two big 
areas of difficulty left:

* What happens when someone wants to insert new processing phases,
  remove old ones, or reorder the existing ones?  They have to override
  the relatively complex process() method, and hope they get all the
  details exactly right in their cut-n-paste.

* What happens when you, as an application author, want to take advantage
  of customized extensions provided by more than one library, where both
  of them have extended RequestProcessor?  Java does not support multiple
  inheritance, so you're stuck manually weaving the RequestProcessor changes
  together.  Again, yuck.

Far better would be to divide the procedural flow into small steps that 
are externally configurable.  And, let each step have its own 
arbitrarily complex internal structure (by virtue of the fact that it 
can be a Command or a Chain of its own).  Oh, by the way, the procedural 
steps become small enough and narrowly focused enough to write high 
quality unit tests for.  And, because commands interact with each other 
*solely* through a Context, you can easily create mock objects (like a 
ServletContext or an HttpSession, in a chain destined for a web 
applicaton) that let you thoroughly test things in a standalone 
environment (in case it's not obvious, I'm a *huge* fan of JUnit :-).

In an environment like this, people who extend the basic Struts request 
processing pipeline will do so by providing implementations of the 
fine-grained commands and chains that make up their extension, and an 
example of how to update the standard processing chain to include their 
functionality.  For the 80% case, we should even be able to do this 
without actually modifying the standard chain (by having the standard 
chain include a step between each actual processing step that says "if 
there is a command registered under name XYZ, process it here"; so the 
act of registering your customized chain under a particular name 
automatically customizes the standard chain).

For a beginning glimmer of this, see how the struts-chain example code 
(in the Struts sources referenced earlier) uses the generic 
LookupCommand to conditionally execute a chain named 
"servlet-complete-preprocess" if and only if it has been registered.  
Because the "optional" flag is set to true, it doesn't complain if there 
is no such chain -- it just proceeds on.

>  Many of my comments will basically be
>concerning why some of the standard control flow abilities (if/then
>statements, loops, exception handling, etc) in Java aren't more easily
>done/simulated using the Chain package.
>

For an example of "been there, done that" on trying to script control 
flows in XML, see the commons-workflow package that is also in the 
Sandbox.  For a far more complex and successful approach at scripting in 
XML, see commons-jelly (in the main jakarta-commons repository).

Fundamentally, if you feel a big need for if/then and loops, I would 
suggest you haven't decomposed your procedural logic into small enough 
pieces yet.  That sort of control flow does not itself need to be 
expressed in chains -- it can be done in the language in which you embed 
commons-chain (typically Java).

Exception handling is a slightly different story -- it was one of the 
motivations for the Filter API (see below).

>  So, here I go with questions:
>1) How come Chains have a static structure?
>

Chains are static so that you can reuse them in an application without 
any fear that they are mutating underneath you.  In addition, the static 
structure allows optimized processing in a multithread environment like 
a web application.  Nothing stops you, of course, from (inside a 
Command) building up your own custom Chain, then executing it, then 
throwing it away.

>  Related to this, how come
>Command.execute returns boolean instead of returning Command?
>

Commands should not know whether or not they have been composed into a 
chain.  Returning a Command would require that type of knowledge.  
Instead, a Command only says whether or not the computation has been 
finished.

Other approaches to this kind of thing have also been tried -- see, for 
example, how javax.servlet.Filter works in Servlet 2.3.  This adds the 
complexity of a FilterContext that has to be passed along (where the 
knowledge of the chain's constituent Commands is maintained), plus it 
creates a horrendously deep call stack.

I opted for the simplest possible APIs to make commons-chain very easy 
to understand and use.

>  If it
>returned Command this would basically eliminate the need for a Chain
>interface altogether.
>

Your approach only works for the top-level chain -- the current APIs 
allow chains to use arbitrarily complex subchains.  Essentially, you'd 
force anyone who wants subchains to re-invent what Chain already does.

>  Chain would become a concrete implementation of
>Command that repeatedly executed Commands until the last command executed
>returned null (which would be the new value to indicate the end of a chain).
>Static chains (such as those configured using an XML file) would easily be
>supported by another concrete implementation of Command which executed a
>series of commands in order, completely ignoring their return values.
>

You can already do exactly this kind of thing with the current API, 
without imposing on yourself the restrictions described above.  Your 
proposed changes would remove functionality and add complexity.

>2) How come Filters have a postprocess method but no catchexception method?
>

The postprocess method does both things, so you don't need a separate 
method.

>The postprocess block can deal with exceptions, but it seems to me like it
>would be more natural for exceptions to be dealt with in a catchexception
>block and for postprocess to be strictly for freeing resources that the
>Command acquired when its execute method was called.
>

My experience has been that the catch exception processing normally has 
to free the resources anyway, so it would end up either calling the 
postprocess method or duplicating the logic.  Either of those is tedious 
and error prone.  Far better just to have a single cleanup method no 
matter what happened.

>
>Ted Husted wrote:
>  
>
>>Of course, another way to go would be to make the Catalog a singleton,
>>or available through some registry, but I'm thinking that going through
>>the Context may be the cleanest approach, since the Context is
>>essentially a Registry too.
>>    
>>
>
>How about making a Register class which is an implementation of Context
>which stores only references to Catalogs?  We could make the registry itself
>a singleton, and write in design notes that since the registry is shared
>between apps, each app should store its Catalog(s) in an
>application-specific attribute like below:
>
>Registry
>|
>|---org.apache.struts
>|---|---actions.RequestProcessor
>|---|---somethingElse
>|---com.bah.krm
>|---org.apache.commons.something
>
>That's not explained incredibly well, but if each application component
>reserves its own spot in the registry, we should be able to make the
>registry a singleton everyone can share.  This keeps us from tying ourselves
>to the Servlet API, as was mentioned in the ChainServlet discussion thread.
>  
>

It should be obvious that creating such a class is trivially simple, but 
you should first study how class loaders work in servlet containers, and 
then think about what happens if commons-chain were placed in a parent 
class loader (meaning that any singletons you try to create with static 
variables are shared across *all* webapps, not just the current one).  
The docs for Tomcat's class loader are specific to Tomcat, but typical 
of the architecture that most web containers offer:

  http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

The other reason I didn't go here is that we're actually at the edge of 
the patterns that commons-chain was created to implement.  How it gets 
embedded into a particular application should be up to that application.

Indeed, the only reason that Catalog exists is to allow chains to refer 
to other chains in an organized way.  One could argue that even this is 
out of scope; however, it's very useful to be able to write a Command 
that uses complex processing logic to decide which other commands (or 
chains, since you can't tell in the catalog what something is) should be 
used to actually perform a task.

Class libraries should be narrowly focused on as few fundamental ideas 
as possible, and then do them there.  They should not impose onerous 
restrictions on applications that want to use them (which is why the 
config package that uses Digester is optional -- you can compose chains 
any way you like).  The fundamental APIs we've defined so far (Command, 
Chain, Context, and Filter) are the minimum needed to implement the 
desired design patterns.  Catalog is on the edge, but useful for 
combining chains/commands in a controlled manner.  Registry is more 
about how catalogs would be accessed, rather than what they do.  Indeed, 
you don't even need such a thing in many environments; for example, a 
web app's ServletContext attributes do exactly what your registry does 
for that particular use case.

>Matt
>
Craig



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> How about making a Register class which is an implementation of Context
> which stores only references to Catalogs?  We could make the registry itself
> a singleton, and write in design notes that since the registry is shared
> between apps, each app should store its Catalog(s) in an
> application-specific attribute like below:
> 
> Registry
> |
> |---org.apache.struts
> |---|---actions.RequestProcessor
> |---|---somethingElse
> |---com.bah.krm
> |---org.apache.commons.something
> 
> That's not explained incredibly well, but if each application component
> reserves its own spot in the registry, we should be able to make the
> registry a singleton everyone can share.  This keeps us from tying ourselves
> to the Servlet API, as was mentioned in the ChainServlet discussion thread.

I was thinking that when I have a case of a Command needing to access 
another Command/Chain, I'd try adding a Catalog attribute to the 
Context. But, it might be too early to define another Registry class 
(since the Context is also a Registry), especially without a use-case to 
test it against. The big step now, I think, is migrating some 
applications to Chain so we can see what's needed in practice. I've got 
both a web and non-web on the hook for this now.

-Ted.



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by "Craig R. McClanahan" <cr...@apache.org>.
Sgarlata Matt wrote:

>The conversation threads are getting kind of crazy, so I'm going to skip
>inline quotes for parts of this.
>
>Craig, now I do see your point about using the ConfigRuleSet to digest a
>portion of
>an arbitrary XML file.  That is very cool, and now I understand why the
>names of the XML elements are configurable.  I always understood the value
>of letting attributes to the <command> element (and other elements).  This
>is a much slicker approach than creating nested <set-property> elements.
>Still, I think it could be useful to have a DTD for the *default* behavior
>of the ConfigRuleSet.  I think in general users will start off using the
>default behavior, and then may at a later date decide to fold their commands
>into some other file, so a DTD will be nice to get people started with the
>Chain package.  I agree with most your points about the constraints I placed
>in the DTD being inappropriate, and will explicitly address each if we ever
>decide to make a DTD.
>

Unfortunately, none of the Command implementations I am interested in 
building into my Chains would be usable in a document parsed against 
such a DTD, for the technical reasons we discussed earlier.  Therefore, 
I'm not interested in any sort of DTD that someone would actually try to 
use in a validating parser.  If what you want is a more high level view 
of the typical structure of such a file (i.e. documentation), that's a 
different matter, and should be addressed with diagrams, examples, and 
how-to guides; minimally, to the level of detail you see in the "Package 
Description" docs for things like Digester and BeanUtils.

>As I've thought more about the package, I don't understand why some design
>decisions were made.
>

Ted points out the GoF patterns this package was created to realize.  I 
discuss below some of my motivations, upon observing limitations in the 
extensibility of Struts based on the design decisions we made.

>  First let me say that I think of Chains as being an OO
>way to simulate procedural logic.
>

It is actually intended to *compose* procedural logic, not to *simulate* it.

In an O-O world, you often compose complex things out of simple things 
by encapsulating the result in a "black box" method that can be called 
by your user.  Ideally, the user doesn't have to know much about what 
happens inside the box -- they just use it.  But, sometimes, the default 
behavior is not enough and you need to specialize.  A typical approach 
to specializing in O-O languages is to subclass, and then override the 
appropriate methods.

Now, it's real easy to add some logic at the beginning, then call 
super.foo(), and perhaps add some logic at the end.  But what happens if 
you need to add a bunch of stuff in the middle?  Or replace one of the 
method calls performed inside the black box with one that does something 
slightly different.  You're often stuck with having to cut-n-paste the 
logic of the method you're specializing, then change the calls you want, 
and hope you notice whenever the class you copied has changed so that 
you can replicate those changes in your version.  Yuck.

One approach to making this work better was tried in Struts 1.1, where 
the RequestProcessor has a single public process() method to process 
each request.  In turn, the process() method called a bunch of protected 
processFoo() and processBar() methods that performed a single step.  
People who wanted to specialize only that step needed to subclass 
RequestProcessor and then just override that single step.  Because the 
steps were fairly fine-grained, this was a big improvement, and lots of 
innovative things were done to extend Struts.  However, there's two big 
areas of difficulty left:

* What happens when someone wants to insert new processing phases,
  remove old ones, or reorder the existing ones?  They have to override
  the relatively complex process() method, and hope they get all the
  details exactly right in their cut-n-paste.

* What happens when you, as an application author, want to take advantage
  of customized extensions provided by more than one library, where both
  of them have extended RequestProcessor?  Java does not support multiple
  inheritance, so you're stuck manually weaving the RequestProcessor changes
  together.  Again, yuck.

Far better would be to divide the procedural flow into small steps that 
are externally configurable.  And, let each step have its own 
arbitrarily complex internal structure (by virtue of the fact that it 
can be a Command or a Chain of its own).  Oh, by the way, the procedural 
steps become small enough and narrowly focused enough to write high 
quality unit tests for.  And, because commands interact with each other 
*solely* through a Context, you can easily create mock objects (like a 
ServletContext or an HttpSession, in a chain destined for a web 
applicaton) that let you thoroughly test things in a standalone 
environment (in case it's not obvious, I'm a *huge* fan of JUnit :-).

In an environment like this, people who extend the basic Struts request 
processing pipeline will do so by providing implementations of the 
fine-grained commands and chains that make up their extension, and an 
example of how to update the standard processing chain to include their 
functionality.  For the 80% case, we should even be able to do this 
without actually modifying the standard chain (by having the standard 
chain include a step between each actual processing step that says "if 
there is a command registered under name XYZ, process it here"; so the 
act of registering your customized chain under a particular name 
automatically customizes the standard chain).

For a beginning glimmer of this, see how the struts-chain example code 
(in the Struts sources referenced earlier) uses the generic 
LookupCommand to conditionally execute a chain named 
"servlet-complete-preprocess" if and only if it has been registered.  
Because the "optional" flag is set to true, it doesn't complain if there 
is no such chain -- it just proceeds on.

>  Many of my comments will basically be
>concerning why some of the standard control flow abilities (if/then
>statements, loops, exception handling, etc) in Java aren't more easily
>done/simulated using the Chain package.
>

For an example of "been there, done that" on trying to script control 
flows in XML, see the commons-workflow package that is also in the 
Sandbox.  For a far more complex and successful approach at scripting in 
XML, see commons-jelly (in the main jakarta-commons repository).

Fundamentally, if you feel a big need for if/then and loops, I would 
suggest you haven't decomposed your procedural logic into small enough 
pieces yet.  That sort of control flow does not itself need to be 
expressed in chains -- it can be done in the language in which you embed 
commons-chain (typically Java).

Exception handling is a slightly different story -- it was one of the 
motivations for the Filter API (see below).

>  So, here I go with questions:
>1) How come Chains have a static structure?
>

Chains are static so that you can reuse them in an application without 
any fear that they are mutating underneath you.  In addition, the static 
structure allows optimized processing in a multithread environment like 
a web application.  Nothing stops you, of course, from (inside a 
Command) building up your own custom Chain, then executing it, then 
throwing it away.

>  Related to this, how come
>Command.execute returns boolean instead of returning Command?
>

Commands should not know whether or not they have been composed into a 
chain.  Returning a Command would require that type of knowledge.  
Instead, a Command only says whether or not the computation has been 
finished.

Other approaches to this kind of thing have also been tried -- see, for 
example, how javax.servlet.Filter works in Servlet 2.3.  This adds the 
complexity of a FilterContext that has to be passed along (where the 
knowledge of the chain's constituent Commands is maintained), plus it 
creates a horrendously deep call stack.

I opted for the simplest possible APIs to make commons-chain very easy 
to understand and use.

>  If it
>returned Command this would basically eliminate the need for a Chain
>interface altogether.
>

Your approach only works for the top-level chain -- the current APIs 
allow chains to use arbitrarily complex subchains.  Essentially, you'd 
force anyone who wants subchains to re-invent what Chain already does.

>  Chain would become a concrete implementation of
>Command that repeatedly executed Commands until the last command executed
>returned null (which would be the new value to indicate the end of a chain).
>Static chains (such as those configured using an XML file) would easily be
>supported by another concrete implementation of Command which executed a
>series of commands in order, completely ignoring their return values.
>

You can already do exactly this kind of thing with the current API, 
without imposing on yourself the restrictions described above.  Your 
proposed changes would remove functionality and add complexity.

>2) How come Filters have a postprocess method but no catchexception method?
>

The postprocess method does both things, so you don't need a separate 
method.

>The postprocess block can deal with exceptions, but it seems to me like it
>would be more natural for exceptions to be dealt with in a catchexception
>block and for postprocess to be strictly for freeing resources that the
>Command acquired when its execute method was called.
>

My experience has been that the catch exception processing normally has 
to free the resources anyway, so it would end up either calling the 
postprocess method or duplicating the logic.  Either of those is tedious 
and error prone.  Far better just to have a single cleanup method no 
matter what happened.

>
>Ted Husted wrote:
>  
>
>>Of course, another way to go would be to make the Catalog a singleton,
>>or available through some registry, but I'm thinking that going through
>>the Context may be the cleanest approach, since the Context is
>>essentially a Registry too.
>>    
>>
>
>How about making a Register class which is an implementation of Context
>which stores only references to Catalogs?  We could make the registry itself
>a singleton, and write in design notes that since the registry is shared
>between apps, each app should store its Catalog(s) in an
>application-specific attribute like below:
>
>Registry
>|
>|---org.apache.struts
>|---|---actions.RequestProcessor
>|---|---somethingElse
>|---com.bah.krm
>|---org.apache.commons.something
>
>That's not explained incredibly well, but if each application component
>reserves its own spot in the registry, we should be able to make the
>registry a singleton everyone can share.  This keeps us from tying ourselves
>to the Servlet API, as was mentioned in the ChainServlet discussion thread.
>  
>

It should be obvious that creating such a class is trivially simple, but 
you should first study how class loaders work in servlet containers, and 
then think about what happens if commons-chain were placed in a parent 
class loader (meaning that any singletons you try to create with static 
variables are shared across *all* webapps, not just the current one).  
The docs for Tomcat's class loader are specific to Tomcat, but typical 
of the architecture that most web containers offer:

  http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

The other reason I didn't go here is that we're actually at the edge of 
the patterns that commons-chain was created to implement.  How it gets 
embedded into a particular application should be up to that application.

Indeed, the only reason that Catalog exists is to allow chains to refer 
to other chains in an organized way.  One could argue that even this is 
out of scope; however, it's very useful to be able to write a Command 
that uses complex processing logic to decide which other commands (or 
chains, since you can't tell in the catalog what something is) should be 
used to actually perform a task.

Class libraries should be narrowly focused on as few fundamental ideas 
as possible, and then do them there.  They should not impose onerous 
restrictions on applications that want to use them (which is why the 
config package that uses Digester is optional -- you can compose chains 
any way you like).  The fundamental APIs we've defined so far (Command, 
Chain, Context, and Filter) are the minimum needed to implement the 
desired design patterns.  Catalog is on the edge, but useful for 
combining chains/commands in a controlled manner.  Registry is more 
about how catalogs would be accessed, rather than what they do.  Indeed, 
you don't even need such a thing in many environments; for example, a 
web app's ServletContext attributes do exactly what your registry does 
for that particular use case.

>Matt
>
Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Greg Reddin <gr...@fnf.com>.
Sgarlata Matt wrote:
> Related to this, how come
> Command.execute returns boolean instead of returning Command?  If it
> returned Command this would basically eliminate the need for a Chain
> interface altogether.  Chain would become a concrete implementation of
> Command that repeatedly executed Commands until the last command executed
> returned null (which would be the new value to indicate the end of a chain).

If Command returned a Command reference, each Command would have to know 
what the next Command in the chain is, which, IMO, would introduce too 
tight coupling between Commands.  Why use configurable chains if you're 
going to programatically hardwire the next step in the process.  The 
Chain interface exists to signify separately from the Commands 
themselves the set of commands that are to be run in a process.  The 
Command returns boolean so that you can "break" execution at any point 
in the chain.  Look at the current RequestProcessor interface in Struts. 
  Some of the processing methods return boolean to indicate that 
processing should not continue to the next "link."

If the interface was changed from what it is now, I'd prefer an approach 
that looks more like Servlet Filters where you call doNextCommand() 
without regard to what the next command is over an approach where you 
determine what the next command is, but I'm cool with the interface the 
way it exists now as well.

Greg



Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)

Posted by Ted Husted <hu...@apache.org>.
Sgarlata Matt wrote:
> How about making a Register class which is an implementation of Context
> which stores only references to Catalogs?  We could make the registry itself
> a singleton, and write in design notes that since the registry is shared
> between apps, each app should store its Catalog(s) in an
> application-specific attribute like below:
> 
> Registry
> |
> |---org.apache.struts
> |---|---actions.RequestProcessor
> |---|---somethingElse
> |---com.bah.krm
> |---org.apache.commons.something
> 
> That's not explained incredibly well, but if each application component
> reserves its own spot in the registry, we should be able to make the
> registry a singleton everyone can share.  This keeps us from tying ourselves
> to the Servlet API, as was mentioned in the ChainServlet discussion thread.

I was thinking that when I have a case of a Command needing to access 
another Command/Chain, I'd try adding a Catalog attribute to the 
Context. But, it might be too early to define another Registry class 
(since the Context is also a Registry), especially without a use-case to 
test it against. The big step now, I think, is migrating some 
applications to Chain so we can see what's needed in practice. I've got 
both a web and non-web on the hook for this now.

-Ted.