Running AJAX with jQuery in Stripes Framework

Though most of articles at this blog are written in my native language – Czech, this one will be different. I have chosen an English to address wider community of Stripes developers – I think there would’nt be enough readers in our beautiful small country. So, please, excuse possible errors and mistakes in the article, I will try my best :-) .

Common introduction to AJAX in Stripes

Stripes framework offers basic but sufficient support for AJAX that is covered with article at official web site. Article recommends using commonly known PrototypeJS AJAX client side library. On the server side, request is processed by Stripes themselves by standard population and execution as any other http request (that means that data from client to server are sent as a standard URL encoded parameters). What you get is correctly populated and validated action bean – and until now you haven’t even recognize, that request is made by JavaScript on the client side not even you have to care of it. You can access session, exchange cookies and so on.

After you process incoming request you have several possibilities how to return result:

  • you can return RedirectResolution or ForwardResolution as you are used to when processing standard browser request – then, if the redirect or forward targets JSP or such, typically text/html content is returned as a response of the AJAX request. This output you can easily inject into appropriate container in DOM via setting innerHTML property (prototype has optimized object for this approach – Ajax.Updater)
  • you can return JavaScriptResolution giving it Java POJO (could be called DTO too) in a constructor – Stripes then take care of marshalling Java object into JSON snippet of code, which could be easily (see chapter Stripes non-standard JSON result for more details) evaluated on a client side
  • you can return StreamingResolution directly creating resulting content along with setting specific content type – this choice gives you most freedom but usually means much more effort than previous two options

Describing above possibilities you can deduce typical use cases for them:

  • when you are not used to code on the client side or you want to save a lot of your time, you would probably choose first option – returning to client whole HTML snippet replacing or other way modifying part of the original page; on the other hand this option is probably the slowest of all involving JSP interpretation (or other type of presentation layer template)
  • when you want to keep size of interchanged data small or you want to modify more different parts of the displayed page at once, second option would be better choice allowing you to access data from server in further interpretable form (simple JavaScript object); on the other hand you would have to make a lot of the work on the client depending on amount of needed modifications
  • only when you need something special or you need to precisely polish resulting response, StreamingResolution should be taken into consideration; it gives you most possibilities for customizing the output but would involve most work

Why Stripes and not DWR?

Although I like using DWR, I must agree that it is worthy to use native Stripes support. DWR is oriented for direct access to Java objects and invoking their methods. When you have ActionBeans prepared for standard web application, you can use huge part of your code at the controller level (eg. validation, message rendering, interceptors, Spring bean injection, field populating protection and so on). With DWR you’d have to solve a lot of things again.

I think that DWR has better support for AJAX itself – I haven’t ever run into an encoding problem with DWR as with Stripes & jQuery combination (see below), nor I have to solve the format in which DWR is transfering its data (DWR consists of both server and client side library). DWR also supports “server push”, has more developed security (request forgery, crossite attack) and so on (I am not aware of having these in Stripes). But seamless integration with web framework is more important if you don’t need such advanced features. It just can save a lot of time.

National characters encoding issue

This was the first problem I had to solve. You’d run into this issue when sending national characters from your browser while having configured non UTF-8 encoding in LocalePicker in Stripes configuration in web.xml. Let’s say, you have your JSPs written in cp1250 encoding, you should then have the same locale set in Stripes LocalePicker configuration, so the Stripes will call request.setCharacterEncoding before any data will have been read from the request. In that combination national characters in request parameters should be ok.

What is the difference with AJAX? The difference is that frameworks such as jQuery or Prototypejs call, when preparing AJAX request, method encodeURIComponent() that will convert all special characters into unicode. This means that data that come in AJAX request are always (or at least this is what I realized) in UTF-8 encoding. So the AJAX request must have been treated differently than standard browser request.

Note: Don’t be fooled. In Prototypejs there is method with parameter encoding – but even if you set different encoding, characters themselves will be encoded in UTF-8 anyway. Problem is that encoding is set by Prototypejs into request headers, but is not used (and cannot be used because there is no paremeter for encoding in it) when using encodeURIComponent method to convert special characters.

What to do?

For me the solution was quite simple (although I don’t like having Stripes configuration twice in my web.xml). This is what I had to do:

Configure Stripes in web.xml twice:

This configuration divides Stripes to treat two request differently accodring to extension of the script (*.x or *.ajax). Each of these requests will have character encoding set differently. Unfortunately I didn’t find out better way how to distinguish these requests – they look the same to the server.

Until now it is ugly solution. But it allows me to neatly implement action beans. Basic action bean oriented for standard non AJAX access looks like this (there is a lot of code cut from the example):

And this is its extension for AJAX call.

Validation and other settings are inherited from the original action bean and only createQuery method is overwritten in AJAX implementation returning different result. If you wonder what ActionContextJavaScriptResolution class is – it is simple extension of JavaScriptResolution building POJO object containing basic information from ActionBean context to be sent to the client (I will include complete code of this resolution at the end of the article along with some demo, so you can use it if you want).

