Using HK2 in a basic Jersey Web Service

At work, I do a lot of backend work in C#. I’ve always felt that seeing other frameworks are good to get better. This time, I decided to go with Java, more precisely Jersey.  I’ve come to love dependency injection in .NetCore, therefore using HK2 in a basic Jersey Web Service was first on my play list.

Project bootstrap

I decided to go for a really simple project and bootstrap it using Maven:

This generates a simple server with a single HTTP GET endpoint.

Playing around

I then started adding a few controllers and workflows. Using this setup, each controller needs a handle to a workflow. Of course, this is easier done using dependency injection. I did not want to reuse what I did for my other project, so I explored what Jersey proposes. Quickly I found that Jersey comes with HK2 all ready, so I glimpsed the HK2 introduction and started playing with it.

I added a few @Contract , @Service  and @Inject , and tried it out. Before even waiting for the results, I knew that something was missing. It was either major magic underneath or I was not defining which service I wanted to use for each contract.

And as expected, I got a nice little exception:  org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection [snip]

Fixing it

After a tiny bit of googling and better reading on my part, I figured the issue: you simply need to register a binder into your server configuration. More explicitly, you’ll need the following:

Final part is to use this configuration class when initializing your server, like so:

Sources

  • Jersey, RESTful Web Services in Java
  • HK2, A light-weight and dynamic dependency injection framework

Why I’m not using Dagger2 on my project

In order to make a Java side project of mine easier to evolve and test, I wanted to add dependency injection. After a quick lookup, I figured that Dagger2 would be a really nice little thing to add to my project. So here is why I’m not using Dagger2 on my project.

Disclaimer: this is only my opinion, Dagger2 seems really good and I’ll most probably use it in a future project where it is more suitable.

Context

My project is split into a core library (to be reused later) and the main project. Quite a bit of the library is built to be sub-classed while enforcing a certain flow, validation and features for the main project.

Experimentations

While tinkering with Dagger2, I did notice a few things that were annoying to me:

  • No support for inheritance;
  • Complex integration with Eclipse (through Gradle);
  • Lack of simple examples

The lack of support for inheritance was already a blocker for me. Still, in order to get a good feel of the library, I decided to try to get around the limitation. Doing so required me to manually inject into my super-class when building my instances. This exposed quite a bit of things that had no right being exposed to the subclass. It also made the code harder to evolve since I would need to update my sub-classes every time I add a dependency into my core library. That would require an API break where there should be none.

I’m new to the whole Gradle ecosystem, and getting it to work correctly with Eclipse was already quite a task (see this post and that post). Integrating Dagger2 into all of that proved to be really painful. I probably missed something somewhere, could simply be missing a bit of documentation somewhere. I do plan on trying to make it work again in the future and document how to get it all running.

Finally, Dagger2 allows support of really complex scenarios, but, sadly, it exposes a lot of complexity when trying to do something simple. This could be due to a lack of simple examples or simply a misunderstanding on my part. One way or another, I do plan on getting back to this to figure out how to use it in simple scenarios.

Solution

In the end, I decided to go with something extremely simple that supports only what I need:

  • Global Singletons;
  • Introspection is used only to inject the dependency manager in the constructor (if needed)

In the end, usage looks roughly like:

I did add a few other helpers in there. Nothing too fancy, just quality of life.

Interacting with Google Tasks on Android

Since I’ve been playing with Google Tasks, I wanted to look at my task from my Android phone. Sadly, all the application I could find were using a lot more permissions than I like to give. Therefore, I decided to look into why all these permissions are needed. This will be a little tutorial on interacting with Google Tasks on Android.

Disclaimer: I have not yet published an application using this, so it is possible that something is missing. I will update this post as soon as I have more information (or remove this disclaimer if nothing more is needed).

Project Setup

There are two basic files that need modification in order to be able to use Google Tasks on Android.

The first files you need to modify is the AndroidManifest.xml file. You will need to add the android.permission.INTERNET by adding the following line:

This permission is used to allow your application to connect to the Internet.

The second file that needs modification is the app/build.gradle file. Adding the following lines to this file will add the needed libraries to your project’s dependencies:

Do note that I had to force the version of com.google.code.findbugs:jsr305 in order to fix a dependency issue.

Google API Setup

Configuring the Google Backend services for Android is a little bit different from doing so for desktop applications. I already did a quick tutorial on doing the configuration for Android here.

Handling the user’s credentials

