SQL Zone is brought to you in partnership with:

Senior Java/JEE Developer from Sydney,Australia with more than 6yrs of experience. Mohan has posted 2 posts at DZone. View Full User Profile

Method Chaining in POJO/DTO/JPA/Hibernate Persistence Objects

08.22.2011
| 6801 views |
  • submit to reddit

In recent years method chaining has become popular in the Java/JEE world. Frameworks that I am aware of, that have used Method Chaining effectively are, Hibernate/JPA,EasyMock/JMock and jQuery. jQuery has revolutionized the JavaScript world by using readable fluent interfaces. Method chaining has been around for years from the Small Talk era. In C++,it is very common practice to use method chaining in getter/setter classes. Let us see how we can apply method chaining to Java POJO classes.

Typical Java POJO Example

Let us consider following daily stock price example,

DailyPriceData.java

public class DailyPriceData {

       private Date transDate;
	private Double open;
	private Double high;
	private Double low;
	private Double close;
	private Double volume;

	public DailyPriceData () {

	}
        public DailyPriceData (Date transDate,
         Double open, Double close)     {
         this.transDate =new Date(transDate.getTime());
         this.open = open;
         this.close = close;
      }
      public Double getClose() {
             return this.close;
      }
      public void setClose(Double close) {
          this.close = close;
      }       
	................./getters and setters
  }

The DailyPriceData class above is the typical way we generate POJO's or the way our IDE's will generate them. The Builder/Converter class that will construct the above object has to use setter methods or a constructor has to be provided. We certainly will not provide a bloated constructor with six arguments. The way we solve this issue generally is, we provide getters/setters and expect the Builder/Converter class to construct object using getter/setters. If we want object to be immutable, then we would break the object finer like Price(open,high,low,close)etc... and provide a constructor with finer nested objects. We will not discuss the later case here, and we will assume we are providing getters and setters in our typical Java POJO way.

Converter/Builder

In the Enterprise Java world, it is quite common to convert Persistence objects to DTOs or JAXB Beans etc.. Also it is quite common for us to write Builder classes which construct/build objects based on certain attributes or from other objects. See the example below how we construct the object below with normal setters,

PriceBuilder.java

DailyPriceData priceData = new DailyPriceData ();
  priceData.setClose(priceBean.getClose());
  priceData.setHigh(priceBean.getHigh());
  priceData.setLow(priceBean.getLow());
  priceData.setVolume(priceBean.getVolume());

POJO using Method Chaining

public class DailyPriceData {
       private Date transDate;
	private Double open;
	private Double high;
	private Double low;
	private Double close;
	private Double volume;

	public DailyPriceData () {

	}
      public Double getOpen() {
		return open;
	}
	public DailyPrice setOpen(Double open) {
		this.open = open;
                return this;
	}
	public Double getHigh() {
		return high;
	}
	public DailyPrice setHigh(Double high) {
		this.high = high;
                return this;
	}
        .......
  }

As you can see the only difference between our classical Java POJO and the class above is ,it returns the object (DailyPrice in our case) that invokes the setter method. Now we will see how we construct the object in our builder class.

 PriceBarData priceData = new PriceBarData().setClose(priceBean.getClose())
                    .setHigh(priceBean.getHigh())
                   .setLow(priceBean.getLow().
                    setVolume(priceBean.getVolume());

One of the major advantages of using this method is  that if you try writing the above code in IDE's like Intellij or Netbeans you would see how fast you would write the code by tabbing :).. Also the technique above will not disturb your Hibernate generators,or Dozer frameworks.

Fluent Interfaces

Martin Fowler wrote an article based on Eric Evans presentation and named interfaces 'that are primarly designed to be readable and to flow' as fluent interfaces. Though, we use method chaining in the above method, it is not readable and flowable as we wish to describe as price().openedAt().closedAt().surgedAt()...etc... We will definitely break our Hibernate or JAXB frameworks,if we are using any fluent interfaces. As he describes in his article, writing a fluent interface requires good bit of thought.

Also you can find this article in my personal Blog Using Method Chaining in POJO/DTO/ Entities

Published at DZone with permission of its author, Mohan Ambalavanan.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Andy Jefferson replied on Mon, 2011/08/22 - 2:58am

"JPA" uses method chaining ? not really. The only part that does it to limited extent is the ugly/verbose "Criteria" API, and even there is less "fluent" than APIs like QueryDSL and the proposed JDO Typesafe API. The other parts of JPA do not, at all, use a fluent API

Nicolas Bousquet replied on Wed, 2011/08/24 - 3:15am

Wow... Really you want to do that? As a joke or for fun, ok! But in your next app on the company you work for? Already java bean are just boilerplate and bullshit. 

If you wanted something consise, you would use:

public class DailyPriceData {
  public Date transDate;
  public Double open;
  public Double high;
  public Double low;
  public Double close;
  public Double volume;
} 

DailyPriceData data = new DailyPriceData();
data.close = 3.4;
data.high = 3.8;
data.low = 3.2;
data.volume = 5;

Or add a constructor using fields:

DailyPriceData data = new DailyPriceData(3.5, 3.8, 3.2, 5);

You see, you have less code to write, you describe exactly the same thing... But have less boilerplate code. In case of constructor, IDE reminds you types and parameters name. If you really want it, you can use a static method instead and call:

DailyPriceData data = DailyPriceData.createFromCHLV(3.5, 3.8, 3.2, 5);

You can like it, or hate it, but this is clean, easy to read way of express the exact same thing.

Now of course we will have the old discution that one day, maybe you would like to add behavior on one of thoses getter/setter... First, this would work for the constructor/static method ways. Second, will you ever add behavior to your data containers? No Theses object are just data holders anyway, call them a C struct if you prefer. And everybody using you API will think you'll not add behaviour.  

What is wonderfull in software world is that we introduce complexity (getter/setters, ORMs), and add then another layer of complexity (fluent interfaces), to remove some of the boilerplate. What we end up with is even more complexity, more code to maintain, more risk of introducing bugs.

Mohan Ambalavanan replied on Thu, 2011/08/25 - 1:24am in response to: Nicolas Bousquet

I dunno whether your are going to read this its pretty late ... Cant agree with you more on that one...Except wat if you want your classes to immutable..Ideally I prefer private fields with objects to be instantiated only in constructor with  only getters..

   getDate() {
          return new Date(today.getTime());
   }

 

 But if we dunt care mutable or immutable, C style structs are good enough ..Mayb equals() and hashCode() if required LOL... 

Nicolas Bousquet replied on Thu, 2011/08/25 - 3:34pm

Ok, why not immutables.

 I tend to think that good developpers tend to avoid state change. That's it you don't need to enforce, they will just read input and return a result... I'am not against immutable, it's just that JAVA need so much code to describe the simplest thing that you want to stick to KISS principle as much as possible.

But well today again I have seen some hugly, heavy mutable code in all its horror. So yes enforcing immutability can be good too !

equals/hashcode, (and clone) yes of course if you are going to use them.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.