Tuesday, January 29, 2008

Stripes 1.5 Feature: Clean URLs

So I promised a list of some new features coming in Stripes 1.5. Since several of them require some explanation to really get the point across I decided to do a daily article about each of the major feature improvements and then one final article on the smaller things. I finally found a bit of time so here is the first one. Stripes 1.5 is coming along really well. The developers have been committing code like crazy the past month. We should be seeing a beta release really soon.

Disclaimer - We know that other web frameworks have had some of these features in some form or fashion so please don't comment with "ZZZ Framework has been doing that for years.". We know. We get it.

Clean URLs have been possible in Stripes for a while through an add on. However, with Stripes 1.5 they will be an optional feature in the core API. As you may or may not know currently you can define a URL Binding for a Stripes action one of 2 ways. You can let Stripes handle it by inspecting the package and class name and binding it for you or you can explicitly set it using the @UrlBinding annotation. With clean URLs @UrlBinding is required. The format is something like:

@UrlBinding("/action/blog/{$event}/{blog.id}")
public class BlogActionBean...

The resulting URL to edit a blog entry would be:

http://.../app/action/blog/edit/1234

If the event is null it is ignored as well as any given parameter. So a URL like:

http://.../app/action/blog

would result in calling the Default Handler for the BlogActionBean. Support for default parameter values are also available.

@UrlBinding("/action/blog/{$event}/{blog.id=1234")

So accessing the url

http://.../app/action/blog

blog.id will have a value of 1234 however if you pass in a blog.id value it will override the default. Default values for {$event} can also be given. This overrides the @DefaultHandler method if one exists. Otherwise, the @DefaultHandler method is executed.

If you still prefer extensions on your URLs, support for that is also available. The change to the URL binding is trivial:

@UrlBinding("/blog/{$event}/{blog.id}.action")

Stripes JSP tags <s:url />, <s:link />, and <s:form /> all support Clean URLs. For example:

<s:link beanclass="com.app.foo.BlogActionBean" event="edit">
<s:param name="blog.id">1234</s:param>
Edit
</s:link>


Will result in:

<a href="/app/action/blog/edit/1234">Edit</a>

And that is pretty much it for Clean URLs in Stripes 1.5. Very simple, elegant, and as good as the next guys. Possibly better? Let me know.

15 comments:

jNayden said...

i just wanna say that STRIPES is GREAT :) I love it it is better than Struts2 ( struts 2 is blah) better than struts1 ( less coding ) and do you know what - I LIKE IT MORE than JSF too :)
btw i dont know what are the plans for 1.5 or 1.5+ but will be nice to have :
better AJAX support ( AJAX tags, taglib) and will be nice to have somethink like <stripes:bundle name="Stripes" name="msg"/> and to use JSTL ${msg.somethink} everywhere in the code.

Gregg Bolinger said...

Thanks "Joke". You can already use resource bundles with stripes. Just use JSTL's FMT tag.

Also, don't bet on any ajaxified taglibs showing up in Stripes core. That's not the focus of what Stripes is and does.

Thanks again for the comment.

Anonymous said...

Nice write-up Gregg!

Three cheers for this, and looking forward to reading your other posts.

Freddy

Jan Novotný said...

Would there be any support for multiple urls to single action bean. For example we have a few requests from our customers to provide "localized" url. So that urls are comprehensible to end users.

For example:
/appName/user/registration
/appName/uzivatel/registrace
/appName/user/registrierung

So something like accepting list of urls in @UrlBinging would be required. Is this issue somehow addressed?

BTW: clean urls itself seems pretty well - good work

Anonymous said...

Hi i want to ask somethink :
when you have validation :
@Validate(required=true, minvalue=13, maxvalue=120)
private int age;
is this validation procedded on runtime ? Becouse I think that when you use reflection API and if you have Security Manager you cant access to private field from other class so is this maked inteligent i mean: when the field is private but annotation is applied to FIELD the value of the field to be getted by the getXXX method and annotation is getted from FIELD is this automatic implemented in Stripes ?

jNayden said...

A Bug in 1.4 i think with low priority:
When you have a stripes:link with event name which is equal to name of an parameter.
the problem is that the link is like :
http://localhost:8080/DevelopersBGStripes/User.action?cancel=&_sourcePage=%2Fpages%2Fuser%2Flogin.jsp&cancel=1221

as u see there is 2 cancel params first is ="" and secound is 1221 the first is the name of the method to be invoked .. the secound is my param which i expect to get with valu 1221 but i cant get it .
<stripes:link href="/User.action" event="cancel">
<stripes:param name="cancel" value="1221"></stripes:param>
Link </stripes:link>

the method :
@DontValidate
public Resolution cancel()
{
System.out.println("Param is"+context.getRequest().getParameter("cancel"));
return new ForwardResolution("/index.jsp");
}
it displays "param is " only becouse the first param have value "".

Gregg Bolinger said...

Wow, lots of comments this morning. Thanks.

@novoj - The stripes team is currently talking about this feature as we speak.

As per the other questions regarding Stripes, please feel free to ask this on the stripes mailing list. You can find a link to it at http://www.stripesframework.org.

Thanks.

metrixon said...

Hi,
that sounds really great - currently we've implemented clean urls using an url rewriting filter but an integration into stripes core is much better.

I'd also vote for multiple URLs per ActionBean.

Unknown said...

When will Stripes 1.5 be released? I can't wait for it to come out. Is it deployed on a maven repo?

Thanks

John Journey said...

This is great! I'm thinking of moving away from URLRewriteFilter and integrate it with stripes.

Quick question, Does it support multiple URLBinding ( multiple url format pointing to the same ActionBean ) as of today? maybe I better ask this from the list. :D

Hugo Alvarado said...

Hi Gregg, I was looking your post and decided to implement your advice in my code but unfortunately its not working as expected, I don't know what am i doing wrong since I just annotated the my ActionBean as you say: putting the @UrlBinding("/register") annotation but when i click a link to register:
stripes:link beanclass="actions.RegisterActionBean">
Click Here to Register!
stripes:link

My Tomcat says that the resource (webapp/register)its not available ?:S is there anything that im missing? thank you.

Unknown said...

@Hugo Alvarado

The clean URL needs a pattern, defined in web.xml, only put /register isn't work!
Look at the examples above.
I can see this part of code:

@UrlBinding("/action/blog/{$event}/{blog.id}")
public class BlogActionBean...

The resulting URL to edit a blog entry would be:

http://.../app/action/blog/edit/1234


Try map your URL to /action/* and then type you address like http://domainserver/action/register

Anonymous said...

Cool post as for me. I'd like to read more concerning that topic. Thanx for giving that data.
Sexy Lady
English escorts

nana said...

Cheap Guild Wars 2 Gold is anyone to end coming from all this particular? It's fair to summarize that right now valid web coding won't assist you to increase your research situation. If Gw2 Bay offers any impact on results, it can be minimal in comparison with additional factors. One other good reasons to utilize good web coding are usually solid and i also might nonetheless suggest all designers start off verifying their internet sites; ArenaNet merely don't expect which doing the work can explode you inside the search rankings at this time.

Thinking said...

Useful feature for bloggers.