Archive

Posts Tagged ‘REST’

Online service development in java – a beginner’s guide

November 4, 2012 1 comment

In the coming series of posts, I will share my development experience (code included) with creating an online service from scratch.  If you read through all posts, you should reach a point where you are capable of writing code and deploying it to a production like environment which is available online, using some of the latest (and greatest) open source libraries available in java.  You will definitely not be at the end of the journey, but will get a pretty good head start.

I’ve created a sample project, which basically does nothing (well, almost nothing), but it does so in a (semi) secure way, using several top libraries.  Basic service, is a service which lets you register, login, and… do nothing.  But, it does so using:

Spring, Maven, ESAPI (+AppSensor) for input validation, JSP’s (JSTL+Tiles 2), jQuery (+UI), Mongo DB, Logback, Jackson, Mockito (+PowerMock) for unit testing, and it does it in a RESTful way, using complete Data and Presentation separation (all JSP’s get their data through REST requests, meaning you can add easily add mobile support without almost any change to the  interface), and is fully internationalized (currently supports hebrew and english, meaning we have RTL languages covered).  The complete source code for Basic service is available on google code, it is a fully functional (and GPL open source) example of combining all of these technologies , which means that you can concentrate on the next steps rather than spend time building the foundation from scratch.  It took me about 3 months to go through all the baby steps in each of those technologies (after spending some time picking the right ones of course), I hope this series will save you at least some of that time.

Please keep in mind that I do not claim this to be a complete and bullet proof piece of software, there is still much to do in order to make it “production ready”.

Basic service is deployed on Cloudbees, using Continuous Deployment,  you’ll get some insights on how to do that as well.

One final note: the title says “a beginner’s guide”, but should be read with two different interpretations: one is (possibly) you, who is just getting started with creating an online service, and the other is me, sharing my experience with jumping into these deep water a couple of months ago.  If you like what you read, you’re welcome to comment, if you see me making horrible mistakes, constructive criticism is more than welcome.

Let’s move on.  The next post will cover the basics of setting up a functional development environment, one which will allow you to develop and instantly deploy your code to production so it is available to the rest of the world

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;
}
}
 

Sending objects to your server from jQuery using POST/PUT and accepting using Spring & Jackson

August 24, 2012 Leave a comment

I won’t cover the basics of how to do REST using jQuery and Spring/Jackson in this post, hopefully I’ll find the time to post a whole series about this, so for this post I’ll assume you’ve followed all the tutorials you found online (quite a few helpful ones, shouldn’t be a problem)

So now you have your app server setup, your controller setup, you’ve created a method that’s supposed to get the object, and a javascript that should send it, BUT it just doesn’t work.  I ran into this problem, here’s what I had setup:

I was already using $.ajax instead of $.getJSON so I could send PUT requests, which means I could influence all aspects of the request (getJSON doesn’t let you do that).  I was sending the following request:

$.ajax({
url: ‘/api/users/configuration/’,
type: ‘PUT’,
dataType: ‘json’,
data: {
  configuration: JSON.stringify(userConfiguration)
},
success: function(response) { 
}
});

where  userConfigurationwas an object holding key and value pairs, and looked like this after stringifying it: {“exposure”:6,”publicName”:1}

And I expected the following code to catch it and translate it correctly to an object:

@RequestMapping(value=”/configuration/”, method=RequestMethod.PUT)
public ResponseEntity<String> setConfiguration(
HttpServletRequest request,
@ModelAttribute(“configuration”) Configuration configuration, BindingResult result 
) {
//  … do something with it
}

Several things had to be fixed for this to work out:

first of all, my javascript had to change a bit, I had to add application/json to the request descriptions so that the server knows it needs to parse it as JSON, and I had to stop sending a key-value pair, I only had to send the object itself (so remove the configuration: part)

This made my js code look like this:

    $.ajax({
    url: ‘/api/users/configuration/’,
    type: ‘PUT’,
    dataType: ‘json’,
    contentType: “application/json; charset=UTF-8”,
    data: JSON.stringify(userConfiguration),
    success: function(response) { 
    }
    });

Next, my request handling needed to change:

I was using @ModelAttribute, which may be good for any number of things, BUT it isn’t good for what I was trying to do.  I had to use @RequestBody instead.  Also, I was passing a domain object called Configuration, but didn’t really need the whole object, just the items map part of it, so I ended up just sending that.

so my server side code changed to:

@RequestMapping(value=”/configuration/”, method=RequestMethod.PUT)
public ResponseEntity<String> setConfiguration(
HttpServletRequest request,
@RequestBody Map<String, Integer> items
){
// do something interesting with this input
}

This was tricky to solved, I looked at quite a few tutorials, questions, etc., but it took some messing about to get it all in place.  This post right here is what finally sorted it all out, you might want to go visit that guy’s post as well.