Stripes non-standard JSON result

Next thing I have encoutered when trying to execute AJAX calls to Stripes is, that Stripes JavaScriptResolution returns weird JSON code not compatible with jQuery nor Prototypejs. Stripes response contains serveral lines of code that has to be evaluated on the client by calling eval(response), but jQuery as well as Prototypejs looks for one declaration that they execute this way: eval(“(” + response + “)”). The response returned by Stripes are not compatible with this way of manipulaiton.

Note: Not only jQuery or Prototypejs have problems – even Firebug is somewhat confused when receiving this kind of output. I realized that breakpoints in JavaScript code started to behave strange when debugging around this problem. It looked like Firebug tried to move over the lines returned by Stripes but looking at my calling code. So the cursor of the active called line just jumped for the first run absolutely mistrial, but when patient it returned back and started to go over the expected lines again.

Example of Stripes returned JSON

Example of expected JSON

What to do?

So in jQuery you have to execute requests in following format to be able to process response:

By fourth argument of the jQuery.post method you specify, that in return you expect plain text. This means that jQuery will no further process received response before handling it to your callback method. Processing of the returned data will be then made by you.

I wonder why the Stripes behave like that? Is there anyone who could explain?

Submitting standard HTML Form via AJAX – Example

At the end of this article I’d like to show you some simple example with snippets of code that you can you if you like it. It is simple HTML form submit in AJAX way. You can see how it looks like in the clip below.

Full resolution of the clip is here.

Demo leverages jQuery effects so it looks like quite well (at least I hope so). JavaScript on the client is pretty sraightforward – you just call one method giving it ids of the form and div, that will render errors / ok messages from the server and name of the event that should be called on the server side. Url itself is taken from the form action property.

Then there si this JavaScript code, that will make an AJAX request and modify page after receiving an response:

On the server side there is action bean shown before. As a result it returns ActionContextJavaScriptResolution(actionBeanContext) that will create simple POJO java object:

ActionContextJavaScriptResolution is simple extension of JavaScript resultions that only creates result POJO object based on information that can be found in standard ActionBeanContext. ActionContextJavaScriptResolution uses standard Stripes properties to render HTML containing errors or messages it finds in context – so you needn’t to do nothing more than you have to do when creating standard Stripes application. This HTML snippet prepared by the server is then used by Javascript to simply pasting it into specified div.

And that’s all. I believe that this solution and code is transferable to any other HTML form. I hope that this will help you to AJAXize your plain HTML forms without much effort.

Links and sources

Podělte se s ostatními:

  • Digg
  • del.icio.us
  • Technorati
  • Diigo
  • DZone
  • FriendFeed
  • Google Bookmarks
  • LinkedIn
  • Reddit
  • RSS
  • StumbleUpon
  • Twitter

Související články:

  1. Stripes, bojovník střední váhy?
  2. Není AJAX jako AJAX – GWT vs. DWR
  3. Část #4: Modulární systémy ve Spring Framework
  4. Oracle, od slova věštit
  5. Část #3: Modulární systémy ve Spring Framework
Ohodnoťte článek:
Takovéhle články už radši ne!Nic nového pod sluncem.Průměr - obsahuje zajímavé střípky informací.Hodnotný článek - lecos nového jsem se dozvěděl.Skvělý článek - informace se mi dost hodí. (2 hlasů, průměrně: 4.00 z 5)
Loading ... Loading ...

-236 Responses to “Running AJAX with jQuery in Stripes Framework”

  1. Hi Jan,

    Really nice artice. Especially the encoding issue is interesting because I ran into similar problem now while using Stripes. This could help. Thanks!

    Demo of the application is sexy ;-)

    Regards,
    Lukas

  2. Novoj says:

    Yeah, but as Vlasta Vavru said in his article http://vavru.cz/ajax/jquery-je-sexy-javascriptova-knihovna-pro-ajax-dom-a-animace/ jQuery itself is sexy.

  3. I agree, it is sexy. However; the question is if this sole fact can be used as a justification for higher management :-)

    I used to use AjaxTags (http://ajaxtags.sourceforge.net/) in the past and it worked well too. I have switched to JQuery some time ago and I like this change but still I do have to support old code with AjaxTags. What if I switch to other (way to sexier) ajax library in the future? Support hell ™ on horizon…

  4. Nice to see that Stripes is gaining attention here! It surely deserves it, as it brings fresh air to JEE, IMHO.

    I’ve always managed to do what I wanted with Taconite+jQuery or simple JavaScriptResolution+jQuery, but these examples might come handy one day..thanks ;)

  5. Makub says:

    I think that the reason for the strange JavaScript code generated by Stripes instead of JSON is that the Stripes’ JavaScriptResolution class allows to send graphs of objects with circular dependencies, while plain JSON can send only a tree of objects, not an arbitrary graph.

  6. Novoj says:

    That makes sense. But unfortunatelly in common case it is unnecessary and and only confuses standard client libraries. But thanks for explaining. Can I ask you where did you find that information?

Leave a Reply