We're using WebWork 2.2 heavily on a handful of projects (OK, a big
handful of big projects), so I definitely understand the concerns.

I didn't mean to shock anyone. I thought my point of view was clear
based on the introduction to the "Rough Spots" page
(http://wiki.apache.org/struts/RoughSpots) and the "Action Next++"
thread (http://forums.opensymphony.com/thread.jspa?threadID=27183).

I'm worried about migrating our WebWork projects, too, but I'm willing
to stick with WebWork 2.2 for a little longer and endure a less
convenient migration in order to support what's best in the long run.
(I also don't think a migration will be as painful as some think.)

In the long run, do we want Struts Action 2.0 to be a standard on the
same footing as JSF or just another non-JSF framework? I want the
former. I want Struts Action 2.0 to be the default choice of major
corporations so I can continue to use it for years to come.

If you agree, the most important thing is that we get the published
API right in the 2.0 release. The published API includes a Java API
like we have here, the configuration (along with the implicit
interceptor and result names), the tag libraries, etc.

Breaking the API in a 2.0.x release is not an option; we'll be stuck
with whatever we put out in 2.0. As I said in the "Action Next++"
thread, I'd rather not start planning on a 3.0 release. Let's get it
right the first time.

On 5/4/06, Don Brown <[EMAIL PROTECTED]> wrote:
I see this new API as a proposal, meant to feed discussion and not to
be voted on as a whole today.  Therefore, let us have a solid
discussion on the particulars of the API, and avoid throwing out the
abused '-1' votes, as those are meant for official votes and carry an
obstructive, negative connotation.

Exactly. Thanks, Don.

o.a.s.action2 - I'd like to hear the design reasoning behind the
Messages changes.  I liked the use of Maps in the XWork design as it
made it easier to work with.  On the other hand, encapsulating message
operations in the Messages object does reduce the number of
message-handling methods required.  Perhaps Messages could extend Map?
 Also, I agree we should continue to support plain Messages, as not
all apps need to be localized.

- Passing in keys vs. actual messages - I think always passing in keys
is one thing Struts got right. Even if you only support one language,
abstracting messages out of your code is still a good practice.

- Using keys enabled us to do away with the TextProvider interface entirely.

- I didn't like having the same set of methods twice: one for errors
and one for regular messages. The new design is more object oriented,
has shorter method names, enables better reuse of code between errors
and normal messages, and leaves the door open to other levels of
messages (such as warning). I'm not saying we want to explicitly
support arbitrary levels (like JSF does), but we don't want to close
the door to it either.

- This design doesn't force inheritance. Notice we don't have
ActionSupport anymore? If users still want to have the implicit
methods, they can statically import them from a support class. The
support class implementation would look up the thread local Request
and delegate to it. I didn't add this yet because I'm not sure if we
really need it.

- In the old design, messages were scoped to an action which doesn't
work very well when you're chaining and you want to display all the
errors from all the actions. I think we want messages to be scoped to
the request (i.e. spanning multiple actions). We actually use our own
message handling and ignore WebWork's at the moment.

- Regarding your Map comment, we've considered having
Messages.forFields() return a Map<String, List<String>>. Would that
work? That would be identical to what WebWork supports today.

I'm not sure I understand the separation of Validatable and
ErrorAware.  In particular, Validatable only has a validate() method
that returns void.  Is there really a case you want to validate, but
not have errors sent anywhere?  I think of the use case of plugging in
a different validation engine like commons-validator, and this
separation makes it harder.  Why not return Messages?

I've been thinking Validatable should extend ErrorAware, but I wanted
to see what you guys thought first. I don't like the idea of
validate() return Messages. I never liked the fact that I had to
create an errors object in Struts. I also want to be able to easily
add validation messages from setters (I like doing field level
validation in the setter and cross field validations in validate()).

o.a.s.action2.attribute - This is again a feature I'd like to hear the
design reasonings of.  I liked the previous use of Maps as they were
easy to test and pass around.  Maps can also be extended to provide
the automatic synchonrization feature talked about easily.

This is something I've been kicking around since generics came out.
Now that we have generics, it seems funny to be passing around a
heterogeneously typed map. The new way results in better type safety
and less code. Here are some examples for comparison:

Old way:

   public class OldWay implements SessionAware {

       static final String FOO_KEY = Foo.class.getName();

       Map<String, Object> session;

       public void setSession(Map<String, Object> session) {
           this.session = session;
       }

       public String execute() {
           Foo foo = (Foo) session.get(FOO_KEY);
           if (foo == null) {
               foo = new Foo();
               session.put(FOO_KEY, foo);
           }
           foo.doSomething();
           return SUCCESS;
       }
   }

New way:

   public class NewWay {

       Attribute<Foo> fooAttribute = new
SessionAttribute<Foo>(Foo.class.getName()) {
           protected Foo initialValue() {
               return new Foo();
           }
       };

       public String execute() {
           Foo foo = fooAttribute.get();
           foo.doSomething();
           return SUCCESS;
       }
   }

Testing is actually easier--it's easier to mock out Attribute than Map.

I also proposed an annotation based approach, but Patrick preferred
the attribute API. Here's how that could work:

   public class AnnotationWay {

       Foo foo;

       // result is stored on session, called after execute() but
before result.
       @SessionAttribute
       public Foo getFoo() {
           if (foo == null) {
               this.foo = new Foo();
           }
           return foo;
       }

       // parameter pulled from session, called before anything else.
       @SessionAttribute
       public void setFoo(Foo foo) {
           this.foo = foo;
       }

       public String execute() {
           getFoo().doSomething();
           return SUCCESS;
       }
   }

I'm inclined to agree with Pat. The annotation approach is clean and
simple, but it conflicts with setting parameters (i.e. how do you
prevent setting parameters on session objects for security reasons?)
and is a little magical.

o.a.s.action2.servlet - I like how the servlet-related classes are
contained in their own package.  This distinction is very important as
I plan to be personally using Action 2 mostly for Portlets.

I talked with Pat about whether we should build an abstraction layer
over the servlet/portlet APIs, and we decided against it. The portlet
API really should have tried harder to embrace the servlet API. To
support the portlet API, we plan to implement a servlet API adapter to
it.

The deal breaker for me was that users will be able to reuse the same
code inside and outside of our framework. They won't have to port
their code from the servlet API to our new abstraction API. And it
makes less work for us and fewer new things for users to learn. ;)

o.a.s.action2.spi - Again, I love this separation - move all the
framework classes the user rarely deals with out into its own package.
 I like making ValueStack a first class interface, and the Interceptor
changes seem reasonable.  I am somewhat concerned about the Request
interface though.  While the goal of putting everything you need for a
request in one object, it seems to be combining too many roles.  For
one, it has servlet object retrieval methods in there that should be
separated, and I'm not sure if it should be handing the execution of
actions and interceptors as well.  If the goal is to turn this into a
Tapestry-like Visitor object which holds all the request state, we
should separate out the servlet getters into their own interface to be
combined by the user.

We've been playing with some ideas here. First off, actions should
pretty much never see this Request object. They still get everything
they need through the *Aware interfaces, etc.

I'm thinking of creating an ActionContext interface and moving all the
information about the currently executing action into there. Then we'd
have Request.getCurrentActionContext(), and we could even provide
access to the contexts of other actions in the chain if we need to.

I'm not sure I understand what you mean about moving the servlet
methods into a separate interface. Can you provide an example? To be
clear, users wouldn't implement the Request interface, but framework
implementors would.

Thanks,
Bob

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to