Archive

Archive for September, 2012

Spring message translation found in JSP but not in controller

September 20, 2012 1 comment

Well, this one had me searching the web for a while, for no avail.  Finally figured it out!

Here’s the problem:

You defined everything correctly to setup your web app to be i18n compatible using Spring, you even got messages to be translated when in jsp view mode, but now you want to translate a message in your controller.  Sounds simple?  not so (unless you know the secret).

So you looked in the web, and found that you need to declare the following:

@Autowired
private MessageSource messageSource;

You already have the MessageSource bean setup (for the View part) in spring-servlet.xml like so:

<bean id=”messageSource”
    class=”org.springframework.context.support.ReloadableResourceBundleMessageSource”>
    <property name=”basename” value=”/WEB-INF/i18n/messages” />
    <property name=”defaultEncoding” value=”UTF-8″/>
</bean>
 
And  still, when you try to run it through messageSource in your controller, you get NOTHING, empty string.  And if you look closely, you will find that you have a DelegatingMessageSource in your messageSource property, with an empty parent source, which means it is EMPTY, i.e. always returns blank.

Well, here’s the thing:  Spring will setup a DelegatingMessageSource when it can’t find a message source definition.  What’s that, you say?  it DID find a message source, it found it for my View!  That’s true, it did find it for the view, but not for your controller.  Why is that?  I don’t really know, but fortunately, I know how to fix it 🙂

So, here’s the solution for this little challenge: move your messageSource definition from spring-servlet.xml to applicationContext.xml!

This will let Spring find your messageSource for your Controller as well, and all will be well.

 

Advertisements

Using REST in cloudbees – not so simple

September 13, 2012 2 comments

Well, this one is going into “things that can drive you mad” for sure, as it took me a couple of days to reach the inevitable conclusion that I have to give up 😦

So here’s the thing:  you created a RESTful application, using the proper GET/PUT/POST/DELETE headers where appropriate, it works great on your local Jetty/Tomcat deployment, but when you try to run it on the cloud, it fails.  After much testing and debug prints, you find that when using PUT & DELETE the request gets there BUT the body embedded  parameters do not.

If this sounds familiar, you’ve got a problem.  As it is right now (Sep. 2012), app servers are not obligated to parse parameters delivered with PUT/DELETE requests if they are sent in the body (like in POST), because the standards to do not define that behavior.  Some will do it, some won’t, and there’s no one to complain to!

You can, of course, do all kinds of work arounds like setup a filter to parse the request on your own, or even do it in the methods, but I hate work arounds, they have a tendency to fail at some point when things change.

In the end, my solution to cloudbees deployment was to get rid of PUT altogether, and use DELETE only in requests which do not need anything in the body.  While this will work, I am unhappy with this solution, to the point of thinking about going to EC2 and not working with Cloudbees!  My applications should work as required, and should not depend on the hosting platform’s limitations!!

UPDATE!

Following Michael’s comment (see below), I gave this item some more attention, and finally got it to work!

As it turns out, it IS possible to use PUT and DELETE in cloudbees, you just need to know how to make it work.  Since PUT requests are not parsed like POST, there is a trick to make the application side parse it correctly.

The way I did it, is by using @RequestBody to pass the data to my dto on the server side, setting my content type to application/json;charset=UTF-8 on the jQuery side, and using JSON.stringify to set the content correctly so it can be parsed by my JSON converter.

So, my method looked like so:

@RequestMapping(value=”{id}/status/read/}”, method=RequestMethod.PUT)
public ResponseEntity<String> markRead(
@CookieValue(value=Constants.AUTHENTICATED_USER_ID_COOKIE, required=false) UUIDValidatedString userIdCookie, 
@PathVariable UUIDValidatedString id,
@RequestBody TestDto test
) {

}
 
and my ajax side looked like so:
 
function internalMarkMessageReadStatus(messageId) {
var obj = new Object();
obj.test = “true”;
$.ajax({
url: ‘/api/messages/’ + messageId + ‘/status/read/’ ,
type: ‘PUT’,
dataType: ‘json’,
contentType: “application/json;charset=UTF-8”,
data: JSON.stringify(obj),
success: function(response) { 
}
});
}
 
The DTO is just a simple POJO:
 
package com.tipabout.dto;
import org.codehaus.jackson.annotate.JsonAutoDetect;
@Document
@JsonAutoDetect()
public class TestDto {
public String test;
 
public TestDto() {
}
 
public String getTest() {
return test;
}
 
public void setTest(String test) {
this.test = test;
}
}