Changing Code without a Restart
The @SupportCodeChange
annotation is used to tell the Space that your code has changed during runtime, affecting the Space task that needs to be executed. The Space can store multiple versions of the same task. This is useful in supporting client applications that may need to implement multiple different versions of a task.
This annotation can be used with:
Task Execution
The annotation can be used when defining task execution. For example, annotate your task with @SupportCodeChange(id="1")
. When the code changes, set the annotation to @SupportCodeChange(id="2")
, and the Space will load the new task.
import org.openspaces.core.executor.Task;
import com.gigaspaces.annotation.SupportCodeChange;
@SupportCodeChange(id="1")
public class DynamicTask implements Task<Integer> {
@Override
public Integer execute() throws Exception {
return new Integer(1);
}
}
import org.openspaces.core.executor.Task;
import com.gigaspaces.annotation.SupportCodeChange;
@SupportCodeChange(id="2")
public class DynamicTask implements Task<Integer> {
@Override
public Integer execute() throws Exception {
return new Integer(2);
}
}
GigaSpace gigaSpace = new GigaSpaceConfigurer(new SpaceProxyConfigurer("xapSpace")).gigaSpace();
DynamicTask task = new DynamicTask();
AsyncFuture<Integer> execute = gigaSpace.execute(task);
System.out.println(execute.get());
For detailed information about task execution, see the Task Execution topic.
Custom Change
The annotation can be used for custom change operations, as demonstrated in the example below.
import com.gigaspaces.annotation.SupportCodeChange;
import com.gigaspaces.client.CustomChangeOperation;
import com.gigaspaces.server.MutableServerEntry;
@SupportCodeChange(id="1")
public class MultiplyIntegerChangeOperation extends CustomChangeOperation {
private static final long serialVersionUID = 1L;
private final String path;
private final int multiplier;
public MultiplyIntegerChangeOperation(String path) {
this.path = path;
}
@Override
public String getName() {
return "multiplyInt";
}
public String getPath() {
return path;
}
@Override
public Object change(MutableServerEntry entry) {
int oldValue = (Integer) entry.getPathValue(path);
int newValue = oldValue * 10;
entry.setPathValue(path, newValue);
return newValue;
}
}
import com.gigaspaces.annotation.SupportCodeChange;
import com.gigaspaces.client.CustomChangeOperation;
import com.gigaspaces.server.MutableServerEntry;
@SupportCodeChange(id="2")
public class MultiplyIntegerChangeOperation extends CustomChangeOperation {
private static final long serialVersionUID = 1L;
private final String path;
public MultiplyIntegerChangeOperation(String path) {
this.path = path;
}
@Override
public String getName() {
return "multiplyInt";
}
public String getPath() {
return path;
}
@Override
public Object change(MutableServerEntry entry) {
int oldValue = (Integer) entry.getPathValue(path);
int newValue = oldValue * 20;
entry.setPathValue(path, newValue);
return newValue;
}
}
GigaSpace gigaSpace = new GigaSpaceConfigurer(new SpaceProxyConfigurer("xapSpace")).gigaSpace();
SQLQuery<Employee> query = new SQLQuery<Employee>(Employee.class, "salary > 50");
ChangeResult<Employee> result = gigaSpace.change(query,
new ChangeSet().custom(new MultiplyIntegerChangeOperation("salary")),
ChangeModifiers.RETURN_DETAILED_RESULTS);
For detailed information about the Custom Change operation, see the Custom Change topic.
Custom Aggregation
The annotation can also be used for custom aggregation operations, as demonstrated by the following example.
@SupportCodeChange(id ="1")
public class ConcatAggregator extends SpaceEntriesAggregator<String> {
private final String path;
private transient StringBuilder sb;
public ConcatAggregator(String path) {
this.path = path;
}
@Override
public String getDefaultAlias() {
return "concat(" + path + ")";
}
@Override
public void aggregate(SpaceEntriesAggregatorContext context) {
String value = (String) context.getPathValue(path);
if (value != null)
concat(value);
}
@Override
public String getIntermediateResult() {
return sb == null ? null : sb.toString();
}
@Override
public void aggregateIntermediateResult(String partitionResult) {
concat(partitionResult);
}
private void concat(String s) {
if (sb == null) {
sb = new StringBuilder(s);
} else {
sb.append(',').append(s);
}
}
}
@SupportCodeChange(id ="2")
public class ConcatAggregator extends SpaceEntriesAggregator<String> {
private final String path;
private transient StringBuilder sb;
public ConcatAggregator(String path) {
this.path = path;
}
@Override
public String getDefaultAlias() {
return "concat(" + path + ")";
}
@Override
public void aggregate(SpaceEntriesAggregatorContext context) {
String value = (String) context.getPathValue(path);
if (value != null)
concat(value);
}
@Override
public String getIntermediateResult() {
return sb == null ? null : sb.toString();
}
@Override
public void aggregateIntermediateResult(String partitionResult) {
concat(partitionResult);
}
private void concat(String s) {
if (sb == null) {
sb = new StringBuilder(s);
} else {
sb.append(':').append(s);
}
}
}
GigaSpace gigaSpace = new GigaSpaceConfigurer(new SpaceProxyConfigurer("xapSpace")).gigaSpace();
SQLQuery<Employee> query = new SQLQuery<Employee>(Employee.class, "salary > 50");
AggregationResult result = gigaSpace.aggregate(query, new AggregationSet().add(new ConcatAggregator("name")));
String concatResult = result.getString("concat(name)");
For detailed information about how to use custom aggregators, see the Aggregators topic.
Number of Caches
The default limit of class loaders (caches) is 3. when this limit is breached, the oldest cache is evicted in favor of the new one. This value can be modified via the following Space properties:
Property Name | Description | Default |
---|---|---|
space-config.remote-code.max-class-loaders | Limit number of class loaders (caches) | 3 |
space-config.remote-code.support.code.change | Enable/Disable code change | true |
@SupportCodeChange
annotations without an ID or with id=""
are not cached.
Limitations
- When using
@SupportCodeChange
, no new types can be introduced to the Space. - Anonymous classes and lambdas do not support the annotation.