> But one of the main benefits of using the command pattern is that you
> only need one client API call.

I guess it's a matter of opinion, but I always saw that as an implementation
detail that gets exposed to any code that wants to use the RPC service.  My
goal in writing gwt-remote-action was to make it so that code on either side
of the RPC call didn't need to know whether or not the command pattern is
being used.  I prefer to have only code that wants to deal with actions as
opaque objects see them as such (e.g. see gwt-remote-action's
merge<http://code.google.com/p/gwt-remote-action/source/browse/merge/src/main/java/com/google/code/gwt/remoteaction/merge/client/MergingActionFilter.java#30>and
batch<http://code.google.com/p/gwt-remote-action/source/browse/batch/src/main/java/com/google/code/gwt/remoteaction/batch/client/AbstractBatchingActionFilter.java#28>filters),
while code that just wants to make an RPC call simply calls a
method.

I forgot to link this in my previous mail, but to get a better feel for the
gwt-remote-action usage see
http://code.google.com/p/gwt-remote-action/wiki/UsageGuide.

> On the server side you have one servlet that can use Guice to
> inject the handlers so you can implement handlers as POJOs.

This is still the case with gwt-remote-action (and is in fact possible with
traditional GWT RPC - see
here<http://stuffthathappens.com/blog/2009/09/14/guice-with-gwt/> and
here <http://code.google.com/p/ggdi/>).

> You should maybe look at something like gwt-dispatcher that implements
> the command pattern.

I've used gwt-dispatch <http://code.google.com/p/gwt-dispatch/> before, and
it wasn't quite what I was looking for.  I found adding a new action to be a
bit harder than I'd like (adding an action, result, and handler class, as
well as a Guice binding).  This was actually my main inspiration for
starting gwt-remote-action.  I also thought that gwt-dispatch is fairly
focused on transactional actions, which, while certainly an important use of
the command pattern, isn't really what I was interested in.

Cheers,
Jamie

On Thu, Nov 19, 2009 at 6:52 AM, David <[email protected]> wrote:

> Hi,
>
> I follow what you are trying to do, it would solve some complexity on
> the server side.
>
> But one of the main benefits of using the command pattern is that you
> only need one client API call. In case of GWT it means that you write
> onesync and async interface with one method... and from there on you
> can add commands without having to update these interfaces. On the
> server side you have one servlet that can use Guice to inject the
> handlers so you can implement handlers as POJOs. That is easier for
> testing and you don't need to extend the RPC servlet class everywhere.
>
> You should maybe look at something like gwt-dispatcher that implements
> the command pattern. I don't like the fact that I need to define that
> many classes (request,result, handler and registere the handler), but
> I guess there can be solutions to improve upon that design as well
> (introspection to find the handler automatically for example).
>
>
> David
>
> On Thu, Nov 19, 2009 at 6:52 AM, Jamie Gennis <[email protected]> wrote:
> > Hi all,
> > I've been writing a GWT library to implement the command pattern for GWT
> RPC
> > calls using the same interfaces that traditional GWT RPC uses.
>  Basically,
> > when an app calls a method of the FooAsync action service interface, an
> > action object is created from the method arguments, processed by some
> action
> > filters on the client, then passed to the server.  The server then pulls
> the
> > method arguments out of the action object and passes them as arguments to
> > the appropriate method of the Foo interface implementation class.  The
> > return value (or thrown Throwable) from that method then gets put into an
> > action result object on the server and sent back to the client, where it
> > gets processed by filters and eventually has the return value or
> throwable
> > pulled out and passed to the onSuccess or onFailure methods of the async
> > callback.
> > I have a working (albeit not extensively tested)
> > [email protected]
> > at http://code.google.com/p/gwt-remote-action/, but the implementation
> > relies on some GWT internals, so it's rather brittle at the moment. I'd
> like
> > to get some feedback on how I can change my implementation to be more
> > future-proof (or correct if it isn't), and which (if any) of the GWT
> > internals that I'm using might be candidates for becoming a part of GWT's
> > public interface.
> > The tricky part of the implementation is the action result.  The purpose
> of
> > an action result object is to encapsulate the result of executing an
> action
> > in such a way that action filters can manipulate it without having any
> > knowledge of what the action was.  It needs to contain an arbitrary
> return
> > value object or an arbitrary Throwable object (as well as an indication
> that
> > the Throwable was thrown rather than returned).  These objects are
> exposed
> > via the ActionResult interface.  Simply having a general action result
> class
> > that contains a return value field of type Object and an exception field
> of
> > type Throwable is not desirable because it would cause deserialization
> code
> > for every class that GWT knows about to be included in the compiled
> > javascript.
> > The current implementation works by generating one action result class
> for
> > each RPC method.  Identical action result classes are generated by a GWT
> > Generator at gwtc-time (for the client) and via Java byte code generation
> at
> > run-time (for the server).  My original idea was that this
> method-specific
> > action result class could have a result field of the specific return type
> of
> > the method along with a field for each type in the method's throws list.
> >  This turned out not to be necessary (at least for the cases I've
> tested),
> > because when GWT calls the Generator for the ActionExecutionService (the
> > traditional GWT RPC that sends the action objects to the server) it
> doesn't
> > find any of the generated method-specific action result classes.  Because
> of
> > this I simplified the action result classes to just have one field of
> type
> > Throwable, and I verified that not all the Throwable classes get included
> in
> > the deserializable classes list in the *.rpc.log files.  I'm not sure
> that
> > this behavior doesn't depend on GWT.create being called in a specific
> order
> > or something else I'm not aware of, but that should be solvable by
> splitting
> > the throwables into multiple fields if needed.
> > Generating the action result classes after the ActionExecutionService
> gets
> > generated means that none of the deserializers for the return values and
> > throwables of the action methods get generated or rescued.  To get around
> > this I:
> >
> > Make the ActionExecutionService use the new deRPC implementation rather
> than
> > the previous RPC implementation
> > Use the RpcProxyCreator class to generate a dummy implementation of a
> deRPC
> > proxy for the action service (this proxy doesn't get used)
> > Add an @ArtificialRescue to the generated action service proxy to rescue
> the
> > _TypeOverridesFactory class that the RpcProxyCreator generated.  This
> > _TypeOverridesFactory class has all of the @ArtificalRescue's necessary
> to
> > deserialize the fields of the generated action result class.
> >
> > Step 1 is mostly acceptable to me, though it would be nice if my
> > implementation didn't depend upon an experimental feature that may not
> make
> > it into GWT 2.0.  Step 2 is somewhat wasteful since it takes gwtc time
> > generating a proxy class that it will ultimately throw away via dead code
> > elimination.  Step 3 is pretty gross since the action proxy generator
> > basically just divines the name of the _TypeOverridesFactory via string
> > manipulation (see the getArtificialRescue method).  It may make sense to
> > factor the _TypeOverridesFactory generation into its own public *Creator
> > class that could return the generated class name (or maybe there's a
> better
> > way for me to leverage that functionality).  Also, the comments for the
> > ArtificialRescue class make me feel like a bad person for using it, so
>  if
> > there's a better way to achieve what I'm trying to do (or could be in the
> > future with some GWT changes) let me know.
> > The one last bit of black magic required to make this work has to do with
> > GWT's aggressive dead code elimination.  The action service proxy class
> that
> > gets generated has code that essentially does:
> > Throwable thrown = actionResult.getException();
> > if (thrown != null)
> >   callback.onFailure(thrown);
> > else
> >   callback.onSuccess(actionResult.getResult())
> > However, because the field returned from the getException method never
> gets
> > written (except by the eval'd code returned from the deRPC call), the GWT
> > compiler thinks it can eliminate the whole if-block, resulting in an
> > unconditional call to callback.onSuccess.  I'm not sure whether this is
> > specific to how I'm doing things or if this is a bug with the deRPC code
> in
> > general.  I currently work around it by creating a dummy action result
> > object (of the generated action result class type) and I set the field
> > returned to 'new Exception()'.  This currently tricks the compiler into
> > thinking that the field gets written to a non-null value, but I don't
> have
> > too much faith that it will continue to trick it in the future.  Who
> knows
> > how smart that compiler will get?
> > If you've gotten this far then... Wow, I'm impressed!  If you actually
> > followed what I was trying to explain then I'm even more impressed.  I'd
> > love to hear what more GWT-knowledgeable folk than me think about this
> > implementation.  I think being able to add command pattern capabilities
> to
> > existing GWT RPC services is pretty cool, but if it can't be implemented
> in
> > a robust and maintainable way then it probably won't fly.
> > Thanks,
> > Jamie
> >
> > --
> > http://groups.google.com/group/Google-Web-Toolkit-Contributors
>
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
>

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to