Adam Bien's Weblog

Tuesday Jul 07, 2009

Will EJB 3.1 Kill Java Interfaces?

Java Interface are used in following scenarios:

  1. You want to swap several implementations, or hide them behind an interface. (Strategy pattern, or even API-SPI) 
  2. You want to mock out existing functionality (its technically related to 1. but the intention is different)
  3. You want to use JDK's dynamic proxy (the "lightweight" AOP).

In EJB 3.1 with the "no-interface view" interfaces are optional -  you can get rid off interfaces entirely.  

Mocking works just perfectly with frameworks like mockito - interfaces are no more necessary for mocking. You can easily provide mocks for (non-final) classes and change their behavior for test purposes.

@Stateless
public class Service {

    public int getNumber(){
        return 1;
    } 

} 

 //...

import com.abien.business.nointerface.control.Service;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class ServiceFacadeTest {

    @Test
    public void twoIsFalse(){
        Service service = mock(Service.class);
        when(service.getNumber()).thenReturn(2);
 //...

} 

Also interceptors (similar to dynamic proxies) do not require interfaces either. You can easily decorate EJB 3.1 without having any interfaces.

The only thing, which cannot be achieved without having an interface is swapping different implementations without recompiling the client. But exactly this (item 1.) was very rare in my past projects. In vast majority of all cases you will only have exactly one implementation of an interface. You could, of course, provide an interface in advance and hope that it will pay-off in future, but it seems to be unlikely.

With EJB 3.1 interfaces became the artifact again, for what they were actually aimed: a typesafe facade for hiding multiple implementations. You should only use interfaces EJB 3.1, in case you actually have multiple implementations for one interface. 

You can check-out the whole project with source code from: http://kenai.com/projects/javaee-patterns/ [NoInterfaceViewEJBUnitTest]. Tested with Netbeans 6.7 and Glassfish v3 Preview.

[I described in the book "Real World Java EE Patterns" Interceptors, Dependency Injection etc. more deeply] 


Special Event: Java 8 with Java EE 7: "More Power with Less Code", 13th October, 2014

A book about rethinking Java EE Patterns

Comments:

And what about remote clients?

Posted by Simon Martinelli on July 07, 2009 at 11:48 AM CEST #

@Simon,

REST, SOAP do not require interfaces. Only if you are using @Remote. For IIOP you will even have to use Remote-Home interfaces...

thanks for your comment!,

regards,

adam

Posted by Adam Bien on July 07, 2009 at 11:57 AM CEST #

Hi Adam,

I think (Java) interfaces are valuable not just for their practical use (such as swapping multiple implementations or enabling the use of dyna-proxies), but also for describing the "published interface" of an object, that is, the "boundary" APIs used by external components to communicate with your own ones.

I know you can even use public EJB methods for such a purpose, but IMHO the use of interfaces helps you clearly separate your object (component) concerns, and even add more public methods to your EJB implementation, which may not be part of your published interface.

In the end, while I think it is right to say that EJB3 doesn't force you to write interfaces, it's equally important to say that programming by interfaces is *still* a valuable practice.

Cheers,

Sergio B.

Posted by Sergio Bossa on July 07, 2009 at 01:06 PM CEST #

@Sergio,

if you are using an interface as an intention to emphasize the boundary - then I would agree. Especially in more SOA-like projects it is important to hide the realization. But this should be a clear requirement.

thanks for your comment!

adam

Posted by Adam Bien on July 07, 2009 at 01:11 PM CEST #

SOA architectures are an important use case for sure, but I prefer the use of interfaces as a general programming practice even for intra-vm boundaries.

Thanks to you for your blog posts,
Cheers,

Sergio B.

Posted by Sergio Bossa on July 07, 2009 at 01:33 PM CEST #

@Sergio,

agreed. In my opinion interfaces should have an additional meaning - e.g. you could use them to denote a contract. Using them for all kind of EJBs is not a good practice and bloat only.

thanks and regards,

adam

Posted by Adam Bien on July 07, 2009 at 01:43 PM CEST #

In internal implementation code, I could imagine these developments making interfaces less useful.

On the other hand, in an API, interfaces vs. classes have very different uses. In an SPI, I can compatibly remove a method from an interface and not break compatibility with existing implementors (this is *only* if you enforce strict API/SPI separation, so code calling the API can never directly get an instance of an implementation of the SPI interface).

Abstract classes on the other hand, are the opposite case - I can add a final method to an abstract class and (most likely - unless there's a subclass with the same signature and an incompatible return type) not break someone's implementation.

So, while for pure internals of an application, interfaces may be less useful, there are definitely cases where they are the more correct choice when creating an API.

Posted by Tim Boudreau on July 07, 2009 at 08:43 PM CEST #

Tim,

you are absolutely right. From platform perspective interfaces are still interesting. The context of this post was rather an architecture for a business application and not a framework/platform. I thought it was clear mentioning EJB 3.1 :-).

I didn't actually thought about RCP development yet. But having DI available in RCP-space will make interfaces also less important (in case decoration / "AOP" will work with plain classes).

I observed interface overuse in projects, evaluated more heavily EJB 3.1 and got idea for this post :-)

thanks for your comment!,

adam

Posted by Adam Bien on July 07, 2009 at 09:07 PM CEST #

There is almost no such thing as interface overuse.

Essentially they are re-use insurance. It is amazing how often I'll find that some random piece of code suddenly needs to go from being a concrete implementation that no-one would ever think needs to change to being some that needs to allow for different implementations.

Your Service example is a great case in point. Its getNumber method always returns 1. It is entirely likely that, against all expectations, some client may require a Service that returns 2. An interface nicely decouples that direct dependency.

Posted by Jamie McCrindle on July 08, 2009 at 02:39 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
Links
License