JSON endpoint in Playframework with one annotation

Playframework 1.2 is really nice in getting things done quickly. Today I’ve had to add JSON endpoints
in my application that would render exactly same models as html pages on same URLs.
I could have done it manually, but there are some AOP mechanisms you can use in Play that may be useful here.

So I’ve implemented some simple aspect that would cut trough requests and return JSON instead
of rendering html templates:

public class JsonPointcut extends Controller {
    
    @After
    @Catch(TemplateNotFoundException.class)
    static void renderModelsJson() {
        if (isJsonRequest()) {
            Scope.RenderArgs renderArgs = Scope.RenderArgs.current();
            Map<String, Object> outputObjects = new HashMap<>();
            for (Map.Entry<String, Object> entry : renderArgs.data.entrySet()) {
                if(entry.getValue() instanceof JPABase) {
                    outputObjects.put(entry.getKey(), entry.getValue());
                }
            }
            renderJSON(outputObjects);
        }
    }
    
    @Util
    static boolean isJsonRequest() {
        Http.Header accepts = request.headers.get("accept");
        return accepts != null && "application/json".contains(accepts.value());
    }
}

It will simply override render statements in controllers annotated with @With(JsonPointcut.class)
and render all parameters that would usually go into html template and extend JPABase (base class of Play entities) in form of JSON map.
Just remember to use Accept:application/json in request HTTP header.

Simple and beautiful.

Update:

Just uploaded a bit more fail safe and powerful version as Playframework module. Check my company GitHub account:
https://github.com/transition-technologies/JSONEndpoint

No documentation yet, but javadocs on controller.JsonRenderer class describe pretty much everything. Will add some later on.

Web Services – Java client

Robert Mac asked some time ago for Java client for my old post here: Web Services in Ruby, Python and Java. So here it is (sorry for the delay). Simplest possible solution, no jars or IDE needed. Just plain Java 6 JDK.

First we have to generate proxy classes for our Web Service (you need to pass WSDL location, as URL or path to file):

wsimport http://localhost:8080/WSServer/Music?wsdl

wsimport is in /bin folder in your JDK.

Now let’s use them:

public class WSClient {

    public static void main(String[] args) {
        Music music = new Music();
        String[] artists = music.listArtists();
        for (String artist : artists) {
            System.out.println(artist);
            Song[] songs = music.listSongs(artist);
            for (Song song : songs) {
                System.out.format("\t%s : %s : %d%s\n", new Object[]{song.getFileName(), song.getArtist(), song.getSize(), "MB"});
            }
        }
    }
}

Now compile it and execute with classes generated by wsimport in classpath.
This is all. Simple, isn’t it?

Generating Web Services server using Axis2

Everybody knows that you can easily generate Web Services client classes just from WSDL file in Java.
You even have such tool (wsimport) in every JDK distribution (check JDK_HOME/bin). It handles
all XML data types to Java mapping and generates all complex types needed. You even have such tools
for many other programming languages. Scripting languages don’t need them at all, they generate them
on the fly.

But what to do if you have to implement WS client and only thing you can get from your customer
is a WSDL file? Of course you can generate client classes from it. But how to test it? (You wouldn’t give
untested code to your customer, won’t you?)

Continue reading…

Web Services in Ruby, Python and Java

Today I’ve had to prepare some examples to show that web services are interoperable. So I’ve created a simple web service in Java using Metro and launched it on Tomcat. Then tried to consume them using Python and Ruby. Here’s how it all finished…
Continue reading…

%d bloggers like this: