No more static methods

Static methods

Tired of those static methods that make your unit test skills look bad? You want to get rid of those hard to mock static methods? You refuse to use PowerMock? Here's a simple way of replacing static methods with non-static methods without breaking your entire code base (or worse someone else's code base).

Example

Let's say we've got the following service class (PostService) which depends on a class with a static method (PostDao).

public class PostService { 
  
  public List getPostsOf(User user){ 
    if(user != null){ 
      return PostDao.findByUser(user); 
    } 
  
    throw new UserNotLoggedInException("User not logged in!!!"); 
  } 
}
public class PostDao { 
  
  public static List findByUser(User user){
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
}

The simplest way would obviously be: remove the keyword "static", watch all the code (that call this method) brake, fix it and off you go. That sounds easy. But what if you don't want to replace the references to the static method in a big-bang fashion, for whatever reason. How would you go about that? Here are the steps:

  • Wrap the static method in a non-static method
  • Replace the reference to the static method with the instance method

Wrapping the static method

This is the easiest part. Create an instance method, in the class with the static method, with the same signature and return type. Call the static method from within the instance method.

The class would look like this

public class PostDao { 
  
  public static List findByUser(User user){
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
  public List findBy(User user){ 
    return findByUser(user); 
  } 
}

Now you're all set to proceed with the second step.

Replacing the references to the static method

Wrapping the static method allows you to replace all the references whenever you want. This enables you to repair your code base at your own pace.

If you want to repair the PostService you should do the following:

  • Create a No-args constructor (for backwards compatibility)
  • Create a constructor which accepts a PostDao instance, for easier testing/mocking purposes
  • Replace the static method call with an instance method call

When all the work is done, the result would be as follows

public class PostService { 
  
  private PostDao postDao; 

  @Deprecated 
  public PostService(){ 
    this(new PostDao()); 
  } 

  public PostService(PostDao postDao) { 
    this.postDao = postDao; 
  } 

  public List getPostsOf(User user){ 
    if(user != null){ 
      return postDao.findBy(user); 
    } 

    throw new UserNotLoggedInException("User not logged in!!!"); 
  } 
}

The PostService will still work, because of the No-args constructor, and does not break any existing code referencing the PostService. The constructor which accepts the PostDao instance allows for easier testing/mocking. You can annotate the No-args constructor with the 'Deprecated' annotation. This shows the intent of removing the no-args constructor somewhere in a future release.

If there are no more references to the static PostDao method you can move the logic which resides in the static method into the instance method and delete the static method. Furthermore, if there are no more references to the no-args constructor in the PostService you can remove the deprecated constructor. This can all be done in a non-big-bang-kinda-fashion...

End result

public class PostDao { 
  public List findBy(User user){ 
    // Some very interesting code for retrieving posts of a given user 
    //.. 
    //.. 
    //.. 
  } 
}

SSH Bad Permissions in Windows

SSH trouble in Windows paradise

Yesterday i was fiddling with Docker en Jenkins. I was busy trying to assemble a cluster of 2 CentOS 7 servers running in docker containers. I wanted to figure out how to set up a Jenkins master and slave scenario. One of the things you need to do in order to configure it is, setting up SSH access with public and private key pairs.

When I was ready to SSH into the machine I stumbled upon an error. I couldn't connect from my Windows 10 host to my CentOS server/container. That's strange because I could connect to the CentOS server with that same key from a Linux box. My .pem file on my Windows box had "Bad Permissions".

Alright, alter some permissions... That should not be so hard! This is what you have to do on Windows in order to get those permissions right. Right click on the .pem file and go to the 'Security' tab on 'Properties'. You would probably see something like this:

The trick is to only give yourself explicitly full control over the .pem file. Click 'Advanced' and 'Disable inheritance'. When Windows asks, click 'Remove all inherited permissions from object'. Click 'Ok'. No one has permission to do anything with that file. So, all you have to do now is add your user and assign 'Full control' privileges.

The end result is a .pem file that your SSH server likes!

I hope this will save you some time figuring out what to do...


Building for readability

Spot the difference

Readability of code should not only be pursued in production code. It is also very important to make your (unit)tests as readable as possible. One of my favourite patterns for enhancing readability is the builder pattern.

Take a look at the following code snippet of a unit test. As you will notice, the creation of the User object involves a lot of lines. Not also does it involve a lot of lines of code, it isn't quite readable as I would like it to be.

    ...

    @Test
    public void not_return_any_tweets_when_user_is_not_followed_by_logged_in_user() throws UserNotLoggedInException {
        tweetService = new TweetService(PIERCE, tweetDAO);

        User james = new User();
        james.setName("James Bond")
        james.addFollower(ROGER);
        james.addFollower(TIMOTHY);
        james.addFollower(DANIEL);
        james.addTweet(ABOUT_ACTORS);
        james.addTweet(ABOUT_MOVIES);

        assertThat(tweetService.getTweetsByUser(james).size(),is(0));
    }

