Home > Articles > A proper way for JPA entities instantiation

A proper way for JPA entities instantiation

If you read Misko Hevery’s blog you should be pretty much familiar with term testable code (and if you don’t know Misko’s blog then I strongly encourage you to visit his site). Misko divides objects into two main types: service objects and value objects. Each service object provides some set functionalities defined in application logic. Value objects are leafs of the objects’ collaboration graph. They usually encapsulate the data, that is manipulated by services. In other words, in most cases they are the model objects, the nouns that you use to describe the application logic. If you use any ORM technology (like Hibernate or Toplink) value objects will most likely be the entities of your application. And on creating the entities I would like to focus in this post. All examples will be for JPA2.0 entities, since this is standard, but the rules can be easily applied to any other ORM solution. Before we move on to the main topic, which is entities instantiation, lets take a look on how service objects are created.

Most of you probably know that for service instantiation we use dependency injection, which makes code maintainable, testable and more declarative. I suspect that most of you guys know about it, but for all non-believers, I’ve created this very simple example for consideration:

public class UserService implements IUserService {
 @Inject
 private IUserDao dao;

 @Inject
 private IFacebookWS facebook;

 public User logIn(String login, String password) {

   User user = dao.findByLoginAndPassword(login,password);
   if(user == null) {
     return User.GUEST;
   }
   return user;
 }

}

We have those three service classes (and equivalent interfaces): UserDAO for database connection, FacebookWS for communication with facebook webservice and finally UserService that binds the application logic. I use dependency injection so I don’t create any instances of my service classes explicitly. This separation of concerns (separation of usage and instantiation of given class) makes my code more declarative. You, as a other programmer of my team, see that UserService uses UserDAO and FacebookWS, but don’t know how those dependencies are instantiated. And you shouldn’t really care, all that is important is that UserService depends on dao and webservice object.

Thanks to Dependency Injection my tests are now easy to write and easy to read:


@Test
public void shouldReturnGuestUserForIncorrectPassword() {

 // given
 IUserService service = new UserService();

 IUserDAO dao = mock(IUserDAO.class);
 when(dao.findByLogin("someLogin").thenReturn(null));
 inject(service, "dao", dao);

 // when
 User returnedUser = service.logIn("someLogin",
                                   "wrongPassword");

 // then
 assertEquals(User.GUEST, returnedUser);

}

Why (beside the fact that I’m using BDD template given-when-then) tests are easy to read? Important thing is that you (as some other developer of my development team) when looking just at my test, see that to perform logIn action, only IUserDAO dependency is mocked and injected to tested UserService class.

 inject(service, "dao", dao);

This way test is documenting the class its testing. You clearly see that to perform logIn action, facebook web service is not needed. In general to understand how some method works, you can first look at created tests for given class and then (if still needed) check out the implementation. I guarantee that reading tests and implementation is far more comprehensive then just reading implementation.

You might say that to understand how logIn works you wouldn’t need really tests. Remember however that this example is trivial. Imagine class with larger set of dependencies. Self-documenting, easy to read tests, might be really really helpful for maintaining code (especially if the code is one year old and it was developed by someone who is no longer hired in your company).

Secondly, why tests are easy to write? Imagine for example what would happen if I didn’t use DI and I was just instantiating dao and service object in a constructor?


public class UserService implements IUserService {

 private IUserDAO dao;
 private IFacebookWS facebook;

 public UserService() {
   dao = new UserDAO();
   facebook = new FacebookWS();
 }

How I could then mock any of those dependencies? One could say, that I would just simply inject the mock object after constructor. But what if for example when instantiating UserDAO, the dao object is connecting to data base? How would you prevent it from happening in your tests? I believe you couldn’t do it.

Ok, so we use DI for service objects, but what about the value objects? And more importantly what about entities? For the given example, how do we create User objects? The rule of thumb is to just simply use constructors when instantiating value objects. This should not be really a suprise. Value objects are fundamentals of your application, as they mostly just gather domain specific information. They are leafs in the objects relation graph, thus they will most likely be never mocked.

So (following this rule) in our example, User class should looked more or less something like this:

@Entity
public class User {

 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password,
             String facebookLogin,
             String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
  }
 }

