Optimization Server - Run Add Issue Task
This task takes scenarioId and a text message as input, adds the message to the scenario issues collection, then returns an output collector of the modified scenario as a result.
@Configuration public class Tasks { @Bean public ScriptedTaskDescription addIssueWithOptimizationServerTask() { ScriptedTaskDescription task = new ScriptedTaskDescription("addIssueWithOptimizationServer", "Add Issue with OptimizationServer"); task.setDescription("Add an issue to the selected scenario, using an OptimizationServer task"); task.getScript() .addStatement(AskInputStatement.of("scenario", true, JobInputType.scenarioId(WRITABLE))) .addStatement(AskInputStatement.of("Issue Message", true, JobInputType.TEXT, "The text of the issue to add")) .addStatement(ExecuteOptimizationServerTaskStatement .forTaskId(StringExpression.of("Add Issue with OptimizationServer")) .withInput("Issue Message", VariableAccessExpression.of("Issue Message")) .withInput("inputCollector", ScenarioDataExpression.of(VariableAccessExpression.of("scenario"))) .withOutputScenario("outputCollector", VariableAccessExpression.of("scenario"), StringExpression.of("GeneIssue"), StringExpression.of("Activity"))); return task; } }
Note that the table names mentioned in the arguments of withOutputScenario
can include list expressions. That is, the corresponding line in the example above could have been written as follows:
.withOutputScenario("outputCollector", VariableAccessExpression.of("scenario"), ListExpression.of(StringExpression.of("GeneIssue"), StringExpression.of("Activity")))
A slightly different version of this task is a task that creates a new scenario (with a name given as input) and adds an issue message to the newly created scenario. To create a new scenario, we use StringExpression.idOfNewScenario()
as in the following task:
@Configuration public class Tasks { @Bean public ScriptedTaskDescription addIssueToNewScenarioWithOptimizationServerTask() { ScriptedTaskDescription task = new ScriptedTaskDescription("createScenarioAndAddIssueWithOptimizationServer", "Add Issue to new scenario"); task.setDescription("Add an issue to a new scenario, using an OptimizationServer task"); task.getScript() .addStatement(AskInputStatement.of("Issue Message", true, JobInputType.TEXT, "The text of the issue to add")) .addStatement(AskInputStatement.of("Scenario Name", true, JobInputType.TEXT, "The name of the scenario to create")) .addStatement(AskInputStatement.of("workspace", true, JobInputType.WORKSPACE_ID, "The Workspace where to create the new Scenario")) .addStatement(SetVariableStatement.of("scenarioId", StringExpression.idOfNewScenario(VariableAccessExpression.of("Scenario Name"), VariableAccessExpression.of("workspace")))) .addStatement(ExecuteOptimizationServerTaskStatement .forTaskId(StringExpression.of("Add Issue with OptimizationServer")) .withInput("Issue Message", VariableAccessExpression.of("Issue Message")) .withInput("inputCollector", ScenarioDataExpression.of(VariableAccessExpression.of("scenarioId"))) .withOutputScenario("outputCollector", VariableAccessExpression.of("scenarioId"), StringExpression.of("GeneIssue"))); return task; } }
The OptimizationServer task with id "Add Issue with OptimizationServer" (for both versions above) is defined in OptimizationServer tasks configuration in worker.yml
as follows:
tasks: - id: Add Issue with OptimizationServer implementationClassName: com.decisionbrain.gene.execution.worker.AddIssueTask description: This task adds an issue to the provided scenario inputs: - name: Issue Message type: TEXT description: The text of the issue to add required: true - name: inputCollector type: BINARY description: Collector with initial data required: true outputs: - name: outputCollector type: BINARY description: Collector with initial data plus added issue required: true
With the following implementation class:
import com.decisionbrain.optimserver.common.parameter.Parameter; import com.decisionbrain.optimserver.worker.api.ExecutionContext; import com.decisionbrain.optimserver.worker.api.Task; import com.decisionbrain.sample.model.Activity; import com.decisionbrain.sample.model.CapacityPlanning; import com.decisionbrain.sample.model.GeneIssue; import com.decisionbrain.sample.model.impl.CapacityPlanningFactoryImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Arrays; public class AddIssueTask implements Task { private static final Logger LOGGER = LoggerFactory.getLogger("AddIssueTask"); @Override public void execute(Parameter input, Parameter output, ExecutionContext context) { CapacityPlanning collector = getInputCollector(input); LOGGER.info("Seeing {} existing issues", collector.getIssues().size()); GeneIssue issue = collector.createGeneIssue(); issue.setSeverity("INFO"); issue.setMessage(new String(input.get("Issue Message"))); emitOutputCollector(output, collector); } private CapacityPlanning getInputCollector(Parameter input) { try { CapacityPlanning collector = new CapacityPlanningFactoryImpl().createCollector(); byte[] inputData = input.get("inputCollector"); collector.loadSnapshot(inputData); return collector; } catch (Exception e) { throw new RuntimeException("Error while preparing data", e); } } private void emitOutputCollector(Parameter output, CapacityPlanning collector) { try { output.emit("outputCollector", collector.saveSnapshot(Arrays.asList(Activity.class, GeneIssue.class))); } catch (IOException e) { throw new RuntimeException("Error while saving data", e); } } }