Multi tenant approach with Java 8 in a Play project.

In my current project, I had to implement a multi tenant approach. There is nothing new about this, I have to check if current user is the owner of some resource. And I have to do the same thing across other several actions. The best way to do this, is to build an Action composition and compose all actions with it. So, let’s say we have this route:

   /admin/users/update/:id

Now, when we try to access this resource, our interceptor will be invoked:

    @Override
    public Promise<SimpleResult> call(Context context) throws Throwable {
    	RoleType currentRole = CurrentUser.role();

    	Long currentLoggedUserId = CurrentUser.id();
    	Long clientParamId = //get parameter here;
    	for (RoleType roleType : rolesAllowed) {
    		if(roleType.acceptsRole(currentRole)
    		&& roleType.acceptsTenant(currentLoggedUserId,clientParamId)){
    			try {
    				return delegate.call(context);
    			} catch (Throwable e) {
    				throw new RuntimeException(e);
    			}
    		}
    	}
    	return Promise.<SimpleResult>pure(
    	  Controller.unauthorized("You are not allowed to see this page"));
    }

And now we have a problem. How do we extract the client id from the url? The first thing that I thought was: All parameters are in request data…

  Long clientParamId = Long.parseLong(context.request()
                     .queryString().get("clientId")[0]);

Unfortunately, Play does not provide this information anywhere :(, if you try to run this code, you will get a NPE. This probably happens because in Scala version you would not have this problem, in there you compose actions in a different way. Basically you can invoke the “call” method from your controller’s action, using the functional support provided by the language instead of using annotation. You can see more here(link). To solve my problem, I used the same approach. Let’s see:

    public static Result updateForm(final Long id) {
    	return new RoleAction(User.class, id, RoleType.ADMIN,RoleType.TENANT)
    			.call(new Function0<Result>() {
    				public Result apply() throws Throwable {
    					User user = JPA.em().find(User.class, id);
    					Form<User> filledForm = userForm.fill(user);
    					return ok(views.html.admin.users.update_form.render(filledForm));
    				}
    			});
    }

It is a little bit verbose, no doubts, but I needed to delivery this feature :). And now I can access all parameters that I need. Just to make the job less annoying, I’ve created a Eclipse template that allows me just write “roleAction” and the code template is generated automatically :).

The good thing about this approach is that, now with Java 8, we can change this implementation in order to use the new lambda support :). Play with Java8 is a lovely thing!

    return new RoleAction(User.class,id,RoleType.ADMIN,RoleType.TENANT)
   .call( () -> {
    	User user = JPA.em().find(User.class, id);
    	Form<User> filledForm = userForm.fill(user);
    	return ok(views.html.admin.users.update_form
    			.render(filledForm));
    });

What do you think? One nice thing here is that I didn’t need to change the original call method. When you have just one method in your interface, the new compiler understands this interface as a Functional Interface and allows you to pass lambda as a parameter. Java 8 support is enabled in Play 2.2.2 and Play 2.3.x!

Advertisements

2 thoughts on “Multi tenant approach with Java 8 in a Play project.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s