Prime-UI, JAX-RS with Jersey and Gson on Oracle Cloud
The Oracle Cloud is around everywhere these days. It had a rough start with Larry denying the need for a cloud for a very (too) long time and some very early announcements and a very bad availability after last year’s Open World nobody seems to be interested anymore. But for me it still has it’s hidden treasures and I believe it has a fair chance of winning it’s customers. Before I dive into the example which will show you how to use JAX-RS with Jersey on the Oracle Cloud Service I want to introduce you to the service a little bit. Feel free to skip this first section.
What the hell is the Oracle Cloud and why do you care?
The Oracle Cloud is a marketing term. It tries to capture a couple of different services sharing a common base called the platform services. Those two basically are the Java and the Database Service. Technically this isn’t too new. We are talking about Oracle’s ‘ Cloud Application Foundation‘ which is out there since a while.
It is down at the bottom of the whole Oracle Fusion Middleware Stack (at least in the available marketing slides) and is the basic software stack that runs on the Exalogic appliances. Most relevant parts for Java developers are the Java EE 5 WebLogic Server and a load balancing solution called Traffic Director. The neat part here is, that you literally can have your personal share of a real Exalogic machine in the cloud for a fraction of the costs that even the smallest rack costs. And it is running in data centers around the world. Fully managed and including the licenses. So, with paying your monthly mite you are done with the administrative parts. And if you ever had the questionable pleasure to deal with licensing and supported platforms you know a little about the added value in it. Technically speaking the Java Service is of little interest at all. EE 5 is outdated and even the Java SE 6 based JRockit feels like a stranger from the past with all the new features in Java SE 7 and the end-of-public-updates policy for SE 6. But I still consider it a good start and I am very looking forward about having latest WebLogic 12c and a decent Java 7 in the cloud.
WebLogic Server and JAX-RS
Do you remember the ancient days? Java EE 5? Running around with the latest EE 6 specification since a couple of years now it feels like you have to drive the car you had as a student again. Believe it or not: JAX-Rs wasn’t part of EE 5 at all. And this is exactly the reason why JAX-RS doesn’t run out of the box on the Oracle Java Service. But you might know that the Weblogic team is very aware of the fact that they are running late with EE adoption and so they are rolling out features which will be included into the base server with the next specification version bit by bit to earlier versions. The same happened with JAX-RS back in early 2011. Since 10.3.4 you’ve been able to facilitate Jersey as JAX-RS implementation by simply adding a library dependency or packaging it to your application. This also works for the Java Service. Simply start a new Maven project in your favorite IDE (might be latest NetBeans 7.3 which is hot off the press) and add
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.9</version> <scope>provided</scope> </dependency>
Jersey as a dependency with scope provided. Another pointer is the Java Version you should compile against. Make sure SE 7 doesn’t slip in somewhere and set the mavven compiler-plugin to use source and target version 1.6. Sad as it is … Next thing to add is the weblogic.xml library ref for Jersey:
<library-ref> <library-name>jax-rs</library-name> <specification-version>1.1</specification-version> <implementation-version>1.9</implementation-version> </library-ref>
Which simply tells the container to add this to the class-loader. Typically you would have to deploy it to your domain first. But believe me: It is already there and you simply can use it. If you are using NetBeans and you start with the new ‘RESTful Web Services from Patterns’ wizard you might end up with a couple of more (unneeded) dependencies but this would save you from adding the Jersey configuration to your web.xml which should look like the following:
<servlet> <servlet-name>ServletAdaptor</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <description>Multiple packages, separated by semicolon(;), can be specified in param-value</description> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>net.eisele.primeui.cloud</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ServletAdaptor</servlet-name> <url-pattern>/webresources/*</url-pattern> </servlet-mapping>
And simply registers the REST servlet together with the package scanning path for your annotated implementation. Choose whatever mapping you like. Following this example closely you should be aware, that I’m going to hard-code the URL to the service in JavaScript later. Watch out for the ‘/webresources’ part.
Adding some JSON
You for sure noticed the et.eisele.primeui.cloud package reference. Let’s look at the class:
@Path('countries') public class RestResource { //... @GET @Produces('application/json') public String getJson(@QueryParam('query') String query) { String[] raw = { 'Albania', 'Algeria', //... }; List<ValueHolder> countries = new ArrayList<ValueHolder>(); for (int i = 0; i < raw.length; i++) { countries.add(new ValueHolder(raw[i])); } Gson gson = new Gson(); return gson.toJson(countries); } }
public class ValueHolder { public ValueHolder() {} public ValueHolder(String label) { this.label = label; this.value = 'v_' + label; } private String label; private String value; }
This basically contains a String[] of countries. Each entry gets converted to a ValueHolder object and added to an ArrayList which gets converted to JSON with the help of Google’s gson library. This is the second dependency we need to include with the pom.xml
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.2.2</version> <scope>compile</scope> </dependency>
Make sure this is packaged with your application by using the compile scope. Mostly done now. You noticed the @QueryParam(‘query’). I build some more logic around selecting the right entries from the String[] to decide which ValueHolder to return. For the complete example refer to the RestResource on github. Now we are in need of a nice front-end.
Prime-UI to the rescue
Everybody is talking about JavaScript these days and I thought it might be a good way of showing off some of the things possible with latest Primefaces offspring called Prime-UI. Those guys do a great job pushing out their already well known and widely used JSF library PrimeFaces to the jQuery world by providing a widget library. Get everything you need from the PrimeFaces website by downloading the prime-ui zip file. If you started with a web project in NetBeans and you did not add JSF you end up by having a nice little jsp file in the webapp folder. Open it and make some changes and tweaks to it. The most important ones are the HTML5 doctype declaration and the needed JavaScript imports:
<%@page contentType='text/html' pageEncoding='UTF-8'%> <!DOCTYPE html> <!-- header, title, all the other stuff you need --> <!-- jQuery --> <script src='js/vendor/jquery.js'></script>
<!-- jQuery UI --> <script src='js/vendor/jquery-ui.js'></script>
<!-- Prime UI Core --> <script src='js/core/core.js'></script>
<!-- Prime UI Input Text --> <script src='js/inputtext/inputtext.js'></script>
<!-- Prime UI Autocomplete --> <script src='js/autocomplete/autocomplete.js'></script>
The Auto complete example binds an input text field to a backend and gives you type-ahead features. Lets assume you have the rest service above running you now simply add the following JavaScript to your head section:
<script type='text/javascript'> $(function() { $('#remote').puiautocomplete({ effect: 'fade', effectSpeed: 'fast', completeSource: function(request, response) { $.ajax({ type: 'GET', url: './webresources/countries', data: {query: request.query}, dataType: 'json', context: this, success: function(data) { response.call(this, data); }, error: function(jqXHR, textStatus, errorThrown) { console.log(textStatus, errorThrown); } }); } }); }); </script>
And add the input tag to your body section of the page:
<input id='remote' name='remote' type='text'/>
That is all you have to do. One little remark. If you are going to deploy the app as it is, you will be prompted with a login screen in front of it. In order to open it to the public you have to add an empty
<login-config/>
element to your web.xml. Now go on and add the cloud to your IDE and deploy the application to your trial instance. If you are using my github sources, it should look like this:
depending on the query it returns the more qualified results. Going the postman way it looks like this:
Take away
I hope, you didn’t expect this to be kind of rocket science at all. It is a basic post along the lines of what most of the WebLogic server developers might have know already. This is one of the biggest advantages but also a big disadvantage of the Oracle Java Cloud Service. If you know WebLogic you are most likely going to love it. If you are on the Open Source side of things you might run into issues that are well known to the Oracle Middleware guys but not to you. EE 5 isn’t that complete than EE 6 and EE 7 will only be slightly better in closing the vendor specific gabs between all the different implementations. But again: This isn’t something new for you, right? Now go: Give it a test-drive and share your experiences! Looking forward reading about them!
Reference: Prime-UI, JAX-RS with Jersey and Gson on Oracle Cloud from our JCG partner Markus Eisele at the Enterprise Software Development with Java blog.