Replication Handlers
Overview
Newton provides an extensible mechanism for specifying how many of a given composite should be deployed to a Newton fabric. This mechanism is via the ReplicationHandler and ReplicationHandlerFactory interfaces. ReplicationHandlers can provide dynamic scalability to composites within a Newton fabric.
API
In order to build a replication handler you should implement the following interfaces:
package org.cauldron.newton.system.api;
import java.util.Collection;
import org.cauldron.newton.model.component.CompositeInstance;
import org.cauldron.newton.model.system.SystemCompositeDescriptor;
public interface ReplicationHandler {
void initialise(SystemContext ctx) throws SystemConfigurationException;
SystemContext getSystemContext() throws SystemConfigurationException;
Collection<CompositeInstance> replicate(SystemCompositeDescriptor template, SystemStateModel model) throws SystemConfigurationException;
void destroy(SystemContext ctx);
}
package org.cauldron.newton.system.api;
import org.cauldron.newton.model.system.ReplicationDescriptor;
public interface ReplicationHandlerFactory {
ReplicationHandler createNewHandler(ReplicationDescriptor descriptor) throws SystemConfigurationException;
}
The ReplicationHandler does the actual work of building composites based on templates supplied from the system document. The ReplicationHandlerFactory is registered in the OSGi registry of the Newton instance running the system manager – this creates instances of ReplicationHandlers based on the configuration supplied via the ReplicationDescriptor element.
Example
The following example shows a ReplicationHandler that deploys composites only at specified times of the day:
package com.example.replication;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import org.cauldron.newton.system.replication.SimpleReplicationHandler;
import org.cauldron.newton.system.api.ReplicationHandler;
import org.cauldron.newton.system.api.SystemConfigurationException;
import org.cauldron.newton.system.api.SystemContext;
public class WorkingDayReplicationHandler extends SimpleReplicationHandler implements ReplicationHandler {
private int count;
private int hourStart;
private int hourEnd;
private Timer timer;
public WorkingDayReplicationHandler(Map<?, ?> config) {
Integer i = (Integer) config.get("count");
if ( i != null ) {
count = i;
}
i = (Integer) config.get("hourStart");
if ( i != null ) {
hourStart = i;
}
i = (Integer) config.get("hourEnd");
if ( i != null ) {
hourEnd = i;
}
}
public void initialise(SystemContext ctx) throws SystemConfigurationException {
super.initialise(ctx);
timer = new Timer();
scheduleRecheck();
}
public void destroy(SystemContext ctx) {
timer.cancel();
timer = null;
super.destroy( ctx );
}
@Override
protected int calculateRequired() throws SystemConfigurationException {
return isWorkingHours() ? count : 0;
}
private boolean isWorkingHours() {
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
return hourStart < hour && hourEnd > hour;
}
private void scheduleRecheck() {
TimerTask recheck = new TimerTask() {
@Override
public void run() {
try {
getSystemContext().rebuild(0);
scheduleRecheck();
} catch (SystemConfigurationException e) {
e.printStackTrace();
}
}
};
if ( isWorkingHours() ) {
timer.schedule(recheck, nextCheck(hourEnd));
}
else {
timer.schedule(recheck, nextCheck(hourStart));
}
}
private Date nextCheck(int hour) {
Calendar c = Calendar.getInstance();
if (c.get(Calendar.HOUR_OF_DAY) > hour) {
c.add(Calendar.DAY_OF_YEAR, 1);
}
c.set(Calendar.HOUR_OF_DAY, hour);
return c.getTime();
}
}
This replication handler is then plugged into the system manager via the following factory:
package org.cauldron.newton.system.replication;
import java.util.Map;
import org.cauldron.newton.model.system.ReplicationDescriptor;
import org.cauldron.newton.system.api.ReplicationHandler;
import org.cauldron.newton.system.api.ReplicationHandlerFactory;
import org.cauldron.newton.system.api.SystemConfigurationException;
public class ExampleReplicationHandlerFactory implements ReplicationHandlerFactory {
public ReplicationHandler createNewHandler(ReplicationDescriptor descriptor) {
if ( "com.example.workday".equals( descriptor.getType() ) ) {
Map<?,?> config = descriptor.getConfig();
return new WorkingDayReplicationHandler( config );
}
else {
return null;
}
}
}
To use this replication handler you would use the following mark up in a system document:
<replication.handler name="workday" type="com.example.workday">
<property name="count" value="10" type="integer"/>
<property name="hourStart" value="9" type="integer"/>
<property name="hourEnd" value="17" type="integer"/>
</replication.handler>


