Building Plug-ins With Java EE 6

"In computing, a plug-in (or plugin) is a set of software components that adds specific abilities to a larger software application. If supported, plug-ins enable customizing the functionality of an application…"
[from http://en.wikipedia.org/wiki/Plug-in_(computing)]

In Java an application usually defines an interface which is implemented then by an extension. The challenge: the application has to locate the implementation without being dependent on it. Java EE 6 / CDI solves this with a single class - javax.enterprise.inject.Instance.

The extension interface:

public interface ConfigurationProvider {
    
    public Map<String,String> getConfiguration();

}

…is going to be (lazy) loaded at startup:

import javax.enterprise.inject.Instance;
import javax.inject.Inject;

@Startup
@Singleton
public class Configuration {

    private Map<String, String> configuration;

    @Inject
    private Instance<ConfigurationProvider> configurationProvider;

   @PostConstruct
    public void fetchConfiguration() {
        this.configuration = new HashMap<String, String>() {{
            put("version", "0.7");
			//...other defaults
        }};
        this.unconfiguredFields = new HashSet<String>();
        mergeWithCustomConfiguration();
    }
    //...

}

If there is an implementation of ConfigurationProvider it will be instantiated by the CDI-container. javax.enterprise.inject.Instance implements java.lang.Iterable, so you can easily locate all implementations without knowing from where they are coming.
Plugin-ins in Java EE 6 are just commodity. There are no patterns, frameworks or libraries required to extend an application core with extension points...

The code above enables a Java EE 6 Configurator to be extended with different configuration sources (file, xml, DB).
[x-ray's cache flushing was configured that way. You will also find the code above in the git repo, See also page 98 "Configuration Over Convention with Inversion of Control" in Real World Java EE Night Hacks--Dissecting the Business Tier.]

Comments:

Hi Adam,

I find @Inject Instance<> great for this use-case.

However, you will have to rebuild your war/ear and redeploy your application to have the new class instance available. Not much of a "plug-in" doing it like this.

Also, defining and deploying the new Instance in new ejb jar archive did not worked for me, the original application will not see it.

The only way I see it working as a plugin so far is to use Glassfish specific @Inject @OSGiService(dynamic=true) Instance<>. Not usable right now because of http://java.net/jira/browse/GLASSFISH-16805.

Any thoughts from you (or maybe a new blog post?) on how to achieve plug-in like capabilities without redeploying the application will be great!

Cheers,
Alex

Posted by Alex on November 10, 2011 at 04:01 PM CET #

@Alex,

I prefer CI and rolling updates over hot deployment in production. I never really had the requirement to hot deploy parts of the application in production. However: all application servers I know are capable to do that.

"Also, defining and deploying the new Instance in new ejb jar archive did not worked for me, the original application will not see it."

It worked in my case(s) - you can put several jars into a WAR. But you will have to redeploy the WAR.

"However, you will have to rebuild your war/ear and redeploy your application to have the new class instance available. Not much of a "plug-in" doing it like this."

Really? How often you managed to install a plugin WITHOUT restarting Eclipse? :-)

The most reliable way to extend application is: http://www.adam-bien.com/roller/abien/entry/restful_calculator_with_javascript_and

If you should also evaluate: LiveRebel (http://zeroturnaround.com/liverebel/)

thanks for your comment & evaluating the code!,

adam

Posted by Adam Bien on November 10, 2011 at 05:10 PM CET #

@Adam,

I think the idea of a plugin is something you can place in say a directory, or register a URL that allows you to download and install plugins without restarting the application, at runtime.. although in many applications adding plugins often requires a restart.

However, the ability to add a chunk of modular code that is "outside" the war file, even if restarting the war is required, for it to be able to find and load that modular chunk of code would constitute a plugin as well.

A fellow friend and I wrote the Platonos plugin engine years ago, modeled after the original Eclipse plugin engine before it went OSGi. We're actually looking at redoing it for Java6 using annotations, CDI and and event bus to provide a easier yet more robust dynamic plugin engine for any purpose. I use a subset of it in my own JEE6 application to dynamically load plugins found at runtime (during a start/restart cycle to be fair) that add some dynamic processing to the JEE6 deployment. The only thing I don't quite understand is the issue behing JEE6 applications banning the ability to use custom classloaders to load dynamic code. To this day I don't see why this is such a problem. Maybe you have more insight and can explain why this might be considered bad?

Posted by Kevin on November 11, 2011 at 07:33 PM CET #

hey! I need some one to please put me through all the jargon of JAVA in relation to plugins. Cause it all sound so whirled, I mean very absurd. Please Show me what material to study to know the rudiment of plugin, you can as well send it to my email(agbajid@yahoo.com). Thank you very much for your concern.

Posted by DANIEL on November 12, 2011 at 03:31 AM CET #

What about User Interface. A plugin is not always only business logic? JSF 2.1 is not supporting yet modularity. Hope JSF 2.2 will do so!!

Posted by Papapetrou Patroklos on November 12, 2011 at 11:17 PM CET #

@Daniel,

"I need some one to please put me through all the jargon of JAVA in relation to plugins"

The only jargon I used here is from wikipedia [ http://en.wikipedia.org/wiki/Plug-in_(computing)]. Because it is wikipedia, you can even change that :-)

In Java EE 6 you can easily implement plugins with:

@Inject
Instance<PluginContract> plugins;

In Java SE with: java.util.ServiceLoader

Because Java is #1 (http://www.adam-bien.com/roller/abien/entry/java_is_1_8230_and) we have several millions plugin frameworks, libraries and patterns.

I could reroute the result of the google search: "java plugin implementation" to your email, but it would overflow your inbox :-)

thanks for your interests,

adam

Posted by Adam Bien on November 13, 2011 at 07:25 AM CET #

Hi Adam,

this is really an easy way to realize a plugin mechanism. Thanks!
I am just missing a way to put the plugins in a specific order. A scenario where this is required might look like this:
- a product provides some core functionality
- plugin1 provides an extension to the core functionality and depends on the core product
- plugin2 provides some customer specific extensions and depends on the core product and plugin1. The required execution order is core -> plugin1 -> plugin2.

Any ideas how to make sure that plugin1 is executed before plugin2? Hard coded ordering information (e.g. a number) will be not maintainable in a huge system with lots of plugins.

Thanks!
Thorben

Posted by Thorben Janssen on November 17, 2011 at 04:23 PM CET #

Hi Adam,

the example only works with POJOs or EJBs with local interfaces.
How would you suggest implementing the same concept with remote EJBs? I have a core version as *.ear deployed on the Server and want to deploy / undeploy (add / remove) the Plugins manually later as ejb.jars.
The Core App should look for all deployed implementations of a sepecific remote Interface and hold references as a list.
Is that possible without implementing complex code like ServiceLocators or custom JNDI lookups?

Posted by Christian on December 28, 2012 at 08:33 PM CET #

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