adam bien's blog

Injecting Remote Properties With Java EE 📎

In Java EE the meta data of an injection target is available as a an optional parameter. The instance javax.enterprise.inject.spi.InjectionPoint holds the class-, field information as well as used annotations:


import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

@Produces
public String getString(InjectionPoint ip) {}

The following field's metadata provides sufficient information to perform a HTTP-GET request and inject the fetched value at runtime:


    @Inject
    @CacheEntry(host = "headlands", port = 8080, cache = "configuration", key = "message")
    String notexisting;

The metadata extracted from above field is used to resolve the following HTTP template and access a remote HTTP-resource:

	http://{host}:{port}/headlands/resources/caches/{cache}/entries/{key}

The JAX-RS 2+ client resolves the template and performs the request:


    import javax.ws.rs.client.Client;
    import javax.ws.rs.client.ClientBuilder;
    import javax.ws.rs.client.WebTarget;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.client.WebTarget;

    private Client client;

    @PostConstruct
    public void init() {
        this.client = ClientBuilder.newClient();
    }
   
   WebTarget resolve(CacheEntry cacheEntry) {
        return this.resolve(cacheEntry.host(), cacheEntry.port(),
                cacheEntry.cache(), cacheEntry.key());
    }

    WebTarget resolve(String host, int port, String cache, String key) {
        return resolve(host, port, cache).path(key);
    }

    WebTarget resolve(String host, int port, String cache) {
        StringBuilder builder = new StringBuilder();
        String hostUri = builder.append("http://").
                append(host).
                append(":").
                append(port).toString();
        return this.client.target(hostUri + 
			"/headlands/resources/caches/{cache}/entries/").
                resolveTemplate("cache", cache);

    }

Now you only have to "produce" the value fetched from a remote HTTP-location:

@Produces
@CacheEntry(cache = "-")
public String getString(InjectionPoint ip) {
	Annotated annotated = ip.getAnnotated();
	CacheEntry cacheEntry = annotated.getAnnotation(CacheEntry.class);
	return resolve(cacheEntry).request().get(String.class);
}

The URI used in this example is compatible with headlands -- a JCache exposed via REST.

Project marina comprises a single class (you will find 80% above) and the CacheEntry annotation. Marina enables injection of entries stored in a remote headlandsinstance.

Marina is available in maven central as following dependency (5.7 kB):

 <dependency>
  <groupId>com.airhacks</groupId>
  <artifactId>marina</artifactId>
  <version>0.0.1</version>
</dependency>

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io. Marina and headlands are used as an example in the Microservices with Java EE 7 and Java 8 on-demand workshop.