Skip to content

Commit

Permalink
Merge pull request #1347 from JanssenProject/agama-issue_1340
Browse files Browse the repository at this point in the history
feat: allow flows to access their metadata properties #1340
  • Loading branch information
yurem committed May 17, 2022
2 parents 26b1163 + 344ba04 commit 3c15e44
Show file tree
Hide file tree
Showing 13 changed files with 1,133 additions and 870 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import io.jans.agama.model.EngineConfig;
import io.jans.util.Pair;
import io.jans.service.cdi.util.CdiUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -24,7 +26,7 @@ public class LogUtils {
//MUST be a single character string
private static final String PLACEHOLDER = "%";

private static final int MAX_ITERABLE_ITEMS = ScriptUtils.managedBean(EngineConfig.class)
private static final int MAX_ITERABLE_ITEMS = CdiUtil.bean(EngineConfig.class)
.getMaxItemsLoggedInCollections();

private enum LogLevel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
import io.jans.agama.engine.misc.PrimitiveUtils;
import io.jans.agama.engine.service.ActionService;
import io.jans.agama.engine.service.FlowService;
import io.jans.service.cdi.util.CdiUtil;
import io.jans.util.Pair;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeContinuation;
import org.mozilla.javascript.NativeJavaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -98,27 +101,28 @@ public static boolean testEquality(Object a, Object b) {
}

//Issue a call to this method only if the request scope is active
public static Function prepareSubflow(String qname, String parentBasepath, String[] pathOverrides)
throws IOException {
return managedBean(FlowService.class).prepareSubflow(qname, parentBasepath, pathOverrides);
public static Pair<Function, NativeJavaObject> prepareSubflow(String qname, String parentBasepath,
String[] pathOverrides) throws IOException {

return CdiUtil.bean(FlowService.class).prepareSubflow(qname, parentBasepath, pathOverrides);

}

public static Object callAction(Object instance, String actionClassName, String methodName,
Object[] params) throws Exception {

return managedBean(ActionService.class).callAction(instance, actionClassName, methodName, params);
return CdiUtil.bean(ActionService.class).callAction(instance, actionClassName, methodName, params);
//TODO: remove?
//if (Map.class.isInstance(value) && !NativeJavaMap.class.equals(value.getClass())) {
// Scriptable scope = managedBean(FlowService.class).getGlobalScope();
// Scriptable scope = CdiUtil.bean(FlowService.class).getGlobalScope();
// return new NativeJavaMap(scope, value);
//}

}

//Issue a call to this method only if the request scope is active
public static void closeSubflow() throws IOException {
managedBean(FlowService.class).closeSubflow();
CdiUtil.bean(FlowService.class).closeSubflow();
}

private static String simpleName(Class<?> cls) {
Expand All @@ -134,9 +138,5 @@ private static String simpleName(Class<?> cls) {
return name;

}

public static <T> T managedBean(Class<T> cls) {
return CDI.current().select(cls).get();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.mozilla.javascript.NativeContinuation;
import org.mozilla.javascript.NativeJavaList;
import org.mozilla.javascript.NativeJavaMap;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Scriptable;
Expand Down Expand Up @@ -113,7 +114,7 @@ public FlowStatus startFlow(FlowStatus status) throws FlowCrashException {
logger.info("Executing function {}", funcName);
Function f = (Function) globalScope.get(funcName, globalScope);

Object[] params = getFlowParams(fl.getInputs(), status.getJsonInput());
Object[] params = getFuncParams(fl, status.getJsonInput());
NativeObject result = (NativeObject) scriptCtx.callFunctionWithContinuations(f, globalScope, params);
finishFlow(result, status);

Expand Down Expand Up @@ -175,9 +176,9 @@ public FlowStatus continueFlow(FlowStatus status, String jsonParameters, boolean
}

// This is called in the middle of a cx.resumeContinuation invocation (see util.js#_flowCall)
public Function prepareSubflow(String subflowName, String parentBasepath, String[] pathOverrides)
throws IOException {
public Pair<Function, NativeJavaObject> prepareSubflow(String subflowName, String parentBasepath,
String[] pathOverrides) throws IOException {

Flow flow = aps.getFlow(subflowName, false);
FlowMetadata fl = flow.getMetadata();
String funcName = fl.getFuncName();
Expand All @@ -193,13 +194,14 @@ public Function prepareSubflow(String subflowName, String parentBasepath, String
Function f = (Function) globalScope.get(funcName, globalScope);
//The values set below are useful when saving the state, see method processPause

ParentFlowData pfd = new ParentFlowData();
ParentFlowData pfd = new ParentFlowData();
pfd.setParentBasepath(parentBasepath);
pfd.setPathOverrides(pathOverrides);
parentFlowData = pfd;

logger.info("Evaluating subflow code");
return f;
Map<String, Object> configs = Optional.ofNullable(fl.getProperties()).orElse(Collections.emptyMap());
return new Pair<>(f, wrapListOrMap(configs));

}

Expand Down Expand Up @@ -312,38 +314,49 @@ private String computeTemplatePath(String path, ParentFlowData pfd) {

}

private Object[] getFlowParams(List<String> inputNames, String strParams) throws JsonProcessingException {

List<String> inputs = Optional.ofNullable(inputNames).orElse(Collections.emptyList());
Object[] params = new Object[inputs.size()];
private Object[] getFuncParams(FlowMetadata metadata, String strParams) throws JsonProcessingException {
List<String> inputs = Optional.ofNullable(metadata.getInputs()).orElse(Collections.emptyList());
Map<String, Object> configs = Optional.ofNullable(metadata.getProperties()).orElse(Collections.emptyMap());

Object[] params = new Object[inputs.size() + 1];
params[0] = wrapListOrMap(configs);

if (strParams != null) {
Map<String, Object> map = mapper.readValue(strParams, new TypeReference<Map<String, Object>>(){});
for (int i = 0; i < params.length; i++) {
params[i] = map.get(inputs.get(i));
for (int i = 1; i < params.length; i++) {
params[i] = map.get(inputs.get(i - 1));
}
}
for (int i = 0; i < params.length; i++) {
String input = inputs.get(i);
for (int i = 1; i < params.length; i++) {
String input = inputs.get(i - 1);

if (params[i] == null) {
logger.warn("Setting parameter '{}' to null", input);
} else {
logger.debug("Setting parameter '{}' to an instance of {}", input, params[i].getClass().getName());

//This helps prevent exception "Invalid JavaScript value of type ..."
//when typeof is applied over this param in JavaScript code
if (Map.class.isInstance(params[i])) {
params[i] = new NativeJavaMap(globalScope, params[i]);
} else if (List.class.isInstance(params[i])) {
params[i] = new NativeJavaList(globalScope, params[i]);
}
NativeJavaObject wrapped = wrapListOrMap(params[i]);
params[i] = wrapped == null ? params[i] : wrapped;
}
}
return params;

}

private NativeJavaObject wrapListOrMap(Object obj) {

//This helps prevent exception "Invalid JavaScript value of type ..."
//when typeof is applied over this param in JavaScript code
if (Map.class.isInstance(obj)) {
return new NativeJavaMap(globalScope, obj);
} else if (List.class.isInstance(obj)) {
return new NativeJavaList(globalScope, obj);
}
return null;

}

private void makeCrashException(Exception e) throws FlowCrashException {

String msg;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public class ExecutionServlet extends BaseServlet {
public static final String URL_PREFIX = "/fl/";
public static final String CALLBACK_PATH = URL_PREFIX + "callback";
public static final String ABORT_PATH = URL_PREFIX + "abort";

//TODO: put string in agama resource bundle
private static final String NO_ACTIVE_FLOW = "No flow running currently " +
"or your flow may have already finished/timed out";

@Inject
private Logger logger;
Expand All @@ -48,7 +52,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response)
String path = request.getServletPath();

if (fstatus == null || fstatus.getStartedAt() == FlowStatus.FINISHED) {
sendNotFound(response);
sendNotFound(response, NO_ACTIVE_FLOW);
return;
}

Expand Down Expand Up @@ -97,7 +101,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
String path = request.getServletPath();

if (fstatus == null || fstatus.getStartedAt() == FlowStatus.FINISHED) {
sendNotFound(response);
sendNotFound(response, NO_ACTIVE_FLOW);
return;
}

Expand Down Expand Up @@ -135,7 +139,7 @@ public void service(HttpServletRequest request, HttpServletResponse response)
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
} else {
sendNotFound(response);
sendNotFound(response, null);
logger.debug("Unexpected path {}", path);
}

Expand Down Expand Up @@ -181,17 +185,23 @@ private boolean processCallback(HttpServletRequest request, HttpServletResponse
if (fstatus.isAllowCallbackResume()) {
continueFlow(request, response, fstatus, true, false);
} else {
logger.warn("Unexpected incoming response at flow callback endpoint");
sendNotFound(response);
logger.warn("Unexpected incoming request at flow callback endpoint");
sendNotFound(response, null);
}
return true;
}
return false;

}

private void sendNotFound(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
private void sendNotFound(HttpServletResponse response, String msg) throws IOException {

if (msg == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
}

}

private void sendRedirect(HttpServletResponse response, String contextPath, FlowStatus fls,
Expand Down
10 changes: 5 additions & 5 deletions agama/model/src/main/java/io/jans/agama/model/FlowMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class FlowMetadata {
private long timestamp;

private String description;
private Map<String, Object> customProps;
private Map<String, Object> properties;

public String getFuncName() {
return funcName;
Expand Down Expand Up @@ -65,12 +65,12 @@ public void setDescription(String description) {
this.description = description;
}

public Map<String, Object> getCustomProps() {
return customProps;
public Map<String, Object> getProperties() {
return properties;
}

public void setCustomProps(Map<String, Object> customProps) {
this.customProps = customProps;
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}

}
Loading

0 comments on commit 3c15e44

Please sign in to comment.