Everything works fine, even despite the fact in my personal opinion calling new User(“someName”,”somePassowrd”, “someOtherName”, “someOtherPassword”) becomes hardly readable and maintainable. However implementation is still valid. But what shall we do if we get a new requirement for our application:

@Test
public void shouldDefaultFacebookValuesEqualsEquvalentNormalValues() {
 // given
 String login = "a";
 String password = "b";

 // when
 User user = User(login,password);

 // then
 assertEquals(user.getLogin(), user.getFacebookLogin());
 assertEquals(user.getPassowrd(), user.getFacebookPassword());
}

In other words we say that login and password are obligatory in object instantiation, but facebook login and password are not – if not present during initialization, facebook login and password are same as normal login and password.
So what should we do to implement those requirements? Well I hope non of you think to do it like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password,
             String facebookLogin,
             String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
  }

 public User(String login,
             String password) {
   this.login = login;
   this.password = password;
   this.facebookLogin = login;
   this.facebookPassword = password;
  }
}

You can clearly see the code duplication. Maintaining this code would turn into a nightmare in no time. A rather well-known solution is to implement something that some programmers call “telescoping constructor pattern” (name I first encountered in Joshua Bloch “Effective Java”) . For our scenario this patter would look like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password) {
   this(login, password, login);
 }
 public User(String login,
             String password,
             String facebookLogin) {
   this(login, password, facebookLogin, password);
 }
 public User(String login,
            String password,
            String facebookLogin,
            String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
 }
}

You define constructor with minimal set of parameters (meaning parameters obligatory to object initialization). Then you continue on extending other constructors with parameters until you reach the constructor that defines them all. This works fine for small set of parameters, but can quickly turn into horror when number of parameters grows and so the vast number of possible constructors.

Another solution would be to go with the JavaBeans pattern.

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User() {
 }

 public void setLogin(String login) {
   this.login = login;
 }

 public void setPassword(String password) {
   this.password = password;
 }

 public void setFacebookLogin(String facebookLogin) {
   this.facebookLogin = facebookLogin;
 }

 public void setFacebookPassword(String facebookPassword) {
   this.facebookPassword = facebookPassword;
 }
}

You create object without any parameters and use set methods to define appropriate values. Solution works fine with any number of parameters and is wildly use by many developers. In fact I’ve seen it almost in every second project I ever worked on. Since every single IDE gives automatic setter and getter generation, most developers follow this simple pattern:

1. create entity class in they favourite IDE (e.g User )
2. define all needed attributes as private fields (e.g login, password, facebookLogin, facebookPassword)
3. auto-generate getters and setters

This pattern is quick when creating entity classes, but it has its flaws. The fact that it generates a lot of code that you might never really need (from time to time check your code on how many getters you have that are never really use, you might get surprised), already makes it a no-no. But it has one more and a lot bigger disadvantage: it allows you to create entity object, that does not have all the obligatory fields set. Example:

User user = new User();
user.setLogin("john");
user.setFacebookLogin("jhawk");
user.setFacebookPassword("12345");

userDao.persist(user);
}

Assuming that userDao.persist(User) calls EntitManager’s persist method, running the code above will throw an exception by the JPA provider, since not-nullable password field was never set.

Ok, so what can we do about it? Joshua Blooch gives fine example of builder pattern.

Instead of making the desired object directly, the client calls a constructor (or static factory) with all of the required parameters and gets a builder object. Then the client calls setter-like methods on the builder object to set each optional parameter of interest. Finally, the client calls a parameterless build method to generate the object, which is immutable. The builder is a static member class of the class it builds.

