Showing posts with label Java EE 6. Show all posts
Showing posts with label Java EE 6. Show all posts

05 November 2013

No More Commercial Support for GlassFish - So What?

"GlassFish reduced to toy product" and "R.I.P. GlassFish" are some of the headlines regarding Oracle's announcement to withdraw commercial support for the application server acting as Java EE reference implementation.

Oh well, I've stopped using GlassFish 3.x on a regular basis about a year ago when it became apparent that GlassFish 3.1.2.2 was a dead end for the Java EE 6 Open Source product (see comments of the linked blog post), and I've never really started using GlassFish 4.0 except for quick demos, knowing the release policy would be just the same as for 2.x and 3.x, where the Open Source release was more of a public beta for the closed-source commercial product.

It's nice to know you can get commercial support for a server if you need it and if somebody is willing to pay for it. On the other hand, lots of companies run successful businesses with applications built on Open Source web containers or application servers without any commercial support, because commercial support is not affordable in their business models. Moreover, commercial support is not a guarantee for getting a hot-fix when you need it, if the vendor's priorities happen to differ from your own.

Like many others, I've turned from GlassFish to JBoss AS/WildFly (after evaluating and dismissing TomEE for lack of stability and documentation). JBoss AS 7 has surpassed GlassFish in terms of usability and reliability, and it's just a shame that RedHat has now converted JBoss AS to a Not-So-Open Source project, hiding branches and tags in a private repository and no longer publishing Community binaries. But that's another story...

18 July 2012

OSGi and CDI Combined

Pax CDI is a new OPS4J community project I've started to combine the best of OSGi and CDI.

Once you've worked with CDI or with an up-to-date annotation-based flavour of Spring, the service registry API or XML-based dependency injection in the Blueprint or Declarative Services style suddenly appears rather verbose.

On the other hand, even though Java EE 6 is more lightweight than ever, its monolithic nature feels rather a burden when you're used to OSGi.

Why not have the best of both worlds? The idea is not new, it has been implemented to some extent both in weld-osgi and in the FighterFish subproject of GlassFish.

Unlike these two projects, Pax CDI is independent of any given CDI, Java EE or OSGi implementation. The first proof-of-concept release is based on Apache OpenWebBeans and Equinox. In contrast to weld-osgi, which required some modifications in Weld itself, Pax CDI works with an unmodified version of OpenWebBeans.

Trying to do the same with Weld is one of the next goals for Pax CDI.

An alpha release Pax CDI 0.1.0 is available from Maven Central.

24 May 2012

OSGi, Java EE and CDI Integration Testing with Pax Exam 3

In-container testing is an approach shared by many testing frameworks like Pax Exam, jeeunit, Arquillian and Spring's test context.

Pax Exam 2.x is a mature solution for testing OSGi bundles and applications, jeeunit was created to simplify Java EE 6 integration testing and has been extended to handle stand-alone CDI applications and non-CDI setups based on Tomcat and Spring.

Taking the best of both worlds, the next major release line Pax Exam 3.x is designed to provide a unified testing experience by incorporating additional test containers for Java EE and CDI from jeeunit while staying backward compatible with Pax Exam 2.x for OSGi.

The first public milestone release Pax Exam 3.0.0.M1 is now available from The Central Repository (aka Maven Central), including test containers for GlassFish, OpenWebBeans and Weld.

While jeeunit works with Embedded GlassFish which lacks all OSGi capabilities of the GlassFish server, the Pax Exam GlassFish Container launches GlassFish 3.1.2 on top of an OSGi framework, enabling users to deploy or provision both WAR modules and OSGi bundles, thus providing a test environment for hybrid Java EE/OSGi applications.

A plain old JUnit test class can be turned into an in-container integration test simply by adding a @RunWith(PaxExam.class) annoation and some configuration data in a properties file.

See the Pax Exam 3.0.0.M1 Release Notes for more details and use the OPS4J mailing list (general@lists.ops4j.org) for feedback and support.

01 May 2012

Deconstructing Spring myths

Over the past five years, I have had the pleasure of working on different Java enterprise projects based on OSGi, Java EE and Spring. Among these three platforms, Spring is the one I'm least happy with.

Granted, Spring lets you build complex enterprise applications without too much pain, or else it wouldn't be so popular. In the times of J2EE 1.4, Spring must have felt like a breath of fresh air, and without the competition of Spring and Hibernate, J2EE might not have evolved into what Java EE 6 is today.

But somehow the glory of Spring's founding myth of killing the beast that was J2EE seems to be fading. The former beast is now as manageable and easy to use as Spring ever was, or even more so. Dependency Injection in Java is no longer synonymous with Spring (and in fact never was).

The Spring Framework needs a new raison d'ĂȘtre, and the current strategy seems to be diversification: Projects like Spring Data or Spring Social offer new features that have no equivalent in Java EE or OSGi. And of course, any Spring XYZ project requires the Spring Framework. But looking at the capabilities of the Spring Framework itself, where are the killer features?

Does Spring provide solutions that are smarter or easier to use than equivalent constructs in Java EE?

Here is a list of reasons why I feel more productive on Java EE 6 than on Spring 3.1.

There is no Spring without Java EE


Most debates about Java EE vs Spring sound like an either-or question, but this is a misconception. You can build an application on Java EE without ever using a Spring API, but you can't really build an enterprise application on Spring without using a number of Java EE APIs and implementations.

A typical Spring-based application includes

  • a web container, usually Tomcat, which means Servlet, JSP, EL, all of which is Java EE
  • a service layer, which has the highest chance of being Spring-only, with Spring transactions and Spring dependency injection
  • some web service endpoints, most likely JAX-RS or JAX-WS, which means Java EE again
  • a persistence layer, traditionally Hibernate Native API + Spring templates, but these days there's really no reason for preferring vendor-specific APIs over JPA 2.0
  • some messaging, e.g. with ActiveMQ, which means JMS and thus Java EE again.

Thus, Spring and Java EE applications mostly differ in the following areas only:
  • the web framework (Spring MVC vs. JSF vs. Wicket vs. Vaadin vs. Struts vs.....)
  • Spring Beans vs. EJB
  • Spring Dependency Injection vs. CDI or Java EE 5 @EJB or @Resource injection

In the age of AJAX and component-oriented web frameworks, Spring MVC feels rather old-school. JSF 2.1 has a lot more to offer, and if you prefer an independent web framework like Vaadin, the underlying container does not matter anyway.

Who's afraid of EJBs? All you need is a @Stateless annotation on your Java class, and you get a thread-safe service where all public methods are transactional by default, which is just what you need in most cases.

And finally, CDI is much more powerful that Spring Dependency Injection, due to its seamless scope handling, its event model and its portable extension mechanism.

API vs. Implementation


Spring has no clear separation of API and implementation, neither at specification level nor at code level. The Spring Reference Manual documents the one and only Spring Framework implementation. The Spring Javadocs document each and every class contained in the Spring Framework. It is not easy to distinguish API level classes from container internal classes.

By contrast, Java EE is first and foremost a set of specifications, represented by a collection of thin API JARs or an all-in-one javaee-api.jar. There are different independent implementations by different providers. Provider specific implementation classes are not normally visible to the user.

Vendor Lock-In


Competition is a good thing. When you are having an issue with your application running on a given Java EE server, try another server. This will give you some insight whether or not the issue is caused by your application or the server.

With Spring, there's only Spring. You can't swap framework components. You can't even cherry-pick framework components. There is insufficient separation of concerns. Inherently, there is no reason why a web framework or a NoSQL persistence provider should have to be tied to a given dependency injection container. But you can't use Spring MVC or Spring Data without Spring Core, just like you can't run Microsoft SQL Server without Microsoft Windows.

JAR Hell


Java EE means one-stop shopping for the core functionality of an enterprise software stack. javaee-api.jar provides the interfaces you need to start developing your own applications. All the required runtime environment is provided by the application server.

Yes, the application server runtime does contain a lot of stuff you'll never need. But modern servers like GlassFish 3.x or JBoss AS7 are modular and lazily activate only the stuff you do need, so there is no runtime overhead. And even a monolithic server like Resin 4.x has a surprisingly small footprint.

My current project is a Spring web application deployed on Tomcat. The final WAR has more than 100 JARs in WEB-INF/lib. More than 30 of these JARs are due to Spring itself, its dependencies or other Java EE components not provided by Tomcat.

In other words, by moving from Spring to Java EE, I could drop a third of the dependencies of my application. And I'm not talking about saving 30 megabytes of disk space, but about the effort of maintaining these dependencies and resolving version conflicts of transitive dependencies.

Configuration Hell


The flip side of JAR hell is configuration hell. With Spring, once you have gathered all required components, you also need to configure them. You may get away with an automatic component scan for your own application beans, but there is always a certain amount of manual plumbing for setting up framework beans, and standard features like transaction management or property substitution have to be enabled explicitly.

Most Spring-based projects started before 2010 still use XML configuration which for my taste is hard to read, extremely verbose and hard to refactor. Spring 3.0 first introduced Java configuration as an alternative but left it unfinished. Spring 3.1 finally supports type-safe Java-only configurations. Unfortunately, the reference manual and Spring extensions like Spring Security still promote XML configuration and leave it to the user to figure out the Java equivalents, which can be rather challenging, especially when custom Spring XML namespaces are involved.

With Java EE 6, little or no configuration is required. Transaction management works out of the box. Use an empty beans.xml marker file to enable CDI. Define the data sources and connections pools for your application in your application server's administration console. That's it.

Thread Safety


Spring leaves thread safety up to you. Controllers and services have singleton scope by default, so you can't use instance variables, or you need to protect them explicitly.

With Java EE, stateless EJB are pooled, concurrent requests each get served by a new beans from the pool, so your beans are thread-safe by default, unless you modify static members or global singletons.

Singleton Antipattern


The fact that Spring beans are singletons and not thread-safe by default tends to promote a rather ugly procedural programming style. Suppose you have a service with one public method performing some non-trivial business logic, factored out into a number of private methods.

In a stateless EJB, your private methods can share state in member variables within the same request (i.e. public method call), so in fact, the EJB is not quite as stateless as it may appear.

In a Spring bean, you often see private methods with long parameters lists, since you cannot share state in member variables, so you have to pass it around in method arguments.

Mixing Scopes


Due to these issues with singleton Spring beans, you may want to use the prototype scope, or the request scope in web applications.

Now when you inject a protoype or request scope bean into a singleton bean, Spring does not by default do the right thing to ensure that the injected bean is indeed a different instance per request. You need to resort to method injection or configure a scoped proxy explicitly.

CDI, on other hand, automatically proxies injected beans when needed.

Transactions


Spring itself does not provide global transactions across multiple resources. It can delegate to a JTA transaction manager but does not provide its own implementation.

Working with two or more persistence units in the same application, you need to configure a transaction manager per persistence unit and reference the correct instance in the @Transactional annotation of your service class or method.

In Java EE, transactions are managed by the container by default. EJBs are transactional by default. The container can handle multiple persistence units without further configuration. Global transactions spanning multiple datasources work out of the box if you configure XA datasources.

Load Time Weaving


Some persistence providers require load time weaving, also known as byte code enhancement. The JPA specification defines a hook for this purpose in PersistenceUnitInfo.addTransformer().

With OpenJPA and GlassFish, this works like a charm. Using OpenJPA with Spring and Tomcat, the required set-up is rather a nightmare, so I ended up using build-time enhancement, which is a lot easier to configure, but still requires additional manual configuration.


Summary


Spring has had its merits in giving relief to frustrated J2EE developers. But this is 2012 - compared to Spring, Java EE 6 now provides equivalent or better solutions for most standard tasks in enterprise application development.

Both Java EE and Spring are far from perfect. All in all, Java EE is more integrated and easier to use - not by orders of magnitude, but noticeably so.

And none of this is an eternal truth, tables may turn again within a few years.


25 January 2012

Integration Testing for JBoss AS7, Tomcat and Weld SE

Initially, the jeeunit Integration Testing framework was exclusively focused on Java EE 6, supporting GlassFish 3.x, which was the only Java EE 6 compliant server at that time. Support for Resin 4.x has been added in subsequent releases.

With the current release 0.9.1, jeeunit supports JBoss AS 7, as well as alternative containers and injection methods beyond the scope of Java EE 6. You can now run jeeunit tests on Tomcat 6 and 7 and Weld SE containers.

Tomcat can be combined either with Spring 3.1 or with CDI (Weld Servlet) to inject dependencies into jeeunit tests.

And there's more to come: While jeeunit will continue a life of its own for a while, I'm planning to merge it step by step into Pax Exam, the OSGi testing framework of the OPS4J community.

Pax Exam and jeeunit both implement an in-container testing approach - while Pax Exam focuses on OSGi alone, jeeunit now supports various other containers, but no OSGi at all.

The Pax Exam/jeeunit merger opens interesting perspectives for hybrid applications, i.e. enterprise applications composed of traditional WARs and OSGi bundles. GlassFish 3.x supports this hybrid application model, implementing a subset of the OSGi Enterprise specifications.

For Pax Exam, the road towards the next major release 3.0.0 will be marked by a sequence of milestone releases, each of which is to incoporate a new container adapted from jeeunit.

A Pax Exam GlassFish Test Container is the goal of the first proof-of-concept milestone 3.0.0.M1. This is work in progress on a dedicated branch exam3-milestones in the Pax Exam GitHub repository.

Stay tuned...

23 October 2011

JBoss AS 7: Catching up with Java EE 6



In my Java EE 6 server comparison of June 2011, JBoss AS 6.0.0 was not exactly the shining star, both in terms of performance and usability.

The next major release JBoss AS 7, claiming to be lightning fast, was published in July 2011, followed by two maintenance updates in August and September.

Time to take another look at JBoss and check if it now compares more favourably to other servers.

07 June 2011

Java EE 6 Server Comparison: Conclusion

Lessons Learned


Portability is not just a Java EE marketing promise. My application now runs on three different Java EE 6 servers, using the same WAR file, without any compile-time configuration.

An application is not portable until it has been ported. Of course, this is true for any specification with different implementations, not just for Java EE. Each of the three servers helped me discovering incorrect API usage in my application that just happened to work on another server.

Certification is not reliable. My application hit at least one major specification violation in each of the three Java EE 6 certified servers. Thus, the test coverage in the Java EE TCKs must be insufficient.

Java EE 6 Server Comparison: Resin

The first time I read about Caucho Resin 4.x was last summer, when I was looking for alternative CDI implementations, i.e. other than Weld. Resin has its own CDI implementation named CanDI, and I was bold enough to give it a try, knowing that Resin 4.x was not yet Java EE 6 certified and probably not stable enough.

I didn't get very far at that time, CanDI looked ok, but the JPA API was broken and @Singleton @Startup beans did not work, so I left it at that and made a mental note to check back after the first stable release.

Java EE 6 Server Comparison: JBoss

I never did any serious work with JBoss AS 5 or earlier versions. At the peak of my frustration with Glassfish last summer after the 3.0.1 release when CDI continued to be unusable, I knew that JBoss would be no help as it also included Weld, the main source of trouble. Besides, given the number of problems in released and certified Glassfish, I dreaded an even larger number of problems in an unreleased, uncertified and undocumented JBoss.

When JBoss AS 6.0.0 was finally released late in December 2010, with surprisingly little marketing noise and community echo, I briefly had a look at the release and was disappointed to find out that it was still largely undocumented.

Java EE 6 Server Comparison: Glassfish

In April 2010, I started a Java EE 6 project, and Glassfish 3.0 was the obvious server choice, or rather, the only option at that time. For the next couple of months, I spent a considerable amount of time not working on my application, but analyzing, reporting and working around bugs in the server, mainly in the CDI and JPA areas. This appeared to be the price you had pay for being an early adopter of the new Java Enterprise standard.

Java EE 6 Server Comparison: Introduction

A year and a half after the Java EE 6 specification release, there are now three Open Source servers certified for the Java EE 6 Web Profile:
  • Glassfish 3.x
  • JBoss 6.x
  • Resin 4.0.x
Time to take a look at these three servers in direct comparison and do some experiments, not with a toy or benchmark application developed for this purpose, but with a real-life enterprise application.

06 June 2011

Java EE 6 Integration Testing on Resin and Glassfish

jeeunit, my Java EE 6 Integration Testing project, now supports Caucho Resin 4.0.18 in addition to Glassfish 3.1.

Another new feature is a @Transactional annotation which can be used to wrap test methods in an auto-rollback transaction.

The current release jeeunit 0.8.0 is available from Maven Central and from the jeeunit Project Page on Google Code.

01 June 2011

Using CDI from Spring

Spring and Java EE are converging in many areas, mainly due to CDI. In fact, by confining yourself to a suitable subset of annotations and other configuration mechanisms, you can design your persistence and service layers to run either on Java EE 6 or on Spring 3, simply by selecting the appropriate set of libraries.

The web layer is a different story: if your web framework is tightly coupled to either Java EE 6 or Spring, it will be hard or even impossible to simply change the container, but even in the web layer, there are solutions like Apache Wicket which work well both with Spring and Java EE, all you need is some glue code to access the dependency injection container.

I'm currently migrating a web application from Tomcat/Spring to Glassfish, and since this application is based on Spring MVC, I cannot completely replace Spring in this step. The goal of the migration is to drop all Spring dependencies from all components except the web frontend and to somehow make the service beans (stateless session beans and CDI managed beans) visible to the Spring web application context.

13 March 2011

Transparent Asynchronous Remoting via JMS

The Scenario


A client needs to invoke a service interface with the following restrictions:
  • The service implementation is running on a remote machine.
  • This fact is transparent to the client, i.e. any service method invocation is just like a local method invocation.
  • The service methods are executed asychronously on the server, method invocations on the client return immediately (fire-and-forget).
  • All service methods have void return types.
  • The service invocations shall be transported via JMS.

20 February 2011

Building a Web Application with Wicket, Spring and JPA

This is a tutorial on setting up a web application stack with Wicket, Spring and JPA, with a special focus on avoiding Spring XML configuration in favour of Java configuration, and on using the JSR-330 @Inject annotation both in the web and service layers.

Martijn Dashorst's blog on Wicket/Spring/Hibernate configurationwas the starting point for my setup, and as I hate "oodles of XML"  as much as he does, I replaced all the XML bean declarations by a @Configuration class, a new feature in Spring 3.0.x.

22 January 2011

Transparent Asynchronous Remoting

The Scenario


A client needs to invoke a service interface with the following restrictions:
  • The service implementation is running on a remote machine.
  • This fact is transparent to the client, i.e. any service method invocation is just like a local method invocation.
  • The service methods are executed asychronously on the server, method invocations on the client return immediately (fire-and-forget).
  • All service methods have void return types.

The Solution with Java EE 6


With Java EE 6, the solution is quite simple, thanks to the @Asynchronous annotation introduced in EJB 3.1. You simply create a remote session bean and add this annotation to any business method or to the entire class. The container will then execute the given methods asynchronously.

Patrick Champion has a complete example in his blog, so there's no need for me to provide any sample code.

When your client is also a Java EE 6 application, you can simply @Inject the service interface and use a @Produces annotation on an @EJB reference somewhere else to direct the client to the appropriate implementation.

In addition, to avoid hardcoding the service URL in your client, you should define a local JNDI alias in your Java EE 6 container for the address of the remote service implementation, so you can move the remote implementation to another host without recompiling your client.

The Solution with Spring 3.0


Spring does not have an out-of-the box solution for this scenario. Spring Remoting provides transparent proxies for remote services, but these proxies are always synchronous. Since Spring 3.0, there annotation support for asynchronous execution, but this only applies to local beans.

However, it is not hard to combine these two features with some glue code to implement a solution for our scenario.

18 January 2011

reFit: Acceptance Testing for Java EE 6, Spring and OSGi

Even if you don't practice test-driven development, you are certainly familiar with the JUnit family of testing frameworks (including ports to other languages like cppunit, NUnit, or independent but similar approaches like TestNG).

This post is about the Fit framework family, which has a somewhat different focus and is not just another JUnit clone. In a nutshell, Fit represents expected and actual test results in tables, and you do not have to be a programmer to read or write them.

The following table has one column of inputs and two columns of outputs:

Each row of this table can be regarded as an acceptance test case. You can feed this table to a given system and compare the outputs:

It's only a couple of weeks ago I was introduced to Fit in my current project, and I must admit my first thought was "Why don't you just write a @Parameterized JUnit test?"

The answer is, JUnit is for developers, and developers only; Fit is for customers and developers.

You still need a developer to implement the skeleton logic of a test (called fixture in Fit), but anyone can write new test cases by adding rows or columns to a given Fit table.

The Fit method and the original Java implementation were created by Ward Cunningham in or around 2002, the project is hosted on Sourceforge and has been inactive since 2008.

The Fitnesse project integrates Fit with a Wiki, it includes a modified version of the original Fit implementation and is under active development. However, Fit and Fitnesse are incompatible, Fit lets you write your test tables in plain old HTML, whereas Fitnesse supports its own Wiki syntax only.

Our project has a fair amount of plain old HTML Fit tests, and our production code uses Spring, so it was a fairly natural idea to inject Spring beans from the system under test into our Fit test code.

Spring is just one (and not really my favourite) framework for dependency injection (and lots of others things). so I inevitably started thinking about how to use Fit together with Java EE or OSGi.

Thinking was followed by coding (yeah, it can be the other way round sometimes...), and this led to a project called reFit hosted on Google Code.

reFit is based on the latest Fit sources from SourceForge, it provides up-to-date Maven artifacts on Maven Central and integrations with Java EE 6, Spring and OSGi Declarative Services. The Java EE integration reuses parts of my jeeunit project.

In addition, reFit lets you run Fit tests under a JUnit wrapper or from a Maven plugin, both with or without Spring integration. reFit includes ready-to-run example code for Glassfish 3.1, Spring 3, Equinox and Weld SE.

There's more to come, I'm currently experimenting with a Web frontend and a WYSIWYG HTML editor.

For more details, check out the reFit Wiki.

28 December 2010

Java EE 6 Integration Testing Easier Than Ever

With jeeunit 0.6.0, you can write and run JUnit integration tests for Java EE 6 components as easy as this:

@RunWith(JeeunitRunner.class)
class MySessionBeanTest {
    
    @Inject
    private MySessionBean mySessionBean;

    @Test
    public void aSimpleTest() {
        boolean result = mySessionBean.doSomething();
        assertTrue(result);
    }
}

The JeeunitRunner builds a WAR on the fly, launches an embedded container, deploys the WAR and delegates all test methods to a proxy runner within the container.

With this approach, you can run your test class (or even a package with multiple test classes) from Eclipse via the context menu. The container is only launched once for all classes.

jeeunit currently supports Glassfish 3.1-b33 or higher. It uses the new Embedded Glassfish API introduced in b33.

Compared to earlier jeeunit versions, it is no longer required to build a test WAR manually or to provide a test suite for running multiple test classes.

Thanks to the excellent service provided by Sonatype OSS Repository Hosting, jeeunit is now available from Maven Central.

18 December 2010

An Update on Memory Issues in Glassfish and Weld

Using the most recent Glassfish milestone build 3.1-b33, I took another look at the memory issues that had plagued my project on Glassfish 3.0.1. The last build I tried was b30, which did not even let me deploy my application.

