Building extensible Java EE Applications – Part 2

The first part covered adapting and packaging extensible Java EE applications.

Introducing Plug-ins

This part will demonstrate how Java EE application can be extended via plug-ins.

To do so we will have to define Service provider interface(s) (SPI).

public interface CorePlugin {
  public String getName();
  ...
}

The applications SPI should be provided in a separate JAR decoupling plug-ins from the core application and avoid cyclic dependency issues (see the previous post for more details).

Implementing a Plugin

It is a simple matter of implementing the defined SPI…

public class MyPlugin implements CorePlugin {
  public String getName() {
    ...
  }
  ...
}

…and packaging it into a bean-archive (see CDI 1.1/1.2 Im-/Ex-plicit bean archives).

Plugin Discovery

Plugin discovery can be implemented using CDI Instance. It is important to note that CDI Instance was not intended for this purpose. As explained by Romain Manni-Bucau “CDI and Instance: 3 pitfalls you need to know”, there are a couple of caveats that have to be taken care of.

  • Slow – Instance forces the container to resolve the beans for each invocation.
  • Can Leak – dependent scoped beans will get created per invocation.

As suggested, both problems can be resolved by caching the resolved instances.

@javax.ejb.Startup
@javax.ejb.Singleton
public class Plugins {

    private final Set<Plugin> plugins = new HashSet<>();

    @Inject
    private Instance<Plugin> pluginInstances;

    @PostConstruct
    public void postConstruct() {
        for (Plugin plugin : pluginInstances) {
            plugins.add(plugin);
        }
    }

    @Lock(LockType.READ)
    public Set<Plugin> getAvailablePlugins() {
        return Collections.unmodifiableSet(plugins);
    }
}

In the example above the plugins are discovered on start-up and cached in a @Singleton EJB (not JSR-330 @javax.inject.Singleton).

Packaging

The plugins have to be included as dependency of the customized application. This can be achieved either by using maven-overlay in case of a WAR…

war
├── ...
└── WEB-INF
|   └── ...
|   └── lib
|       └── core-spi.jar
|       └── custom-module-a.jar
|       └── custom-module-b.jar
|       └── ...
└── ...

…or building a customized EAR file to provide plugins to EJB-JAR’s.

ear
├── lib
|   └── core-spi.jar
|   └── custom-module-a.jar
|   └── custom-module-b.jar
|   └── ...
└── core-ejb-jar
└── ...

Packaging is explained in more detail the previous post.

Acknowledgements

I would like to thank Björn Sonntag and Robert Meyer for reviewing my posts.

Leave a Reply

Your email address will not be published. Required fields are marked *