CDI Unterstützung für Infinispan

Infinispan unterstützt CDI (Contexts and Dependency Injection) über das Modul infinispan-cdi. Das Modul ermöglicht sowohl den Infinispan-Cache zu konfigurieren als auch das Injizieren von Cache-Instanzen in CDI-Beans. Zusätzlich bietet das Modul eine partielle Unterstützung der JCache (JSR-107) Cache Annotationen.

Embedded Cache Integration

Mit der Annotation @Inject auf Service- oder DAO-Ebene lässt sich wie in folgendem Beispiel der Default Cache injizieren:

import javax.inject.Inject;

public class NachrichtenService {
    @Inject
    private Cache cache;

    public String sendNachricht(String user) {
        String cachedValue = cache.get(user);
        if (cachedValue == null) {
            cachedValue = "Hello " + user;
            cache.put(user, cachedValue);
        }
        return cachedValue;
    }
}

Es gibt die Möglichkeit, einen spezifischen Cache anstelle des Default Caches zu benutzen. Dafür muss eine entsprechende Cache-Konfiguration und ein Cache Qualifier zur Verfügung gestellt werden.

Ein Beispiel für einen Qualifier wäre:

import javax.inject.Qualifier;

@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NachrichtenCache {
}

Die passende Cache Konfiguration sieht wie folgt aus:

import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.cdi.ConfigureCache;
import javax.enterprise.inject.Produces;

public class Config {
    @ConfigureCache("nachrichten-cache") // The cache name.
    @NachrichtenCache // The cache qualifier.
    @Produces
    public Configuration nachrichtenCacheConfiguration() {
        return new ConfigurationBuilder()
                    .eviction()
                        .strategy(EvictionStrategy.LRU)
                        .maxEntries(1000)
                    .build();
    }

}

Ohne Custom-Konfiguration wird die Konfiguration des Default Caches benutzt.

import org.infinispan.configuration.cache.Configuration;
import org.infinispan.cdi.ConfigureCache;
import javax.enterprise.inject.Produces;

public class Config {
    @ConfigureCache("nachrichten-cache")
    @nachrichtenCache
    @Produces
    public Configuration nachrichtenCacheConfiguration;
}

Der mit Hilfe der Konfiguration bereitgestellte Cache kann ähnlich zur Eingangs gezeigten Variante auf Service oder DAO Ebene injiziert werden. Dazu muss die Annotation mit dem erstellten Qualifier @NachrichtenCache am entsprechenden Injection Point konfiguriert werden.

Überschreiben und Konfigurieren des DefaultEmbeddedCacheManager

Man kann die Default Cache Konfiguration, bei welcher der default embedded Cache Manager benutzt wird, überschreiben. Dafür reicht es, einen “configuration producer” mit der @Default Annotation zu annotieren.

public class Config {
    // By default CDI adds the @Default qualifier if no specific qualifier is provided.
    @Produces
    public Configuration defaultEmbeddedCacheConfiguration() {
        return new ConfigurationBuilder()
                    .eviction()
                        .strategy(EvictionStrategy.LRU)
                        .maxEntries(100)
                    .build();
    }
}

Es ist ebenso möglich, den verwendeten default embedded Cache Manager zu überschreiben. Der neue default Cache Manager muss mit dem @Default Qualifier und dem Scope @ApplicationScoped annotiert werden.

import javax.enterprise.context.ApplicationScoped;

public class Config {
    @Produces
    @ApplicationScoped
    public EmbeddedCacheManager defaultEmbeddedCacheManager() {
      return new DefaultCacheManager(new ConfigurationBuilder()
                                          .eviction()
                                              .strategy(EvictionStrategy.LRU)
                                              .maxEntries(100)
                                          .build());
   }
}

Integration eines Remote Caches

Mit dem infinispan-cdi Modul lässt sich auch ein Cache in Client-Server-Mode integrieren. Im simpelsten Fall reicht hier die Injizierung des DefaultRemoteCache analog zur lokalen Variante:

public class NachrichtenService {
    @Inject
    private RemoteCache cache;

    public String sendNachricht(String user) {
        String cachedValue = cache.get(user);
        if (cachedValue == null) {
            cachedValue = "Hello " + user;
            cache.put(user, cachedValue);
        }
        return cachedValue;
    }
}

Die Injizierung eines spezifischen, verteilten Caches ist über einen Namensparameter möglich. Dafür fügt man zusätzlich zu @Inject noch @Remote("spezifischer-cachename") mit dem Namen des Caches als Übergabewert an der entsprechenden Injizierungsstelle ein.

public class NachrichtenService {
    @Inject @Remote("nachrichten-cache")
    private RemoteCache cache;

    ...
}

Analog zum lokalen Cache ist es hier sinnvoll, einen eigenen Qualifier zu erstellen, der mit @Remote annotiert ist.

@Remote("nachrichten-cache")
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RemoteNachrichtenCache {
}

Mit dem zusätzlichen Hinzufügen des Qualifiers @RemoteNachrichtenCache z.B. auf Service- oder DAO-Ebene lässt sich der spezifizierte Nachrichten-Remote-Cache benutzen.

Default RemoteCacheManager überschreiben

Wie beim Default Cache erfolgt auch die verteilte Cache Integration mit einem DefaultRemoteCacheManagerProducer, der für spezifische Konfigurationen ebenso überschrieben werden kann:

public class Config {
    @Produces
    @ApplicationScoped
    public RemoteCacheManager defaultRemoteCacheManager() {
        return new RemoteCacheManager(localhost, 1544);
    }
}
Short URL for this post: https://wp.me/p4nxik-24v
This entry was posted in Java EE, Java Persistence, Java Runtimes - VM, Appserver & Cloud and tagged , , , , . Bookmark the permalink.

Leave a Reply