Just in time for Christmas, there are Good Tidings - Weld has improved a lot, and I can no longer see any suspicious memory usage related to Weld. I took my Wicket+EJB+OpenJPA+PostgreSQL application packaged in a single WAR and deployed it to several different Glassfish versions from the command line. Then I used the Eclipse Memory Analyzer to a create a heap dump of the running Glassfish instance.

The Total Heap column in the following table is the total size of the heap as reported by the Memory Analyzer. The Shallow, Retained, and Percentage Columns refer to the amount of heap memory consumed by instances of org.jboss.weld.introspector.weld.jlr.WeldClassImpl

Glassfish Version Total Heap Shallow Retained Percentage
3.0.1 412.1 MB 84.680 378.215.056 87.52 %
3.1-b26 335.3 MB 85.144 205.527.048 58.38 %
3.1-b33 149.6 MB 84.216 7.041.704 4.49 %

The retained heap of an object is the set of objects that will be garbage collected when the given parent object is garbage collected.

So in b33, Weld still holds 5 % of the total heap - whether or not this is still too much or just reasonable is surely debatable. But I'm really happy to see that Weld has improved a lot, so I would no longer consider it as a no-go.

The version of my application I used for these measurements is the last one that actually used Weld, before I decided in August to stop using CDI to get rid of most memory issues.

I took some more measurements with the successor version in which CDI was eliminated essentially just by replacing @Inject by @EJB throughout the sources. This is really the only difference between the two versions, and here are the total heap sizes:

Glassfish Version with @Inject with @EJB
3.0.1 412.1 MB 44.4 MB
3.1-b33 149.6 MB 138.3 MB

The illustrates, as claimed in my previous post, that I was able to save 90 % of heap memory by not using CDI on Glassfish 3.0.1. Doing the same on Glassfish 3.1-b33, I can still save about 9 %.

But I was really surprised to see the heap usage of my application increase by a factor of 3 between Glassfish 3.0.1 and 3.1-b33.

The Memory Analyzer reveals the culprit to be org.glassfish.hk2.classmodel.reflect.impl.TypesCtr with a retained heap of about 80 MB.

I have no clue what this class is doing, but it smells like another case of an oversized reflective model of the application, which was just the problem with earlier Weld versions.

GLASSFISH-15266 is the related issue in Glassfish JIRA.

10 December 2010

The Interface Antipattern

Keeping interfaces and implementations separate is a useful design pattern for building modular systems. If your clients only depend on a service interface, you can switch service implementations without your clients even noticing.

Now there can be too much of a good thing, and the quality of a software system is certainly not measured by the ratio of interfaces to classes.

When you are planning to implement a FrobnicatorService, think twice before creating an IFrobnicatorService interface and a FrobnicatorServiceImpl. How many different Frobnicator implementations are there going to be? If you do need at least two implementations with distinct behaviour, then go ahead and create the interface. If there's only one implementation, then don't bother with the interface.

Resist the temptation of speculative generalization: "Oh, there might be a performance bottleneck, and in that case an alternative CacheingFrobnicatorServiceImpl might help, so I really should start with a service interface now." Think twice: you ain't gonna need it.

And if you do need the interface, you can still pull it out when you need it. Most IDEs have an automatic refactoring Extract Interface. (Unfortunately, none of the major Java IDEs seems to have the opposite refactoring Merge Interface and Implementation.)

Even in Java EE, the times of interface inflation are gone with EJB 3.1, thanks to the no-interface local view. For a stateless session bean, it is enough to implement

@Stateless
public class FrobnicatorService {
    
    public void frobnicate() {
        ...
    }
}

Every public method of this class will be part of the implicit local business interface.

In OSGi, a service does not need to have a separate interface, you can register any class as a service. Even when using Declarative Services, don't get fooled by the XML syntax of the Service Component Descriptor:

<service>
  <provide interface="com.example.FrobnicatorService"/>
</service>


The provide element has an interface attribute, but the attribute value can be any old class.

The same is true in Spring: There is no rule forcing you to inject Spring beans only via their interface. Any old class will do, even when working with automatic transaction proxies (just make sure that CGLIB is on your classpath).

So remember the KISS principle and kill some of the interfaces you don't really need!