We were babbling on IRC, as we tend to do. I mumbled about this a  
couple of days ago, and then Double-A Porter got on his bullhorn  
about StripesStuff.

I want to explore adding a more formal REST capability to Stripes.

I think that there is great value is adding better "full bodied" REST  
Support to an Action framework like Stripes.

If you cruise around the Intratubes, you'll find that we have Action  
Frameworks, but we also have REST Specific frameworks as well.

Turns out the Action frameworks don't actually support REST as well  
as they could, and REST frameworks don't support classic web apps  
very well, if at all.

Now, some may say "WTH? What's so hard about REST? It's just HTTP, eh?"

Yes, it is just HTTP. Which is why it's kind of silly to need two  
"HTTP" Frameworks to make writing this server side logic.

"But if REST is just HTTP, why can't we just use Stripes out of the  
box?" Well, first it doesn't come in a box -- you have to download  
it. But, be that as it may, Stripes, like most every other Action  
Framework, actually supports only a subset of HTTP.

For example, we had the post earlier about the other HTTP verbs and  
how, save for GET and POST, Stripes pretty much just shows them the  
door.

That's Bad(tm).

See, the REST wonks want to use all of those other verbs: HEAD, PUT,  
DELETE, etc. In fact, some want to make their own as well (for  
example, WebDAV creates its own HTTP verbs). This is fully within the  
HTTP spec, making this stuff up as you go.

Now, while you Cro-Magnon web page grognards from the "when I was a  
kid, all we had was GET, 14K modems, and Perl" school of web  
programming are happy with the status-quo. REST aficionados, umm, ain't.

Fortunately, it should not be a real leap to bring Stripes in to the  
21st century, and be a Good Citizen with the rest of the HTTP protocol.

Ideally, this can all be done in Stripes Stuff with interceptors, so  
as not to need to change Stripes core and offend Tim and his "GET OFF  
MY LAWN" ways.

I think the primary thing is to be able to expose the HTTP verb as a  
first class part of the binding and event mechanism.

The requirements are:

+ Stripes works as it always has -- this is an "opt in" system. So,  
breaking classic Stripes is off the table.
+ First class handling of the Standard HTTP verbs: GET, PUT, POST,  
DELETE, HEAD, OPTIONS. TRACE and CONNECT appears to be server level  
Verbs, so we'll punt on those.
+ Ability to support other verbs. This means, basically, being able  
to bind to a String.
+ Better support, perhaps through utility methods for content  
negotiation, HTTP headers, and response codes. Response codes are a  
Big Deal to REST folks, so they should be easy.
+ Easy return of ValidationErrors in some format besides HTML (i.e.  
XML or JSON)
+ Ideally, binding to other data types beside multipart form  
requests, notably XML and JSON, though this is at the bottom of the  
list for a reason.

In REST, it's important that the same URL do different things  
depending on the verb.

Right now, Stripes conflates GET and POST to mean the same thing. To  
the REST cognoscenti, the two are quite, quite, different. So, we  
need to be able to readily handle differentiating those two kinds of  
requests, even tho the URL is identical.

There's two ways to do that.

One is annotating a method with @Rest, or @Http or something, and  
then using a configuration by convention meme base on the name of the  
event.

For example:

// Default rest binding
public class PersonActionBean {
        @Http
        public Resolution post() { ... }
         @Http
         public Resolution get() { ... }
         @Http
         public Resolution delete() { ... }
         @Http {method="MYHTTPVERB"}
         public Resolution myHttpVerb() { ... }
}

If an event is passed, we could do:

public class PersonActionBean {
         // For event name "view"
        @Http
        public Resolution postView() { ... }  // should this be viewPost?
         @Http
         public Resolution getView() { ... }
         @Http
         public Resolution deleteView() { ... }
         @HandlesEvent("view") // stock stripes annotation
         @Http {customMethod="MYHTTPVERB"}
         public Resolution myHttpVerbForViewEvent() { ... }
}

If we punt on CbC, and be explicit we can do:

@Http(method={HttpVerb.DELETE, HttpVerb.PUT}, customMethod= 
{"MYDELETE", "MYPUT"}, eventName="shazam", default=true)

where

method = The HTTP verbs that this event would bind too.
customMethod = Custom HTTP verbs to bind to
eventName = the name of the event to bind too

And stock @DefaultHandler would be used to tell us that it's the  
default for that specified methods.

By default, any event that isn't annotated would be considered as  
method={HttpVerb.POST, HttpVerb.GET}, i.e. both, like Stripes is now.

Does anyone like or dislike either of these techniques for binding  
events?

For content negotiation, I think just some utility methods can be  
used to break up and make the content-types more available to the  
user. I don't see a need to dispatch on content type (though that  
could be interesting as well, I think it's something that could also  
be layered in later).

For the Headers and ResultCodes, that can probably be handled with a  
couple of new Resolution types, I don't recall how stripes handles  
result codes right off the top of my head.

We saw the issue that Freddy had with having to extend  
ForwardResolution to add his Success header, a customer resolution  
that lets us tack on headers would be trivial to do.

As for returning errors in a different format than HTML, that could  
also be done, I think through a custom resolution,  
JSONErrorsResolution, or XMLErrorResolution, and the dispatch code  
could (somehow) know which one to you, either by configuration or,  
ideally, content negotiation.

For now, I'll punt on potentially binding other data type for input  
besides mutlpart form requests. I think there's value here, as many  
REST services are POX services, as well as multipart, and Ajaxy types  
like chatting in JSON.

The basic thought was that the process would "flatten" the in coming  
XML  or JSON into, effectively, multipart parameters, and then let  
Stripes do the rest of the work. Also, we make available, perhaps,  
the DOM of the XML if the action has a Document field. And, perhaps,  
something appropriate for JSON (I don't know much about JSON, so I  
can't say what this would be, heaps of bags of maps of maps maybe).

Obviously, if you send stuff that the standard Stripes binding can't  
do, then, well,it doesn't work. Don't do that. Be nice to Stripes,  
it'll be nice to you.

Save for the potential binding of incoming data, you can see that  
this should not be a horrible amount of work.

And I'm not suggesting anyone take it on, or that the Stripes guys do  
it.

But I would like to have your thoughts about the approach, which you  
like better, and any suggestions that y'all might have.

Regard,

Will Hartung


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Stripes-users mailing list
Stripes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/stripes-users

Reply via email to