There's an incredible number of web frameworks out there. I sometimes can't help but ask myself: do we really need these many options???
Not to mention the variety of really cool languages (Groovy, Scala, Python, Ruby, Node.js, Clojure....) everyone, including myself, is eager to try!
To do that, I will use just these 2 kick-ass Java technologies:
These are quite new, but already well-established technologies, so you can expect them to just work!
I will show you how to build a Java application to provide a HTTP REST API with minimum effort.
We are going to use Jersey to implement our REST web services because it is the default implementation of JAX-RS/JSR-311. Also, due to an important technical reason: a high level of awesomeness!
Guice will be used as our DI framework because it is simple to get started with, uses (type-safe) Java code to do the bindings, and provides everything we're likely to need in a project such as this one.
The only XML we will be needing here is the Maven POM (I was tempted to give Gradle a try, but will leave that for a next post) and, in case you want to deploy your app on an existing server (instead of just bootstrapping your own, as I'll show here for our unit-tests), the web.xml file.
So, let's write some code!
Creating a simple Jersey RESTful API with Guice
First off, let's have a look at the Maven dependencies we will need.
The first one is the Servlet API. Although we will not directly use the Java Servlet API, we need it as Jersey/Guice will be using it under the hoods.
Obviously, we need Jersey itself, so we import the jersey-server artifact. We also add the Jersey-Guice dependency so we can get all of Guice's functionality in a well-integrated union with Jersey.
I am using the latest stable version of Jersey at the time of writing: 1.17.1.
Finally, we have our unit tests dependencies, which for now include only the Jersey client package (to generate API calls), JUnit4 and the Grizzly 2 web server, which is really, really fast and extremely simple to start up, perfect for us to deploy our simple app and see if things are working as expected.
Now we can get to what really matters. Let's write a REST Service, hopefully with as little boiler-plate as possible.
With Jersey, that's a breeze, as you'll see.
Although I always strive to keep things simple, I also can't stand bad design... so let's not throw good software design practices out the window just yet, and keep our application's different concerns tidily separated.
The first thing a Service needs to work is a way to get data, which basically means we need a DAO (Data Access Object) definition:
This is a generic DAO which can be used to retrieve either all of the items of a certain type T, or just a single one if we know its ID.
For simplicity, for now we will not worry about updating/saving/deleting stuff. Just reading stuff! We also don't care about the implementation of this interface... we just take it for granted that we will be able to get data from somewhere.
Now we can get to the Service class itself:
I hope you will forgive me for the apparent breach of separation of concerns I have just committed! Generating HTML directly from the service class is not a great idea, but I hope the reader will appreciate the fact that the important here is to demonstrate how to use the JSR-311 API.
Later on, we would need to modify this to actually provide pure data (in Json or XML format), which would be really simple to do with Jersey without even writing any mappings directly! But that would require use to define an Object Model, which for now, we don't really need to do...
By the way, notice our imports... No mention at all of Jersey or Guice so far! Only
It would take too much space to explain the JSR-311 specification, but I hope you can see how easy it is to write pure Java code which maps to a REST API using only annotations.
For example, the request mappings look like the following ( assuming we're running our app in localhost:8080 ):
For a detailed explanation of the specification please check the Jersey documentation.
The next thing we need to do is create our dependency injection ( Guice, in this case ) module, which will put all parts of the application together:
You may notice that now we have finally added vendor-specific code to our application. There are some Guice and Jersey classes. But this is basically the only place where we define the actual implementation of our Dependency Injection framework (Guice) and REST Web-Service framework (Jersey). Changing the implementations used would be a matter of changing only this one class (and maybe web.xml if you have one)!
This is an extremely simple module, but I think it captures well what a real-world application would look like. Being Java code, this just scales! You could have hundreds of bindings, separating them perhaps by application layer in different Java classes.
When we create the Guice Injector, we pass a
We must also bind the Service classes in the context. To do that, we use the handy Jersey
Finally, we declare that we want to serve requests to
Note that this changes slightly our mappings from the examples given previously. Now, the path specified in the Service class will be pre-pended by
The reason for me to add "services" to the path is that I wanted to allow our server to still provide static content (index.html, css, js files, etc), which would be harder if we let the GuiceContainer handle all requests.
Now we can have some fun!!! Let's run this code.
If you're like me, you don't just want to see your code running, you want to make sure it works in a number of different scenarios.
To do this, we should write unit tests...
You may think it would be a little difficult to test this... we seem to require a Web Server and a Servlet container just to get off the ground.
Well, you do need those, but it's not nearly as hard as you might think.
See for yourself below.
Here's the code required to start our Grizzly server, including configuring our Guice Module (imports omitted for brevity):
Notice that we have a test Guice module that looks really similar to the real one. This is important because we want our test to be as close as possible to our real environment. However, it cannot be the same because we need to "mock" some dependencies (the Dao in this case) which we are not testing here. Another difference is that we don't need to do the binding of the Service classes from within the ServletModule... that's because we can pass the
Now we're ready to run some tests (@Before and @Test are plain JUnit4 annotations so these tests can be run in your IDE or Maven comand-line without any setup):
Lastly, let's not forget to stop the server after each test is run.
You may also want to try hitting the Grizzly server from your browser... add a main method like this to the test class:
Then access this URL with your browser:
It seems our code is working, thanks to our unit-tests... but to be sure of that, there's only one way: to deploy it to a couple of web servers/servlet containers and hit it from an external program. After all, we haven't even used our "real" Guice module in the unit tests.
So we need to implement a Dao (I just wrote a fake dao, StuffDao mentioned above, to get some data into the Service), write a web.xml deployment descriptor file, and use curl or a browser (I wanted to use a browser to test some stuff like real HTML/style-sheets requests also work, that's part of the reason why the REST API written here actually provides HTML instead of XML or Json) to manually verify the web app can indeed be deployed to any web server/servlet container. If you want to automate this kind of test, you may want to check out SoapUI, which allows you to easily write functional tests which can verify your actual production environment.
The implementation of a fake Dao is left as an exercise to the reader :)
Here's the web.xml needed:
That's it for the web.xml file. Really... forever... you will never have to change this file again unless you want to specify some static resource (welcome-file-list, error-page etc). Because the resources are all managed/configured in the Java code, the XML file is used just to make the server happy.
Now to deploy it to a Jetty server, for example, you can add this snippet to your POM:
After doing this, you get the application running in Jetty by typing the following:
Impossible to get any simpler.
Knowing how popular Tomcat is, you probably want to also try your app in it.... easy! Supposing you have a Tomcat instance running in your local machine, just copy the war file generated by maven into your Tomcat's webapps directory and you're done. Tomcat will hot-deploy it for you, no re-start required.
That's it for now!
I hope you enjoyed reading and had as much fun as I had writing it.
We saw how easy it is to write a web service using Jersey, and gluing different parts of the application together with Guice.
As a side-note, you may be interested to know you can actually access an automatically-generated WADL of your API by running the app in your server of choice (as shown above) and hitting this URL:
This can be extremely useful! You can use this WADL in your functional and load tests later. You can use SoapUI/LoadUI for those! Maybe I will write about that some time... but I must mention that both tools are developed by my employer Smart Bear (I currently work in the LoadUI team).
The code is on Github:
Please leave your comments below!