Spring Form Tag Broken for Portlet Use

This issue came up as I was dealing with the Spring Portlet ResourceRequest change(before I found the problem/solution).  Still not getting the portlet to render views via ResourceRequests properly, I decided to test with Spring 3.2.x to see if the problem would follow.  I was also curious to see what changes would be made on the portlet side of things, any added improvements or shortcuts?  Based on the 3.2.x changelog, not much was changed regarding portlet support(ctrl+f “portlet”).  But its never that simple, right?

Enter SPR-8684.  This change actually makes things easy for most Spring webapps; automatically prepending the contextPath and servletPath in the Spring form tag is an easy shortcut.  But for portlets, this renders the form tag essentially useless.  Portlets don’t want their forms to be prepended with their own contextPath, they should resolve to the portal’s contextPath.  The good news is that my request for a fix was accepted almost instantly, SPR-10382.  So I’ll just have to wait to use Spring 3.2.3.

I know many of my most recent posts have been about problems using Spring, but I don’t want to sound like a complainer.  Without Spring I would be without a brilliant framework to code portlets with, and its a pretty niche area to be honest.  I love Spring because they are constantly moving forward by adding new ideas and technologies into their product.  Also, the community support is pretty fantastic!

Spring Portlet ResourceRequest Change

Spring Portlet made a change to the way portlets return resource requests.  They changed the default behavior of DispatcherPortlet when handling resource
requests to use PortletRequestDispatcher.forward instead of PortletRequestDispatcher.include; JIRA issue here — SPR-9876.  I’m indifferent about the change.  It seems more people use the ResourceRequest with the .forward, so its good for them I guess.  I mostly use resource requests with small custom jsps, so I use the .include.  But it doesn’t really matter to me aslong as they maintain compatibility, which they did.  If you set renderResourceViewViaInclude property to true(defaults as false) it should work the same as before.

Well, I can’t get my views to render through resource requests anymore after this change.  The only change that was supposed to be needed was adding an init-param into your portlet.xml, but even with that in place my views just return blank.

<init-param>
<name>renderResourceViewViaInclude</name>
<value>true</value>
</init-param>

Another person also suggested to set alwaysInclude to true on the InternalResourceViewResolver in the applicationContext, but that didn’t work for me either.

<bean id=”viewResolver” class=”org.springframework.web.servlet.view.InternalResourceViewResolver”>
<property name=”cache” value=”false”/>
<property name=”alwaysInclude” value=”true”/>
<property name=”viewClass” value=”org.springframework.web.servlet.view.JstlView”/>
<property name=”prefix” value=”/WEB-INF/jsp/”/>
<property name=”suffix” value=”.jsp”/>
</bean>

I’m still trying to figure out why this isn’t working.  Based on the git commit tied to the issue, it looks like aslong as renderResourceViewViaInclude is set to true then the dispatcher should call .include.  Is it not working as intended?  Or is renderResourceViewViaInclude not being set properly?

The culprit has been found! While talking with the person who made the JIRA issue and git commit, it looks like Spring never implemented the renderResourceViewViaInclude flag on DispatcherPortlet(and now rereading the last comment on JIRA I can see that they actually said they weren’t going to). So all resource requests were ALWAYS using .forward.  The fix?  You will have to subclass DispatcherPortlet and override doDispatch to use .include, or set up your own flag.

Hopefully Spring will actually put this the flag into the their portlet library so people won’t have to do this for every portlet that wants a review returned from a resource request.Talking with some other portlet developers, it seems I am in the minority of using resource requests to return views, they are mostly used to return pure json data.  It seems I either need to get with the times or I will have to use my subclassed DispatcherPortlet in all future portlets.

Spring Portlet Handler Mapping Error

Another post about Spring Portlet MVC.  Currently in Spring 3.1.2(and 3.1.1 as far as I can tell) there is a problem with portlet annotation handler mapping apparently due to a flaw in predicate comparison; its documented more in depth in their jira at SPR-9303.  The issue has been reported to have been fixed for Spring 3.1.3, but until that comes out I had to find a work around.

The hard part about diagnosing this bug is that it may or may not affect your portlet depending on how many annotation handlers you have, how they are structured, and in what order they are picked up by Spring.  Many of the portlets we have created haven’t had any problems(or none that we have experienced so far), but one portlet in particular was mapping every single render request to its default mapping.  Someone on stackoverflow has investigated the ordering further and shows exactly why the ordering matters.  Long story short, if the default handler mapping isn’t ordered last then any handler mappings behind it will never get used.

A workaround is simple enough, albeit a little ugly.  Remove the default annotation handler mapping method into its own class and package and have Spring component-scan to register it separately.  Like so:

<context:component-scan base-package=”com.kwilkins.portlets.foo”>
<context:exclude-filter type=”regex” expression=”com.kwilkins.portal.foo.controller.springbug..*”/>
</context:component-scan>
<!– This package temporarily exists due to spring bug; SPR-9303 –>
<context:component-scan base-package=”com.kwilkins.portlets.foo.controller.springbug”/>

Doing this should scan and register the default mapping after everything else already has been.

Spring Portlet Validation Errors

I am currently in the process of updating some of our portlets to use Spring 3.1 and the new Portlet 2.0 spec in preparation with a portal framework upgrade taking place for ZotPortal this summer.  A problem we were experiencing using the new Spring 3.0 annotations for our portlets was the new way Spring handles validation/binding errors for forms.  Before, the validation is done in the action phase, then the error(s) are stored in the model attribute, and if errors are present you can redirect back to the render phase so the initial page form will be displayed again with the submitted data but this time displayed with error messages that explain to the user why it failed validation.  I was surprised when the validation would fail this time and redirect back to the page form but no errors would show.  Apparently something changed in the way Spring handles objects placed into the model via the @ModelAttribute annotation.  Now Spring would replace an object even if it is associated with errors and they will not be present/displayed when redirected back to the form.