This works fine for value objects that are immutable (meaning once set, their state is never changed). Consider the example below:

public class Coffee {
 private final CoffeType type;
 private final int cupSize;
 private final boolean hasMilk;

 public static class Builder {
   public CoffeeType type;
   public int cupSize;
   public boolean hasMilk;

   public Builder(CoffeeType type, int cupSize) {
      this.type = type;
      this.cupSize = cupSize;
      hasMilk = false;
   }

   public Builder withMilk() {
      hasMilk = true;
      return this;
   }

   public Coffee build() {
     return new Coffee(this);
   }
 }

 private Coffee(Builder builder) {
   this.type = builder.type;
   this.cupSize = builder.cupSize;
   this.hasMilk = builder.hasMilk;
 }
}

Reading the code above you can clearly see that coffee type and cup size are obligatory and whether coffee should or shouldn’t have milk is not mandatory field. Creating Coffee could look more or less like this:

Coffee coffee = new Coffee.Builder(CoffeeType.Expresso, 3).withMilk().build();
}

Of course using this pattern for value object that has two parameters would be an exaggeration. J. Blooch says:

In summary, the Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if most of those parameters are optional.

The problem is that entities are not immutable by nature. So the question still remains, how can we construct entity classes? What I really like to do is combine JavaBeans pattern and Builder pattern when creating entities. For all entity attributes I create private fields, those that are obligatory become parameters for the public constructor. Since JPA requires that each entity has a parameter-less constructor, I create one, but I give him protected access level, so in most cases it won’t be accessible from client code. I create setter methods for all fields that require them at the moment and incrementally add them whenever needed. So our User example would look more or less like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 protected User() { }

 public User(String login, String password) {
   this.login = login;
   this.password = password;
 }

 public void setFacebookLogin(String facebookLogin) {
   this.facebookLogin = facebookLogin;
 }

 public void setFacebookPassword(String facebookPassword) {
   this.facebookPassword = facebookPassword;
 }
}

And if I would like to stick with all previously mentioned in this posts requirements, we could slightly enhance the constructor to look like this:

 public User(String login, String password) {
   this.login = login;
   this.password = password;
   this.facebookLogin = login;
   this.facebookPassword = password;
 }

Now instantiating User class requires two parameters (login and password). You gain flexibility of JavaBeans, with security of the Builder pattern. Of course this is only hybrid of this two solutions, so it is still possible to create malformed entity (instantiated with obligatory values and then set them again to nulls with setter methods), but this is less likely to happen. You gain on readability, since quick look on constructor parameters gives you notion of all obligatory attributes.

You can also combine this solution with JSR-303 validation and unit testes, solution that can shield you from creating malformed entities… But this is probably topic for another post.

But I wonder how you create your entity classes. Do you know any other ways to create entity classes so their instantiation is safe, readable and maintainable?

Advertisements
Categories: Articles Tags: , ,
  1. January 7, 2010 at 10:44 am

    Excellent article 🙂 Especially for the fact that you are promoting unit test with given-when-then scenario.

    Would you consider adding a null check inside the setters in last example? This way you wouldn’t be able to reset the facebook credentials back to null.

  2. krombaher
    July 20, 2010 at 3:57 pm

    It’s clear about @Inject, but one Q:

    inject(service, “dao”, dao);

    – what test should extends to use this method ‘inject(…)’ ??

    • paulszulc
      July 24, 2010 at 11:46 am

      Hi, inject(service, “dao”,dao) was just sort of pseudo code. I assumed people use different techniques to inject mocks, so I wrote this inject method as a placeholder for any injecting technique you could use.

      If you dont know any I could recommend BeanInject tool http://www.laughingpanda.org/mediawiki/index.php/Bean_Inject

      The above example with BeanInject would look like this:
      Inject.field(“dao”).of(service).with(dao);

      Hope it helps.

  1. January 27, 2010 at 11:08 am

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

%d bloggers like this: