Throwing a party without a container

Throwing a party without a container

Michal Gebauer | August 27, 2018

OK, so there we have some Servlet container, some EJB container, Spring container, this container, that container... Cool, everyone uses container, but why? Can't we just make class instances by ourselves? To prove it I decided to make a party and I'll do it in an old fashioned way without any help of container.

Let's throw a party

I will focus just on one person, as to make the example simple. Meet my friend, ordinary party goer, Bob:

class Bob implements InvitedBuddy {

  @Override
  public void partyTime() {
    partyService.joinParty("What's up guys?");
    snackService.gimme("burger");
    barService.canIHave("beer", 1);
    barService.canIHave("vodka", 1);
    barService.oneMorePlease();

    socialService.makeAJoke("A dyslexic man walks into a bra.");
    barService.oneMorePlease();
    // beginning of the end
    socialService.huntForGirls();
    barService.canIHave("Whatever but fast", Integer.MAX_VALUE);
    socialService.makeAJoke("..."); // you really don't want to hear this one

    RuntimeException up = new AlcoholOverflowException("blarghhhh");
    throw up;
  }
}

Brief examination:

  • Bob joins the party and says hello - so we'll need authentication.
  • He drinks an alcohol. OK, it's legal for Bob but what about the others? - authorization added.
  • Can't judge, but seems after several calls to barService there might be a case when something is thrown, e. g. en Exception - would be nice to involve transactions.
  • And last but not least, I'd like to keep track of everything that is happening at the party - let's put logging in place

Security

We want to have private party therefore every service call must require fully authenticated and in case of barService also authorized users. Let's start with a very very simplified login mechanism:

public class PartyService {
  // imagine constructor and other stuff here..

  // login to party
  public String joinParty(String hello) {
    // try to recognize who is talking to you
    Friend friend = friendRepository.findByVoiceAndFace(hello, faceScan);

    // unknown people shell not pass
    if (friend == null) {
      throw new HeyManWhatAreYouDoingHereException();
    }

    // generate and remember unique ID for your friend
    String partyId = UUID.randomUUID();
    partyMap.put(partyId, friend);

    // pass your friend ticket he will use to
    // call service methods
    return partyId;
  }

  // Here is how to check if someone is allowed to be at party
  public Friend whoIsThisGuy(String partyId) {
    Friend friend = partyMap.get(partyId);
    if (friend == null) {
      throw new HeyManWhatAreYouDoingHereException();
    }

    return friend;
  }
}

Now we have the authentication for people joining our party. Everyone who comes will receive a ticket to avoid unnecessary re-authentication and will show it to stuff when he visits the snack or bar service:

public class BarService {
  // ... omitted lines of no interest

  public Beverage canIHave(String partyId, String type, int amount) {
    // Check if he is who ho he pretends to be
    partyService.whoIsThisGuy(partyId);

    // OK, no Exception was thrown - verified, handle his request
    // ...
  }
}

public class SnackService {
  // ... omitted lines of no interest

  public Snack gimme(String partyId, String type) {
    // Check if he is who ho he pretends to be
    partyService.whoIsThisGuy(partyId);

    // OK, no Exception was thrown - verified, handle his request
    // ...
  }
}

Did you spot the differences in the services' methods? No? That's right since there is not any. Every service method in our party:

  • must have partyId argument
  • must verify the caller before the request is handled

What we got here is code duplication and certainly code pollution - imagine we plan to have also music service, game service, darts service... What we want here is to get rid of boilerplate code and focus only on our party business.

Our little security verification code spreads all over our application and in programming terminology it would be called an aspect. And how to deal with aspects? Well, these are best addressed by Aspect-Oriented Programming (AOP). In a nutshell, to organize such scattered code you need to create a rule which says in which classes and methods you want to call your aspect. That way you can fully remove your repetitive code lines and have it just in one place.

Warning, spoiler follows: All of the points I put down at the beginning (security, transaction, logging) are very good candidates for AOP and would be solved in very similar way as I am going to deal with authentication. Therefore, for the sake of you precious time, those will not be covered in my post.

But let's go step by step.

Forget tickets, use wristbands

