use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class ProcessInstanceMarshaller method marhsallProcessInstance.
public byte[] marhsallProcessInstance(ProcessInstance<?> processInstance) {
io.automatiko.engine.api.runtime.process.ProcessInstance pi = ((AbstractProcessInstance<?>) processInstance).internalGetProcessInstance();
if (pi == null) {
return null;
}
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
ProcessMarshallerWriteContext context = new ProcessMarshallerWriteContext(baos, ((io.automatiko.engine.workflow.base.instance.ProcessInstance) pi).getProcessRuntime(), null, env);
context.setProcessInstanceId(pi.getId());
context.setState(pi.getState());
String processType = pi.getProcess().getType();
context.stream.writeUTF(processType);
io.automatiko.engine.workflow.marshalling.impl.ProcessInstanceMarshaller marshaller = ProcessMarshallerRegistry.INSTANCE.getMarshaller(processType);
Object result = marshaller.writeProcessInstance(context, pi);
if (marshaller instanceof ProtobufRuleFlowProcessInstanceMarshaller && result != null) {
AutomatikoMessages.ProcessInstance _instance = (AutomatikoMessages.ProcessInstance) result;
PersisterHelper.writeToStreamWithHeader(context, _instance);
}
context.close();
((WorkflowProcessInstanceImpl) pi).disconnect();
return baos.toByteArray();
} catch (Exception e) {
throw new RuntimeException("Error while marshalling process instance", e);
}
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class ParticipantsAccessPolicy method whenInitiatorNotSetOrAsIdentity.
@SuppressWarnings("unchecked")
protected boolean whenInitiatorNotSetOrAsIdentity(IdentityProvider identityProvider, ProcessInstance<T> instance) {
if (identityProvider.isAdmin()) {
return true;
}
WorkflowProcessInstance pi = (WorkflowProcessInstance) ((AbstractProcessInstance<?>) instance).processInstance();
if (pi.getInitiator() == null || pi.getInitiator().isEmpty() || pi.getInitiator().equals(identityProvider.getName())) {
return true;
}
// next check if the user/group is assigned to any of the active user tasks that
// can make it eligible to access the instance
boolean result = ((WorkflowProcessInstanceImpl) pi).getNodeInstances(true).stream().filter(ni -> ni instanceof HumanTaskNodeInstance).anyMatch(ni -> {
HumanTaskWorkItem workitem = (HumanTaskWorkItem) ((HumanTaskNodeInstance) ni).getWorkItem();
return workitem.enforce(SecurityPolicy.of(identityProvider));
});
if (!result) {
result = instance.subprocesses().stream().anyMatch(spi -> whenInitiatorNotSetOrAsIdentity(identityProvider, (ProcessInstance<T>) spi));
}
return result;
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class CassandraProcessInstances method disconnect.
protected void disconnect(ProcessInstance instance) {
((AbstractProcessInstance<?>) instance).internalRemoveProcessInstance(() -> {
try {
Select select = selectFrom(config.keyspace().orElse("automatiko"), tableName).column(CONTENT_FIELD).whereColumn(INSTANCE_ID_FIELD).isEqualTo(literal(instance.id()));
ResultSet rs = cqlSession.execute(select.build());
Row row = rs.one();
if (row != null) {
byte[] reloaded = codec.decode(row.getByteBuffer(1).array());
return marshaller.unmarshallWorkflowProcessInstance(reloaded, process);
} else {
return null;
}
} catch (RuntimeException e) {
LOGGER.error("Unexpected exception thrown when reloading process instance {}", instance.id(), e);
return null;
}
});
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class $Type$Resource method create_$name$.
@APIResponses(value = { @APIResponse(responseCode = "400", description = "In case request given does not meet expectations", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "500", description = "In case of processing errors", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "409", description = "In case an instance already exists with given business key", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "403", description = "In case an instance cannot be created due to access policy by the caller", content = @Content(mediaType = "application/json")), @APIResponse(responseCode = "200", description = "Successfully created instance", content = @Content(mediaType = "application/json", schema = @Schema(implementation = $Type$Output.class))), @APIResponse(responseCode = "202", description = "Successfully accepted request to create instance (applies only to async execution mode)", content = @Content(mediaType = "application/json", schema = @Schema(implementation = $Type$Output.class))) })
@Operation(summary = "Creates new instance of $name$")
@POST()
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response create_$name$(@Context HttpHeaders httpHeaders, @QueryParam("businessKey") @Parameter(description = "Alternative id to be assigned to the instance", required = false) String businessKey, @Parameter(description = "User identifier as alternative autroization info", required = false, hidden = true) @QueryParam("user") final String user, @Parameter(description = "Groups as alternative autroization info", required = false, hidden = true) @QueryParam("group") final List<String> groups, @Parameter(description = "Indicates if instance metadata should be included", required = false) @QueryParam("metadata") @DefaultValue("false") final boolean metadata, @Parameter(description = "The input model for $name$ instance") $Type$Input resource) {
if (resource == null) {
resource = new $Type$Input();
}
final $Type$Input value = resource;
String execMode = httpHeaders.getHeaderString("X-ATK-Mode");
if ("async".equalsIgnoreCase(execMode)) {
String callbackUrl = httpHeaders.getHeaderString("X-ATK-Callback");
String startFromNode = httpHeaders.getHeaderString("X-ATK-StartFromNode");
ProcessInstance<$Type$> pi = process.createInstance(businessKey, mapInput(value, new $Type$()));
((AbstractProcessInstance<$Type$>) pi).unlock(true);
$Type$Output output = mapOutput(new $Type$Output(), pi.variables(), businessKey, pi.metadata());
Map<String, String> headers = httpHeaders.getRequestHeaders().entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> e.getValue().get(0)));
IdentityProvider identity = identitySupplier.buildIdentityProvider(user, groups);
IdentityProvider.set(null);
CompletableFuture.runAsync(() -> {
IdentityProvider.set(identity);
io.automatiko.engine.services.uow.UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
if (startFromNode != null) {
pi.startFrom(startFromNode);
} else {
pi.start();
}
tracing(pi);
$Type$Output result = getModel(pi, metadata);
io.automatiko.engine.workflow.http.HttpCallbacks.get().post(callbackUrl, result, httpAuth.produce(headers), pi.status());
return null;
});
});
ResponseBuilder builder = Response.accepted().entity(output);
return builder.build();
} else {
identitySupplier.buildIdentityProvider(user, groups);
return io.automatiko.engine.services.uow.UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
ProcessInstance<$Type$> pi = process.createInstance(businessKey, mapInput(value, new $Type$()));
String startFromNode = httpHeaders.getHeaderString("X-ATK-StartFromNode");
if (startFromNode != null) {
pi.startFrom(startFromNode);
} else {
pi.start();
}
tracing(pi);
ResponseBuilder builder = Response.ok().entity(getModel(pi, metadata));
return builder.build();
});
}
}
use of io.automatiko.engine.workflow.AbstractProcessInstance in project automatiko-engine by automatiko-io.
the class WorkflowFunction method callTemplate.
public void callTemplate($Type$ resource) {
AtomicBoolean hasData = new AtomicBoolean(true);
if (resource == null) {
resource = new $Type$();
hasData.set(false);
}
String typePrefix = "$TypePrefix$";
final $Type$ value = resource;
identitySupplier.buildIdentityProvider(null, Collections.emptyList());
FunctionContext ctx = io.automatiko.engine.services.uow.UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
String startFromNode = "$StartFromNode$";
ProcessInstance<$Type$> pi = value.getId() == null ? null : process.instances().findById(value.getId()).orElse(null);
if (pi != null) {
if (hasData.get()) {
pi.updateVariables(value);
}
pi.triggerNode(startFromNode);
} else {
pi = process.createInstance(value.getId(), value);
pi.startFrom(startFromNode);
}
String pid = (String) ((WorkflowProcessInstanceImpl) ((AbstractProcessInstance<$Type$>) pi).processInstance()).getMetaData().remove("ATK_FUNC_FLOW_ID");
if (pid == null) {
pid = id(pi);
}
((WorkflowProcessInstanceImpl) ((AbstractProcessInstance<$Type$>) pi).processInstance()).getMetaData().remove("ATK_FUNC_FLOW_COUNTER");
return new FunctionContext(pid, (List<String>) ((WorkflowProcessInstanceImpl) ((AbstractProcessInstance<$Type$>) pi).processInstance()).getMetaData().remove("ATK_FUNC_FLOW_NEXT"), getModel(pi));
});
if (ctx.nextNodes != null && eventSource != null) {
for (String nextNode : ctx.nextNodes) {
LOGGER.debug("Next function to trigger {}", sanitizeIdentifier(nextNode));
eventSource.produce(sanitizeIdentifier(nextNode), typePrefix + sanitizeIdentifier("$ThisNode$".toLowerCase()) + ctx.id, ctx.model);
}
}
}
Aggregations