In order to get the user’s credentials, you will need to ask for his permission. I went the easy route and asked directly for read/write access to Google Tasks, but you can get the list of scopes that can be used here. In order to be able to get the user’s token, you need to add the requestEmail permission.

Basically, the way the permission flow works is:

  1. Build a sign-in intent (with the desired permissions);
  2. Ask the system to fulfill the intent and wait for the response;
  3. Process the response

The code is quite straightforward:

Initializing the Google Tasks API

In order to initialize the Google Tasks API, you will need 3 things:

  • A JSONFactory
    I went with an instance of com.google.api.client.json.jackson2.JacksonFactory simply because it was there and worked
  • HttpTransport
    Depending on the Android version you are targeting, you must use a different class. Using AndroidHttp.newCompatibleTransport() makes this selection transparent.
  • The user’s credentials

Interacting with Google Tasks on Android

Once you got the Tasks Service in your hands, interacting with it is the same as doing so in Java. Since I’ve been using API 23, I can’t use streams like I used in my java example. Therefore, I did two little helpers ( TaskList findTaskList(TaskLists tasklists, String title)  and Task findTask(Tasks tasks, String title)).

Creating a task list

Finding a task list

Creating a task

Finding a task

Updating a task

Completing a task

Handling a large number of return values

Like any good online service, Google Tasks API handles a large number of values using pagination. By default, most APIs will return a maximum of 100 results. You are allowed to change this value, but in order to get good performance, you should not put it bigger.

Basically, the way to handle pagination is: do your normal call, check if you got a page token and if you do you know there are more results waiting. You can then call the API again with the page token in order to get the next result set:

Sources

Interacting with Google Tasks using Java

I already did a post giving an overview of interacting with Google Tasks using Ruby, but with the change in scope of my project, I now need to do the same in Java. Therefore, here is an overview of interacting with Google Tasks using Java. Do note that this probably won’t work on Android, it is meant to be used from Java Desktop editions.

Project Setup

Using gradle, the project setup is quite simple:

Google API Setup

In order to access Google Tasks using Java, you will need to use Google’s OAuth. Google’s OAuth uses what they call client secrets file. These files contain all the information needed to access the selected services.

To get a client secrets file, you can follow my other post.

Handling the user’s credentials

This project is my first Java project since a long time ago. I quickly remembered how painful it can be to play with the interface/abstract class hell. You have to instantiate 20 different things before calling anything and selecting the right implementation, or even simply finding an implementation, is sometimes tricky. Here, I selected the following implementations:

  • JsonFactory: com.google.api.client.json.jackson2.JacksonFactory, it was there and worked, so I used it;
  • HttpTransportcom.google.api.client.http.javanet.NetHttpTransport, according to the API’s documentation “NetHttpTransport is based on the HttpURLConnection built into the Java SDK, so it is normally the preferred choice“;
  • DataStoreFactorycom.google.api.client.util.store.FileDataStoreFactory, this implementation will store the tokens in a file (Ok … multiple files …). In my case, it will be in a directory called tokens in the current working directory;

Here is the authentication code I used. It will take care of caching the tokens, opening the browser if a new token is needed and getting the result token.

Initializing the Google Tasks API

In order to use the Google Tasks API, you need to build the service. Doing so requires most of the things that were initialized in the previous section:

Interacting with Google Tasks using Java

Creating a task list

Once you have all the boilerplate done for the initialization of the API and the service, creating a tasklist becomes quite easy:

Finding a task list

The Google Tasks API only allows you to search by tasklist ID, not a title. This ID is automatically generated and therefore not really easy to use. The easiest way to find a task list is to list all task lists and find the one you are looking for in there:

Creating a task

In order to create a task, you first need a tasklist. Once you got that, creating the task is easy enough:

Finding a task

Just like finding a tasklist, you can’t directly search by task title. Therefore, you need to go iterate over the full list to find the one you are looking for:

Updating a task

Once you have a task (and a tasklist) in your hands, updating most of its fields can be done directly on the Task instance. The following example updates the due date of a task:

Completing a task

Just like updating a task, completing it is quite easy: set its status field to completed:

Handling a large number of return values

Like any good online service, Google Tasks API handles a large number of values using pagination. By default, most APIs will return a maximum of 100 results. You are allowed to change this value, but in order to get good performance, you should not put it bigger.

Basically, the way to handle pagination is: do your normal call, check if you got a page token and if you do you know there are more results waiting. You can then call the API again with the page token in order to get the next result set:

 

Sources