    ...

Don't get me wrong, the code above is quite readable but if you take a look at the code below it reads a bit more nicer. It is almost like you are reading a normal sentence. That is what the builder pattern gives you. Fluent readable object creation.

    ...

    @Test
    public void not_return_any_tweets_when_user_is_not_followed_by_logged_in_user() throws UserNotLoggedInException {
        tweetService = new TweetService(PIERCE, tweetDAO);

        User james = aUser()
                        .named("James Bond") 
                        .followedBy(ROGER, TIMOTHY, DANIEL)
                        .withTweets(ABOUT_ACTORS, ABOUT_MOVIES)
                        .build();

        assertThat(tweetService.getTweetsByUser(james).size(),is(0));
    }

    ...

Note that the static import is used in order to call aUser() without the class name. Otherwise it would read Userbuilder.aUser(). The latter is also readable but the first one reads a bit more natural. (But that is nitpicking 2.0)

Getting it done

How does that pattern work, you might think. The basic idea is that while creating the object the the builder saves all the data and when all is ready the build() method is invoked and at that point the object is created.

In order to chain the methods together all the methods that collect data (e.g. named an followedBy) should return the Builder object itself.

Creating the builder contains three steps:

  • Creating the static method which returns a new Builder (opening method)
  • Creating the data collecting methods which return the builder (intermediate methods)
  • Creating the build method (terminating method)

Opening method

This static factory method (not to be confused with the Factory design pattern) is added pure for enhanced readability.
If we didn't have this static method the builder would has to be invoked something like this: new UserBuilder().followedBy(...). The intent is less clearer as opposed to using the static factory method.

    ...

    public static UserBuilder aUser() {
        return new UserBuilder();
    }

    ...

Intermediate methods

In order to chain the methods each intermediate method should return itself. Notice the usage of the varargs parameter. By using the varags we delegate the adding of followers one-by-one to the builder itself. This is also the case for the withTweets(...) method.

    ...

    public UserBuilder followedBy(User... followers) {
        this.followers = followers;
        return this;
    }

    ...

Terminating method

For actually creating the User object, the builder must have a terminating method. This method is responsible for creating the actual object needed by the client. In this method we see that every piece of data, collected by the intermediate methods, is transferred to the User object and finally the constructed user is returned to the client.

    ...

    public User build() {
        User user = new User();
        setNameFor(user);
        addTweetsTo(user);
        addFollowersTo(user);
        return user;
    }

    ...

The full builder

public class UserBuilder {
    private String name = "";
    private User[] followers = new User[]{};
    private Tweet[] tweets = new Tweet[]{};

    public static UserBuilder aUser() {
        return new UserBuilder();
    }

    public UserBuilder named(String name) {
        this.name = name;
        return this;
    }

    public UserBuilder followedBy(User... followers) {
        this.followers = followers;
        return this;
    }

    public UserBuilder withTweets(Tweet... tweets) {
        this.tweets = tweets;
        return this;
    }

    public User build() {
        User user = new User();
        setNameFor(user);
        addTweetsTo(user);
        addFollowersTo(user);
        return user;
    }

    private void setNameFor(User user) {
        user.setName(name);
    }

    private void addFollowersTo(User user) {
        for (User follower : followers){
            user.addFollower(follower);
        }
    }

    private void addTweetsTo(User user) {
        for (Tweet tweet : tweets){
            user.addTweet(tweet);
        }
    }
}

Conclusion

According to Wikipedia "The intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern that occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.

I would like to add that the builder pattern can also be used for enhanced readabilty and easier creation/validation of objects.


Set up an SVN Server on a Synology NAS

Subversion is an open source version control system often used for version control in an IT development environment. In this how to I am going to show you how to set up an SVN Server on a Synology NAS through the Synology Disk Station Manager (DSM 4.2) web page.
 

Preparations

What we need in order to set it up:

  • A Synology NAS running in your LAN
  • Access to your NAS via the Synology DSM web page
  • 10 minutes of your time

 

Installing SVN Server

To set up a SVN Server only requires two actions. First you have to install SVN Server on your Synology NAS. Log in to your NAS and head over to the "Package Center". Search for SVN Server and install it. This should take about five minutes. Which leads us to the second - and last - step.

After successfully installing SVN Server, it is time to create a new repository location. Open SVN Server and add a new repository (Control Panel -> SVN Server -> Add). On the General tab click Add. Type in a new repository name and a realm. All we have to do now is add a user for accessing the repository. This can be done in the User tab.

Set up a SVN Server on a Synology NAS
Configuring the repository...
Set up a SVN Server on a Synology NAS
Adding a user...

 

The result

Set up a SVN Server on a Synology NAS

An up and running SVN repository in a LAN. Accessible for the created user via URI "svn://xxx.xxx.xxx.xxx:3690/projects". 3690 is the default port for SVN Server.

All in all it took me ten minutes to set up a SVN server and start committing data to it. In the next "How to", I will show you how to set up a SVN client in Eclipse Luna...

More info
More info on Subversion (SVN) can be found at subversion.apache.org.
For more info on Synology in General and Synology Disk Station Manager in particular visit synology.com