Monday, April 21, 2014

How to use sling thread pool in CQ/AEM

Use Case: You are designing an application where you might need to delegate Job to a separate thread and you want to control this using thread pool so that your application it self does not run out of threads.

Prerequisite: Knowledge of Java Threads and basic Knowledge of thread pool. Note that there are Java Level thread pool as well that you can use. Check http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html for that.

Reference: https://sling.apache.org/documentation/bundles/apache-sling-commons-thread-pool.html

Implementation Example:

Step 1: Create your Thread class

public YourThreadClass implements Runnable {


 public void run() {
    //Your custom logic
}
}

Step 2: Main class to use sling Thread pool

import java.util.Map;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.commons.threads.ModifiableThreadPoolConfig;
import org.apache.sling.commons.threads.ThreadPool;
import org.apache.sling.commons.threads.ThreadPoolConfig.ThreadPriority;
import org.apache.sling.commons.threads.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Component
@Service
public class YourTestClassService {
private static final Logger LOGGER = LoggerFactory.getLogger(YourTestClassService.class);

@Reference
    private ThreadPoolManager threadPoolManager;

    /** your thread pool */
    private ThreadPool threadPool;

@Property(label = "minThreadPoolSize", description="Minium Thread pool size", intValue=5)
  private static final String MINIMUM_THREAD_POOL_SIZE = "minThreadPoolSize";
  private int minThreadPoolSize;
 
  @Property(label = "maxThreadPoolSize", description="Max Thread pool size", intValue=10)
  private static final String MAXUIMUM_THREAD_POOL_SIZE = "maxThreadPoolSize";
  private int maxThreadPoolSize;

  @Activate
  protected final void activate(final Map<Object, Object> config) {
    this.minThreadPoolSize = OsgiUtil.toInteger(config.get(MINIMUM_THREAD_POOL_SIZE), 5);
    this.maxThreadPoolSize = OsgiUtil.toInteger(config.get(MAXUIMUM_THREAD_POOL_SIZE), 10);
    ModifiableThreadPoolConfig threadPoolConfig = new ModifiableThreadPoolConfig();
    if(threadPoolConfig.getMinPoolSize()<this.minThreadPoolSize) {
      threadPoolConfig.setMinPoolSize(this.minThreadPoolSize);
    }
    if(threadPoolConfig.getMaxPoolSize()<this.maxThreadPoolSize) {
      threadPoolConfig.setMaxPoolSize(this.maxThreadPoolSize);
    }
    //You can make this configurable as well
    threadPoolConfig.setPriority(ThreadPriority.NORM);
    this.threadPool = threadPoolManager.create(threadPoolConfig);
    if(threadPool == null) {
      throw new IllegalStateException("Could not get a ThreadPool");
    }
  }

  @Deactivate
  protected void deactivate(ComponentContext ctx) throws Exception {
   if(threadPool != null) {
      threadPoolManager.release(threadPool);
      threadPoolManager = null;
      threadPool = null;
    }
  }

  public void yourMethod(){
  YourThreadClass your_thread_class = new YourThreadClass();
  Runnable YOUR_CUSTOM_THREAD = new Thread(your_thread_class);
  this.threadPool.execute(YOUR_CUSTOM_THREAD);
  }

}



Use CQ dependency finder to find what dependency you need for above code in your pom.xml

2 comments:

  1. Nice use case. We will promote this from with Adobe.

    ReplyDelete
  2. Thanks for this great share. This site is a fantastic resource. Keep up the great work here at Sprint Connection! Many thanks.

    Southbay Pool Cleaning Services

    ReplyDelete