We don't want people at our party to care about tickets whenever they need something. That would spoil the fun certainly. I will store the tickets on them - I will use wristbands. Can you think of any Java wristband implementation?

ThreadLocal is a storage which is unique for each thread that accesses it. I know that everyone at my party uses just one thread, we are having a standard Servlet party, therefore I will use Threads to store the party identification:

public class PartyService {
  public void joinParty(String hello) {
    // same good old code lines here as before

    // NOT NEEDED ANYMORE:
    // String partyId = UUID.randomUUID();
    // sessionMap.put(partyId, friend);

    // every guest has its own body (thread)
    // for the wristband ticket;
    partyThreadLocal.set(friend);

    // no need to return anything from this method
  }

  // we don't need partyId argument here anymore
  public void whoIsThisGuy() {
    Friend friend = partyThreadLocal.get();
    if (friend == null) {
      throw new HeyManWhatAreYouDoingHereException();
    }

    return friend;
  }
}

Fine, we are half way there. Now we don't need the partyId argument, but we still need to call the verification in all services and theirs methods:

public class BarService {
  // ... omitted lines of no interest for now

  public Beverage canIHave(String type, int amount) {
    // the caller will be identified by the thread he is using
    partyService.whoIsThisGuy();

    // ... actual method implementation
  }
}

// the same applies to other services...

Step two, method call removal

I don't want other services to do the party people verification. They might forget it, or do it wrong. Instead, I will do it myself. And how? What about wrapping services in a proxy and intercept every action they do:

  // create an instance of service to be wrapped
  IBarService target = new BarService();
  // create a proxy
  IBarService barService = (IBarService) Proxy.newProxyInstance(
      BarService.class.getClassLoader(),
      // Proxy from JDK API can work only with classes that implement interface(s)
      new Class[] { IBarService.class },
      (proxy, method, arguments) -> {
          // before every service method call verification is triggered
          partyService.whoIsThisGuy();
          // call the original method
          return method.invoke(target, arguments);
      }
  );

Ta-da! Using this approach we can get rid of all authentication logic from service classes and they can solely focus on their own business:

public class BarService implements IBarService {
  // ... other methods here

  @Override
  public Beverage canIHave(String type, int amount) {
    // this method does not even care about verification
    // it is done by me

    // method implementation
  }
}

// the same applies to other services...

What we achieved here is that if we apply similar logic to all other issues on our list (authorization, transactions, logging) we will get very clean code that is much easier to read, develop, maintain and test and is not tangled with repetitive code that relates mainly to infrastructure.

Conclusion

And now is the right time for a moment of a reflection. How did the code transform?

For my solution to be feasible

  • I need to be the one who constructs services' instances
  • I intercept and manage code flow of the services

Which means I am now the one who fully controls the party. More precisely, what happened here is an Inversion of Control, so called IoC or someone might call it Container pattern. And the bottom line is, I reinvented the wheel.

Container is not imaginary black box that just does something. It's a real code that was created for you to make your life as a programmer easier. Had I started from the beginning with Spring and used its capabilities I would have my whole party done by now.


The story, all names, characters, and incidents portrayed in this production are fictitious. No identification with actual persons is intended or should be inferred. Especially, barService() has nothing to do with famous foo() and bar() actors.

Do you like this post? Share it ;-)

My recent posts:

Secure your GraphQL with Spring AOP

As I wrote in my previous post ( How GraphQL beats REST when I am hungry ) GraphQL has only one endpoint and that means our security configuration can…

How GraphQL beats REST when I am hungry

REST web services proved to be solid standard for communication and became easy way to expose server interfaces to clients. To introduce them into…

My offered Courses

Java

Java's been here for ages and is mature, stable language with huge community, standards and third party libs.

Javascript

Javascript is becoming the most popular programming language. Since Nodejs introduction it expanded everywhere.

Spring

Java enterprise framework which helps you to create full production ready application in amazingly short time.

React

A javascript library made by Facebook and used by half of the modern pages on the internet. It is my personal favourite for frontend development.

jQuery

A library which used to be the only choice for front-end development in javascript. It is still used by plenty of (not only legacy) applications.