Stardust/Knowledge Base/Infrastructure System Administration Maintenance/Model Deployment

From Eclipsepedia

Jump to: navigation, search

 Process Model Deployment

For general information about process model deployment please refer online documentation.

Refreshing the Model Cache

In an environment where several server instances are not running as a real (EJB) cluster but synchronize only via the database (e.g. Spring) the model caches of the instances can get out of sync. After a model has been deployed via one particular server instance the other instances have to be notified of the change so they can flush and reload their local model caches. The console command below can be used to do this (username and password have to be replaced with the credentials of a user having the Administrator role). Obviously restarting a server instance or reloading the web application will also refresh the local model cache.

console -u user -p password engine -init

Model Synchronization via a clustered Model Cache

Process models deployed into a runtime are stored into the Audit Trail database. The object model, however, is loaded into memory to guarantee fast access to process model information during process execution. The model cache is updated whenever a new process model is deployed. That means as soon as the model deployment is done and the model cache updated, new processes will behave on basis of the new process model version. The model cache is a cache per JVM. Therefore in clustered environments the model cache is updated on the node on which the deployment has been applied only. There's no inbuilt automatism yet, that would take care of model cache synchronization across multiple nodes within a cluster. Caches need to be flushed per node explicitly by using console command line tool, which causes an operational overhead.

There’s, however, a simple way to enable an automatic model cache synchronization across multiple nodes within a cluster by using Hazelcast distributed caching technology.

  1. Save the hazelcast-1.9.jar into the WEB-INF/lib of your IPP web application.
  2. Make the ModelWatcher.java (find source code below) part of one of your custom JAR deployments (or create a new JAR if necessary)
  3. Set the property Model.Watcher = com.infinity.bpm.model.ModelWatcher in your carnot.properties.

Please note: The automatic model cache synchronization does only work for deployments of process model version. It does not work for overwrite and model delete operation. Both, however, are not meant to be applied in productive environment outside a maintenance window.

 
 
package com.infinity.bpm.model;
 
import ag.carnot.base.log.LogManager;
import ag.carnot.base.log.Logger;
import ag.carnot.workflow.runtime.QueryService;
import ag.carnot.workflow.runtime.beans.QueryServiceImpl;
import ag.carnot.workflow.spi.cluster.Watcher;
 
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.ITopic;
import com.hazelcast.core.MessageListener;
 
@SuppressWarnings("unchecked")
public class ModelWatcher implements Watcher, MessageListener {
 
	private static final Logger logger = LogManager
			.getLogger(ModelWatcher.class);
 
	private boolean dirty;
 
	private Object globalState;
 
	private ITopic modelTopic;
 
	private QueryService qService;
 
	public ModelWatcher() {
 
		this.modelTopic = Hazelcast.getTopic("model");
		this.modelTopic.addMessageListener(this);
 
		logger.info("Member added to model change listener.");
 
		this.qService = new QueryServiceImpl();
	}
 
	public Object getGlobalState() {
		return globalState;
	}
 
	public boolean isDirty() {
		return this.dirty;
	}
 
	public void setDirty() {
 
		logger.info("Model changed. Notify listeners.");
 
		this.globalState = this.qService.getActiveModel().getModelOID();
 
		this.modelTopic.publish(this.globalState);
 
	}
 
	public void updateState(Object globalState) {
		logger.info("Model changed. Reload model.");
		this.qService = new QueryServiceImpl();
		this.globalState = qService.getActiveModel().getModelOID();
		this.dirty = false;
	}
 
	public void onMessage(Object msg) {
 
		logger.info("Received model change notification.");
 
		if (msg instanceof Integer) {
			Integer modelOid = (Integer) msg;
			if (this.globalState != modelOid) {
				this.dirty = true;
			}
		}
	}
 
}