Maven and JBoss a concrete example: Infinispan

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

If you have completed the basic Maven and Eclipse tutorial we will now learn how to enhance the simple Project by adding a dependency to a JBoss framework: Infinispan.

Infinispan currently has already some Maven archetypes you can use to create a skeleton project and get started using Infinispan.  This is an easy way to get started using Infinispan as the archetype generates sample code, a sample Maven pom.xml with necessary depedencies.

So the quick way to generate this project is by running maven archetype generator using the org.infinispan.archetypes groupId:

 mvn archetype:generate -DarchetypeGroupId=org.infinispan.archetypes -DarchetypeArtifactId=newproject-archetype -DarchetypeVersion=1.0.10 -DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public

If you want to learn how to get started with Maven and JBoss projects, we suggest to build the project from an quickstart project (see this tutorial how to create a quickstart project). This can be useful if you will familiarize with basic Maven concepts.

So provided that you have created a quick start project, add the following classes under the src\main\java folder

package com.sample;

import org.infinispan.Cache;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.*;
import org.infinispan.notifications.cachelistener.event.*;
import org.infinispan.notifications.cachemanagerlistener.event.Event;
import org.infinispan.util.concurrent.NotifyingFuture;

import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Sample application code.  For more examples visit http://community.jboss.org/wiki/5minutetutorialonInfinispan
 */
public class Application {

   public void basicUse() {
      System.out.println("\n\n1.  Demonstrating basic usage of Infinispan.  This cache stores arbitrary Strings.");
      Cache<String, String> cache = SampleCacheContainer.getCache();

      System.out.println("  Storing value 'World' under key 'Hello'");
      String oldValue = cache.put("Hello", "World");
      System.out.printf("  Done.  Saw old value as '%s'\n", oldValue);

      System.out.println("  Replacing 'World' with 'Mars'.");
      boolean worked = cache.replace("Hello", "World", "Mars");
      System.out.printf("  Successful? %s\n", worked);

      assert oldValue == null;
      assert worked == true;
   }

   public void lifespans() throws InterruptedException {
      System.out.println("\n\n2.  Demonstrating usage of Infinispan with expirable entries.");
      Cache<String, Float> stocksCache = SampleCacheContainer.getCache("stock tickers");
      System.out.println("  Storing key 'RHT' for 10 seconds.");
      stocksCache.put("RHT", 45.0f, 10, TimeUnit.SECONDS);
      System.out.printf("  Checking for existence of key.  Is it there? %s\n", stocksCache.containsKey("RHT"));
      System.out.println("  Sleeping for 10 seconds...");
      Thread.sleep(10000);
      System.out.printf("  Checking for existence of key.  Is it there? %s\n", stocksCache.containsKey("RHT"));
      assert stocksCache.get("RHT") == null;
   }

   public void asyncOperations() {
      System.out.println("\n\n3.  Demonstrating asynchronous operations - where writes can be done in a non-blocking fashion.");
      Cache<String, Integer> wineCache = SampleCacheContainer.getCache("wine cache");

      System.out.println("  Put #1");
      NotifyingFuture<Integer> f1 = wineCache.putAsync("Pinot Noir", 300);
      System.out.println("  Put #1");
      NotifyingFuture<Integer> f2 = wineCache.putAsync("Merlot", 120);
      System.out.println("  Put #1");
      NotifyingFuture<Integer> f3 = wineCache.putAsync("Chardonnay", 180);

      // now poll the futures to make sure any remote calls have completed!
      for (NotifyingFuture<Integer> f: Arrays.asList(f1, f2, f3)) {
         try {
            System.out.println("  Checking future... ");
            f.get();
         } catch (Exception e) {
            throw new RuntimeException("Operation failed!", e);
         }
      }
      System.out.println("  Everything stored!");

      // TIP: For more examples on using the asynchronous API, visit http://community.jboss.org/wiki/AsynchronousAPI
   }

   public void registeringListeners() {
      System.out.println("\n\n4.  Demonstrating use of listeners.");
      Cache<Integer, String> anotherCache = SampleCacheContainer.getCache("another");
      System.out.println("  Attaching listener");
      MyListener l = new MyListener();
      anotherCache.addListener(l);

      System.out.println("  Put #1");
      anotherCache.put(1, "One");
      System.out.println("  Put #2");
      anotherCache.put(2, "Two");
      System.out.println("  Put #3");
      anotherCache.put(3, "Three");

      // TIP: For more examples on using listeners visit http://community.jboss.org/wiki/ListenersandNotifications
   }

   public static void main(String[] args) throws Exception {
      System.out.println("\n\n\n   ********************************  \n\n\n");
      System.out.println("Hello.  This is a sample application making use of Infinispan.");
      Application a = new Application();
      a.basicUse();
      a.lifespans();
      a.asyncOperations();
      a.registeringListeners();
      System.out.println("Sample complete.");
      System.out.println("\n\n\n   ********************************  \n\n\n");
   }

   @Listener
   public class MyListener {