A few solutions have been proposed across the spring forms, stackoverflow, and the interwebs;

  1. Validate the form object during the render phase as well.  This will generate the errors and have them displayed on the form when the rendering completes.
  2. Explicitly preserve the form object or errors after the redirect and ensure they get passed to the form when rendering completes.
  3. Instead of using @ModelAttribute, persist the form object as a session attribute so it persists across the action and render phases.

Option 1 isn’t really an option for our applications.  In the initial render phases the form object would not pass our validation tests because it isn’t filled out yet!  We don’t want to display validation error messages to the user upon the first load of the form when they haven’t had a chance to submit any data yet, it would seem a bit rude in my opinion.  Validation should occur if data has been submitted.  Option 3 seemed to be overkill, submitting a simple form shouldn’t need to persist the form object in the session which lives well past the action phase of the submit.  I believe Spring has some nice ways of handling these session attributes, but I haven’t played with it very much.

I decided to use option 2.  When the render phase is deciding what object to populate the form with it first checks to see if an applicable object with errors already exists in the model, if it does it lets that object stay in the model to populate the form.  The previous submitted data and errors get passed through the render phase and displayed on the form for the user to see and fix so it can be validated properly.

I wrote an example for persisting the object and it seems the same result can be accomplished by persisting the errors object instead, but I haven’t tested that.  Options 1 and 3 can also be found in this thread.

Campus Organizations Portlet

Currently I am a student software engineer for the University of California Irvine where I build web tools for the for the student portal, ZotPortal.  If you aren’t too sure of what a web portal is, think iGoogle – lots of different content pieces on one page.  These content pieces are called portlets and I design, engineer, and maintain them on ZotPortal. I want to talk about two different things in this post, 1) a portlet I designed that enables people to search for on campus organizations at UCI and 2) some different ways of obfuscating email addresses (or other data) from potential scrappers/spammers. The connection will become apparent later.

Campus Organization Portlet

The Campus Organizations Portlet was the first portlet I built. The idea was simple enough: given a feed of all the campus organizations, parse out the data, and display all the organization information in a searchable UI. There are currently around 540 different organizations to show, so the data needed to be broken up into separate pages.  I decided to use the Fluid Pager javascript component to page through the data without having to reload the page. This enables us to place each organization in its row along with its info box and category. The gapped paging scheme makes navigating through the pages a breeze without cluttering the pager bar. Some more javascript was added for to display organization info and the search bar to re-render the pager with just the search results.

Now, on each organization’s information panel we supplied a mailing address so a user could contact the club leaders. And since this portlet is accessible from the guest view, there is potential for spam bots to troll through our student portal and collect all of the club email addresses to sell or send spam to. I wanted to hide the email addresses from the spammers while at the same time enable the viewer to use the email. So, I spelled out the symbols in the email to confuse any would-be spam bots reading through my portlet data. Instead of coolclub@uci.edu, coolclub[at][you see eye][period]edu. An average spam bot wouldn’t recognize this as an email address, spam avoided! The only thing that bothers me with this approach is the fact that the user has to do the work of replacing [at][you see eye][period] with”@uci.”. Sure, it isn’t very difficult or time consuming, but it would be a lot better if the user could simply copy/paste or click a mailto tag.

I found someone in a similar dilemma and a really good answer was provided to him.  Examining these different methods of obfuscation allows us to pick the best one for our situation.

  1. CSS direction
    • Code
      • <span style="unicode-bidi: bidi-override; direction: rtl;">moc.elpmaxe@zyx</span>
    • Renders as
      • xyz@example.com
  2. CSS display
    • Code
      • xyz<span style="display: none;">foo</span>@example.com
    • Renders as
      • xyz@example.com
  3. ROT13 encryption
    • Code
      • <script>var email = decodeROT13(klm@rknzcyr.pbz); emailElement.append(email);</script>
    • Renders as
      • xyz@example.com
  4. Using ATs and DOTs
    • Renders as
      • xyz[AT]example[DOT]com
  5. Building with javascript
    • Code
      • <script>var email = 'xyz'; m += '@'; m+= 'example.com'; emailElement.append(email);</script>
    • Renders as
      • xyz@example.com
  6. Replacing ‘@’ and ‘.’ with entities
    • Code
      • xyz&amp;amp;amp;amp;#64;example&amp;amp;amp;amp;#46;com
    • Renders as
      • xyz@example.com
  7. Comment splitting
    • Code
      • xyz<!-- eat this spammer -->@<!-- ha ha -->example.com
    • Renders as
      • xyz@example.com
  8. Urlencode
    • Code
      • xyz%40example.com
    • Renders as
      • xyz@example.com
  9. Plaintext
    • Renders as
      • xyz@example.com

The author of this study (credit to Silvan Mühlemann; his original post can be found here) even watched each of these methods for over a year just to see the different amounts of spam each strategy would receive.  These were his findings…

Obfuscation Methods

The current obfuscating strategy I use received the lowest amount of spam out of the ones that got spam in this study.  However, there are better strategies, with zero spam, that don’t require any work from the user (strategies 1-3).  So, I should change the strategy for obscuring the organization email in the portlet since there doesn’t seem to be any cost Late February 2011, we changed the obfuscating method and decided to use CSS direction.  We still are looking into a combination approach with CSS direction for display and javascript building for a mailto link for better and easier interaction.