# Is it worth to use POJOs instead of EJB 3 in terms of performance? (with results, source and load scripts)

I hear from time to time funny statements like "EJB 3 are too heavyweight", or "POJOs are lightweight". If I have the chance I ask directly how the term "lightweight" is defined - and get really funny (mostly inconsistent) answers. This remembers me somehow the answers I get for questions like: "What you actually meant by serviceorientation?" or even better "What do you mean by Web 2.0?". Lastly I was asked "...It would be interesting to see if the same web app would be faster if
you only developed a web-project using JSF, Derby and TomCat as
Webserver..." (instead of Glassfish with EJB 3, JSF and Derby). This request made me really curious - and I built two independent projects. An EAR "EJBLoadTest" which consists of an Servlet and to cascaded EJB 3.public class NumberGenerator extends HttpServlet {    @EJB    private NumberGeneratorFacadeLocal numberGeneratorFacadeBean;       protected void processRequest(HttpServletRequest request, HttpServletResponse response)    throws ServletException, IOException {        response.setContentType("text/html;charset=UTF-8");        PrintWriter out = response.getWriter();        try {            out.println(numberGeneratorFacadeBean.getNumber());        } finally {             out.close();        }    }  } With two local Session Beans. The first one fetches the millis, calls the second one and computes the result. The business logic is dumb, but it avoids GC optimizations.@Localpublic interface NumberGeneratorFacadeLocal {    public long getNumber();    } @Statelesspublic class NumberGeneratorFacadeBean implements NumberGeneratorFacadeLocal {  @EJB  private MillisProviderLocal millisProviderBean;      public long getNumber(){      return System.nanoTime() - millisProviderBean.getMillis();  } } The second bean is simple as well.  package com.abien.loadtest.ejb;import javax.ejb.Stateless;@Localpublic interface MillisProviderLocal {    public long getMillis();    }@Statelesspublic class MillisProviderBean implements MillisProviderLocal {        public long getMillis(){        return System.currentTimeMillis();    }} I introduced the two beans, to maximize the overhead between the "POJOs" and EJB3. In simple applications there would be only one layer - and so less overhead.The POJO application is identical. Instead of EJBs I used POJOs, and instead of an EAR, a WAR.The POJO servlet comes with an additional "init" method. Because dependency injection doesn't work for POJOs (=classes without the @EJB annotation), the POJO creation was factored out in a init method:public class NumberGenerator extends HttpServlet {   private NumberGeneratorFacadeLocal facade;       public void init(){        this.facade = new NumberGeneratorFacadeBean();    }The same story in the facade -  the DI was replaced with an constructor call:public class NumberGeneratorFacadeBean implements NumberGeneratorFacadeLocal {  private MillisProviderLocal millisProviderBean;    public NumberGeneratorFacadeBean(){      this.millisProviderBean = new MillisProviderBean();  }      public long getNumber(){      return System.nanoTime() - millisProviderBean.getMillis();  } }  For the load tests I used JMeter. I repeated the tests several times. The load generator and the Glassfish v2 were on the same machine. This differs a little bit from real world - but is perfectly suitable to show the EJB 3 overhead.The results: EJB3: The throughput of the EJB 3 solution was 2391 transactions/second. The slowest method call took 7 milliseconds. The everage wasn't measurable. Please keep in mind that in every request two session beans were involved - so the overhead is doubled.POJO: The throughput of the POJO solution was 2562 requests/second (request - there are no transactions here). The slowest method call took 10 ms.The difference is 171 requests / seconds, or 6.6% (therefore 3.3% for a single session bean).Conclusion:The dfference is less than expected (I expected an overhead over 10%)... However the POJO sample only works for idempotent / transient use cases. It wouldn't work for highly concurrent, database applications -  I only created one instance for servlet - not request.... In that case, you will have to synchronize the access to the shared state e.g. with transactions or "instances per request". In that case a plain web container wouldn't be the simplest solution.However the EJB 3 solution would work even with database and JMS without modification... The funny story here - the POJO solution required some more lines of code. :-).I checked the projects (POJOLoadTest, EJB3LoadTest), the load script, as well as the results (as screenshots) into http://p4j5.dev.java.net. I used plain Netbeans 6.0 for this purpose - feel free to reexecute the load test again - and share the results :-).