      @CacheEntryCreated
      @CacheEntryModified
      @CacheEntryRemoved
      public void printDetailsOnChange(CacheEntryEvent e) {
         System.out.printf("Thread %s has modified an entry in the cache named %s under key %s!\n",
                           Thread.currentThread().getName(), e.getCache().getName(), e.getKey());
      }

      @CacheEntryVisited
      public void pribtDetailsOnVisit(CacheEntryVisitedEvent e) {
         System.out.printf("Thread %s has visited an entry in the cache named %s under key %s!\n",
                           Thread.currentThread().getName(), e.getCache().getName(), e.getKey());
      }
   }
}

This class is part of the 5 minutes quickstart tutorial to Infinispan and provides a simple and effective way to demonstrate some basic cache functionalities, the cache lifespan of entries, recording asynchronous operations in the cache, and registering listener to cache, which will notify your application when an entry has been created/moded/removed/visited.

Additionally, we will enrich the project with the SampleCacheContainer class which will be used to retrieves the embedded cache manager and the single named caches contained in the configuration file.
package com.sample;

import org.infinispan.Cache;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;

import java.io.IOException;

/**
 * This sample cache container acts as a factory and a mechanism with which to create and configure an embedded cache
 * manager, and to hold this cache manager such that other code can access it.
 */
public class SampleCacheContainer {

   private static final String INFINISPAN_CONFIGURATION = "infinispan-local.xml";
   private static final EmbeddedCacheManager CACHE_MANAGER;

   static {
      try {
         CACHE_MANAGER = new DefaultCacheManager(INFINISPAN_CONFIGURATION);
      } catch (IOException e) {
         throw new RuntimeException("Unable to configure Infinispan", e);
      }
   }

   /**
    * Retrieves the default cache.
    * @param <K> type used as keys in this cache
    * @param <V> type used as values in this cache
    * @return a cache
    */
   public static <K, V> Cache<K, V> getCache() {
      return CACHE_MANAGER.getCache();
   }

   /**
    * Retrieves a named cache.
    * @param cacheName name of cache to retrieve
    * @param <K> type used as keys in this cache
    * @param <V> type used as values in this cache
    * @return a cache
    */
   public static <K, V> Cache<K, V> getCache(String cacheName) {
      if (cacheName == null) throw new NullPointerException("Cache name cannot be null!");
      return CACHE_MANAGER.getCache(cacheName);
   }

   /**
    * Retrieves the embedded cache manager.
    * @return a cache manager
    */
   public static EmbeddedCacheManager getCacheContainer() {
      return CACHE_MANAGER;
   }
}

The configuration file, "infinispan-local.xml" used by the SampleCacheContainer, will be added into the resources folder of your application
<?xml version="1.0" encoding="UTF-8"?>

<infinispan
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:infinispan:config:5.0 http://www.infinispan.org/schemas/infinispan-config-5.0.xsd"
      xmlns="urn:infinispan:config:5.0">

   <global>
      <globalJmxStatistics enabled="true" jmxDomain="Infinispan" />
   </global>

   <default>
      <locking concurrencyLevel="5000" />
   </default>

   <namedCache name="stock tickers">
      <locking isolationLevel="REPEATABLE_READ" useLockStriping="false" lockAcquisitionTimeout="10000" />
   </namedCache>

   <namedCache name="wine cache">
      <locking lockAcquisitionTimeout="500" />
      <eviction maxEntries="500" wakeUpInterval="100" />
      <lazyDeserialization enabled="true" />
   </namedCache>

   <namedCache name="another">
      <expiration lifespan="1000" maxIdle="500" />
   </namedCache>

</infinispan>

Here's how the project should look like in your Eclipse editor:
infinispan maven jboss infinispan maven jboss

Now what we need is adding a dependency into the pom.xml so that the project will be able to use Infinispan libraries:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.sample</groupId>
   <artifactId>com.mastertheboss</artifactId>
   <packaging>jar</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>A sample project using Infinispan</name>
   <url>http://www.myorganization.org</url>

   <properties>
      <version.infinispan>5.1.5.FINAL</version.infinispan>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.infinispan</groupId>
         <artifactId>infinispan-core</artifactId>
         <version>${version.infinispan}</version>
      </dependency>
   </dependencies>
        <!--
         Just in case you have not configured a Repository for JBoss projects in settings.xml
        -->
   <repositories>
      <repository>
         <id>JBoss.org Public Repository</id>
         <releases>
            <enabled>true</enabled>
         </releases>
         <snapshots>
            <enabled>true</enabled>
         </snapshots>
         <url>http://repository.jboss.org/nexus/content/groups/public/</url>
      </repository>
   </repositories>

</project>

The repositories section has been added just in case that your Maven's settings.xml file does not contain a repository for JBoss libraries (you can skip this section if you have already configured it in settings.xml)

Now you can run your application by right-clicking on your pom.xml and specifying the main class which will execute.
maven infinispan example jboss maven infinispan example jboss

Follow us on Twitter