Skip to content


Subversion checkout URL

You can clone with
Download ZIP
An adapter-aware dependency injection framework for Java.
Clojure Java Shell
Tree: 2c592f1bc6

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


An Adapter-aware Dependency Injection Framework for Java.


Gluer is a lightweight framework for injecting objects into other object's fields, where the injected object need not be type-compatible with the field's type. The injections are competely external, i.e. no changes in any of the classes are required. The framework uses specialised Adapter classes for type-incompatible injections.


Let's look at a simple example. Say we have the following interface and class in one component:

public interface Service {
    public void do(String text);

public class Client {

    private Service service;

    public Client() {"something neat");

    public static void main(String[] args) {
        new Client();

We see here that class Client uses some Service object that is referenced in a field. Say we also have the following class in another, separatly developed, component:

public class Archiver {

    public void archive(String text) {
        System.out.println("Archiving: "+ text);
        // ... archive text.

The class Archiver is a good candidate for being used as a service. So, if want to use an Archiver object in a Client object, i.e. inject the Archiver in its service field, we can specify this in a file, for instance in example.gluer, having the following line:

associate field Client.service with new Archiver

Notice that the types are not compatible. Above statement would inject an Archiver object into a field of type Service. This is where Adapter classes come in. For this example, we would need to define the following Adapter:

import gluer.Adapter;

public class Archiver2Service implements Service {

    private Archiver adaptee;

    public Archiver2Service(Archiver adaptee) {
        this.adaptee = adaptee;

    public void do(String text) {

Since the Archiver2Service is tagged with the @Adapter annotation, the Gluer framework recognizes this class and registers it as an available Adapter. Whenever Gluer is requested to inject an Archiver (or a subtype of it) object into a field of type Service (or a supertype of it), like in our example, it will automatically use above Archiver2Service to "adapt" the method calls.

Gluer has two modes of usage, i.e. a checking mode and a runtime mode. We can check if our injections will work using Gluer as a checking tool. Both modes require a small configuration file, for instance in example.config:

glue: example.gluer

Above configuration tells the tool to use one .gluer file, namely 'example.gluer'. Checking our .gluer specifications and the Adapter classes goes as follows (assuming all above classes are in the current directory):

$ java -cp . -jar gluer.jar example.config
No errors.

Since no errors are found, we can run our application using Gluer as a runtime framework:

$ java -cp . -javaagent:gluer.jar=example.config Client
Archiving: something neat


This project is written in Clojure 1.4. Building it requires leiningen 2 to be installed. To build it, clone this repository and type lein uberjar in a terminal, while in the root directory of the clone. The 'standalone' JAR file can be found in the 'target' directory.


Adapter classes

Adapter classes are ordinary classes, that have some simple rules.

  • It needs to tagged with the @gluer.Adapter annotation.

  • The types (classes and interfaces) it extends or implements determine where the Adapter can be used. Currently there are no restrictions on this. This means an Adapter extending or implementing nothing is possible as well, but it would only be applicible for places where a java.lang.Object is expected.

  • The single-argument non-primitive constructors determine what an Adapter can "adapt". At least one such a constructor is required.

  • The class needs to be declared public. If the class is a member of another class, it needs to be declared static as well.

Adapter resolution

To have an idea which Adapter will be chosen at runtime (and how resolution conflicts are determined when using the checker), have a look at the following rules used by the tool. The Adapter selection is based on the type where the injection takes place and the type of what is requested to be injected.

  1. Check whether the what type is a where type (following the inheritance relations). If so, then we are done and the what will be injected directly into the where. Otherwise, continue to 2.

  2. Determine all eligible Adapters, by filtering all available Adapters on (a) whether it implements/extends a (sub)type of the where type, and (b) if it has a single-argument constructor taking a (syper)type of the what type. Based on the filtered result, the resolution continues as follows:

    • If none are found to be eligible, report this as an error (or throw a RuntimeException), for the injection cannot take place.
    • If one is found, we are done and that Adapter will be used for injection. Continue to step 4.
    • If more than one has been found, continue to step 3.
  3. Determine the "closest" Adapter. We take the eligible Adapters from step 2 and filter them once more, to see which are the closest. Closest here means, which Adapter has a single-argument constructor that takes a type closest to the what type, when looking at the inheritance hierarchy, and if more than one are found to be equally close at this point, the same is done for the where type. Based on the filtered results, the resolution continues as follows:

    • If one is found (at least one is always found), we are done and that Adapter will be used. We continue at step 4.
    • If more than one has been found, the framework cannot make a decision which Adapter to use and reports a resolution conflict error (or throws a RuntimeException).
  4. A (most) suitable Adapter has been found at this point, and if the tool is used in checking mode, then we are done. If, however, the tool is used in runtime mode, it will also determine the "closest" constructor of that Adapter, based on the what type. This constructor will be used for instantiating the Adapter.

    • It can occur that multiple constructors are equally close to the what type. Currently, the constructor choice will be semi-random.

Associations (.gluer files)

The injections (called associations) are in specified in .gluer files. Each associations takes a where clause, a what clause, and optionally specifies the adapter to use. The lines in the .gluer file take the following form:

associate <where> with <what> [using <adapter>]

The following <where> clauses are currently supported :

  • field <class>.<field>: Means injecting the object into the <field> of every instance of the specified <class>. An example: ... field somepackage.SomeClass.aField ....

The following <what> clauses are currently supported:

  • new <class>: Means injecting a new instance of the specified <class> each time the <where> clause triggers an injection. The class should have a non-argument constructor. An example: ... new somepackage.SomeClass ....

  • single <class>: Means injecting a single instance of the specified <class> each time the <where> clause triggers an injection. In other words, the Gluer runtime instantiates the class only once and reuses it for every injection done by this association. The class should have a non-argument constructor. An example: ... single somepackage.SomeClass ....

  • call <class>.<method>([argument expressions]): Means a call to a static (non-void) method each time the <where> clause triggers an injection. The returned object is injected. This clause gives more expressive power, in case the former two <where> clauses are not sufficient. An example: ... call somepackage.SomeFactory.get(MyConfig.isProduction()) ....

Optionally, one can specify which Adapter class should be used when an injection takes place, with using <adapter>. The <adapter> needs to be a fully qualified name of the Adapter class. Adding this to a association overrules the automatic Adapter resolution as described above. Currently this is the only means to mitigate resolution conflicts.

An association might also specify injections that are type compatible. This is perfectly fine, and the runtime will inject the result of the <what> clause directly in the place designated by the <where> clause. Such a direct injection will still take place through the Gluer runtime (i.e., it cannot be optimised), because one can write associations that sometimes need an Adapter and sometimes do not, depending on the actual runtime type of the <what> clause (in particular the 'call' clause).

An example .gluer file:

associate field package.AClass.fieldFoo with new apackage.OtherClass using adapter.OtherClass2Foo

associate field package.AClass.fieldBar with single expensive.InitialisingService

associate field package.Alice.bob with call factories.Persons.create("Eve")

Configuration (.config files)

To keep the number of required command-line arguments to a minimum and to make a Gluer component easily distributable, a small configuration file is used as a way of communicating the necessary information to the framework. The same configuration file can (and should) be used for both the checker as well as the runtime mode of Gluer.

The format of the configuration is simple. Every line that contains at least one colon (:) is considered a key-value pair. Any subsequent colon after the first one is considered part of the value. All other lines are considered comment and are ignored.

The following keys are currently supported:

  • glue: The value specifies a .gluer file, relative to the configuration file. This key can be specified multiple times.
  • verbose: The value can be either 'true' or 'false'. If set to true, debug logging is displayed.
  • plug-in: The value specifies the namespace path to a plug-in file. See the section on 'Extending the framework' below. This key can be specified multiple times.
  • classpath-entry: The value specifies a class-path entry, which will be added to the standard classpath automatically. This key can be specified multiple times.

An example .config file:

This is just comment text, since it does not contain a colon.
Empty lines are ignored as well.

glue: path/to/file.gluer
glue: paths/are/relative/from/the/config.file
glue: more/colons:are:part/of/the.value

plug-in: gluer.plugin.what-call

classpath-entry: adapters.jar

verbose: false

Extending the framework

Future improvements

  • Generics support
  • Plug-in system
  • Class-path entries in configuration

License and disclaimer

Source Copyright © 2012 Arnout Roemers

Distributed under the Eclipse Public License, v1.0

This is a work in progress, use at own risk.

Something went wrong with that request. Please try again.