diff options
33 files changed, 1403 insertions, 310 deletions
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java index caaa1842b..192653930 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019-2020 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -97,7 +97,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap */ @Override public void setContext(final Executor<?, ?, ?, ?> incomingParent, final AxState incomingAxState, - final ApexInternalContext incomingContext) { + final ApexInternalContext incomingContext) { // Save the state and context definition this.parent = incomingParent; this.axState = incomingAxState; @@ -108,7 +108,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap // Set a task executor for each task for (final Entry<AxArtifactKey, AxStateTaskReference> stateTaskReferenceEntry : axState.getTaskReferences() - .entrySet()) { + .entrySet()) { final AxArtifactKey taskKey = stateTaskReferenceEntry.getKey(); final AxStateTaskReference taskReference = stateTaskReferenceEntry.getValue(); @@ -125,20 +125,20 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap } else if (taskReference.getStateTaskOutputType().equals(AxStateTaskOutputType.LOGIC)) { // Get the state finalizer logic for this task final AxStateFinalizerLogic finalizerLogic = - axState.getStateFinalizerLogicMap().get(taskReference.getOutput().getLocalName()); + axState.getStateFinalizerLogicMap().get(taskReference.getOutput().getLocalName()); if (finalizerLogic == null) { // Finalizer logic for the task does not exist throw new StateMachineRuntimeException("state finalizer logic on task reference \"" + taskReference - + "\" on state \"" + axState.getId() + "\" does not exist"); + + "\" on state \"" + axState.getId() + "\" does not exist"); } // Create a state finalizer executor for the task task2StateFinalizerMap.put(taskKey, - executorFactory.getStateFinalizerExecutor(this, finalizerLogic, context)); + executorFactory.getStateFinalizerExecutor(this, finalizerLogic, context)); } else { // This should never happen but..... throw new StateMachineRuntimeException("invalid state output type on task reference \"" + taskReference - + "\" on state \"" + axState.getId() + "\""); + + "\" on state \"" + axState.getId() + "\""); } } } @@ -158,6 +158,10 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap for (final TaskExecutor taskExecutor : taskExecutorMap.values()) { taskExecutor.prepare(); } + + for (final StateFinalizerExecutor stateFinalizer : task2StateFinalizerMap.values()) { + stateFinalizer.prepare(); + } } /** @@ -165,13 +169,13 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap */ @Override public StateOutput execute(final long executionId, final Properties executionProperties, - final EnEvent incomingEvent) throws StateMachineException, ContextException { + final EnEvent incomingEvent) throws StateMachineException, ContextException { this.lastIncomingEvent = incomingEvent; // Check that the incoming event matches the trigger for this state if (!incomingEvent.getAxEvent().getKey().equals(axState.getTrigger())) { throw new StateMachineException("incoming event \"" + incomingEvent.getId() + "\" does not match trigger \"" - + axState.getTrigger().getId() + "\" of state \"" + axState.getId() + "\""); + + axState.getTrigger().getId() + "\" of state \"" + axState.getId() + "\""); } // The key of the task to execute @@ -194,7 +198,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap final TreeMap<String, Object> incomingValues = new TreeMap<>(); incomingValues.putAll(incomingEvent); final Map<String, Object> taskExecutionResultMap = - taskExecutorMap.get(taskKey).execute(executionId, executionProperties, incomingValues); + taskExecutorMap.get(taskKey).execute(executionId, executionProperties, incomingValues); final AxTask task = taskExecutorMap.get(taskKey).getSubject(); // Check if this task has direct output @@ -207,20 +211,20 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap final StateFinalizerExecutor finalizerLogicExecutor = task2StateFinalizerMap.get(taskKey); if (finalizerLogicExecutor == null) { throw new StateMachineException("state finalizer logic for task \"" + taskKey.getId() - + "\" not found for state \"" + axState.getId() + "\""); + + "\" not found for state \"" + axState.getId() + "\""); } // Execute the state finalizer logic to select a state output and to adjust the // taskExecutionResultMap stateOutputName = - finalizerLogicExecutor.execute(executionId, executionProperties, taskExecutionResultMap); + finalizerLogicExecutor.execute(executionId, executionProperties, taskExecutionResultMap); } // Now look up the the actual state output final AxStateOutput stateOutputDefinition = axState.getStateOutputs().get(stateOutputName); if (stateOutputDefinition == null) { throw new StateMachineException("state output definition for state output \"" + stateOutputName - + "\" not found for state \"" + axState.getId() + "\""); + + "\" not found for state \"" + axState.getId() + "\""); } // Create the state output and transfer all the fields across to its event @@ -242,7 +246,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap return stateOutput; } catch (final Exception e) { final String errorMessage = "State execution of state \"" + axState.getId() + "\" on task \"" - + (taskKey != null ? taskKey.getId() : "null") + "\" failed: " + e.getMessage(); + + (taskKey != null ? taskKey.getId() : "null") + "\" failed: " + e.getMessage(); LOGGER.warn(errorMessage); throw new StateMachineException(errorMessage, e); @@ -254,7 +258,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap */ @Override public final void executePre(final long executionId, final Properties executionProperties, - final EnEvent incomingEntity) throws StateMachineException { + final EnEvent incomingEntity) throws StateMachineException { throw new StateMachineException("execution pre work not implemented on class"); } @@ -277,6 +281,10 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap // Clean the task selector taskSelectExecutor.cleanUp(); } + + for (final StateFinalizerExecutor stateFinalizer : task2StateFinalizerMap.values()) { + stateFinalizer.cleanUp(); + } } /** diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java index 6fb28bca8..a46ddfb9e 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2020 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +21,7 @@ package org.onap.policy.apex.core.engine.executor; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -123,11 +125,8 @@ public class StateFinalizerExecutorTest { assertEquals("task input fields \"[InField0]\" are missing for task \"Task0:0.0.1\"", ex.getMessage()); } - try { - executor.executePre(0, null, incomingEvent); - } catch (Exception ex) { - assertEquals("executionProperties is marked @NonNull but is null", ex.getMessage()); - } + assertThatThrownBy(() -> executor.executePre(0, null, incomingEvent)) + .hasMessageMatching("^executionProperties is marked .*on.*ull but is null$"); try { executor.executePre(0, new Properties(), incomingEvent); @@ -140,7 +139,7 @@ public class StateFinalizerExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute() not implemented on abstract StateFinalizerExecutionContext class, " - + "only on its subclasses", ex.getMessage()); + + "only on its subclasses", ex.getMessage()); } try { @@ -148,7 +147,7 @@ public class StateFinalizerExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute-post: state finalizer logic execution failure on state \"NULL:0.0.0:NULL:NULL\" " - + "on finalizer logic null", ex.getMessage()); + + "on finalizer logic null", ex.getMessage()); } executor.getExecutionContext().setMessage("Execution message"); @@ -157,7 +156,7 @@ public class StateFinalizerExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute-post: state finalizer logic execution failure on state \"NULL:0.0.0:NULL:NULL\" " - + "on finalizer logic null, user message: Execution message", ex.getMessage()); + + "on finalizer logic null, user message: Execution message", ex.getMessage()); } try { @@ -171,7 +170,7 @@ public class StateFinalizerExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute-post: state finalizer logic \"null\" did not select an output state", - ex.getMessage()); + ex.getMessage()); } try { @@ -185,9 +184,10 @@ public class StateFinalizerExecutorTest { executor.executePost(true); fail("test should throw an exception"); } catch (Exception ex) { - assertEquals("execute-post: state finalizer logic \"null\" selected output state " - + "\"ThisOutputDoesNotExist\" that does not exsist on state \"NULL:0.0.0:NULL:NULL\"", - ex.getMessage()); + assertEquals( + "execute-post: state finalizer logic \"null\" selected output state " + + "\"ThisOutputDoesNotExist\" that does not exsist on state \"NULL:0.0.0:NULL:NULL\"", + ex.getMessage()); } try { diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java index c2abd1e96..7256b3f31 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2020 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +23,7 @@ package org.onap.policy.apex.core.engine.executor; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.LinkedHashMap; @@ -37,7 +39,6 @@ import org.onap.policy.apex.context.parameters.SchemaParameters; import org.onap.policy.apex.core.engine.ExecutorParameters; import org.onap.policy.apex.core.engine.context.ApexInternalContext; import org.onap.policy.apex.core.engine.event.EnEvent; -import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.service.ModelService; @@ -164,15 +165,15 @@ public class StateMachineExecutorTest { state1.getTaskReferences().put(task1Key, str1); Mockito.doReturn(new DummyTaskExecutor(true)).when(executorFactoryMock).getTaskExecutor(Mockito.anyObject(), - Mockito.anyObject(), Mockito.anyObject()); + Mockito.anyObject(), Mockito.anyObject()); dummyTsle = new DummyTaskSelectExecutor(true); Mockito.doReturn(dummyTsle).when(executorFactoryMock).getTaskSelectionExecutor(Mockito.anyObject(), - Mockito.anyObject(), Mockito.anyObject()); + Mockito.anyObject(), Mockito.anyObject()); dummySfle = new DummyStateFinalizerExecutor(true); Mockito.doReturn(dummySfle).when(executorFactoryMock).getStateFinalizerExecutor(Mockito.anyObject(), - Mockito.anyObject(), Mockito.anyObject()); + Mockito.anyObject(), Mockito.anyObject()); } @After @@ -183,8 +184,8 @@ public class StateMachineExecutorTest { @Test public void testStateMachineExecutor() { - StateMachineExecutor executor = new StateMachineExecutor(executorFactoryMock, - new AxArtifactKey("OwnerKey:0.0.1")); + StateMachineExecutor executor = + new StateMachineExecutor(executorFactoryMock, new AxArtifactKey("OwnerKey:0.0.1")); try { executor.execute(0, null, incomingEventMock); @@ -224,8 +225,9 @@ public class StateMachineExecutorTest { try { executor.prepare(); - } catch (StateMachineException e) { - fail("test should not throw an exception"); + fail("test should throw an exception"); + } catch (Exception e) { + assertTrue(e instanceof NullPointerException); } axPolicy.setFirstState("BadState"); @@ -260,11 +262,11 @@ public class StateMachineExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("state execution failed, next state \"Policy:0.0.1:PName:BadState\" not found", - ex.getMessage()); + ex.getMessage()); } axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1") - .setNextState(AxReferenceKey.getNullKey()); + .setNextState(AxReferenceKey.getNullKey()); dummyTsle.setTaskNo(0); try { executor.execute(0, null, incomingEventMock); @@ -279,7 +281,7 @@ public class StateMachineExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("incoming event \"Event1:0.0.1\" does not match trigger \"BadTrigger:0.0.1\" " - + "of state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); + + "of state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); } axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("Event1:0.0.1")); @@ -297,11 +299,11 @@ public class StateMachineExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("state finalizer logic on task reference " - + "\"AxStateTaskReference:(stateKey=AxReferenceKey:(parentKeyName=Policy," - + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1)," - + "outputType=LOGIC,output=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1," - + "parentLocalName=state1,localName=sfl))\" on state \"Policy:0.0.1:NULL:state1\" " - + "does not exist", ex.getMessage()); + + "\"AxStateTaskReference:(stateKey=AxReferenceKey:(parentKeyName=Policy," + + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1)," + + "outputType=LOGIC,output=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1," + + "parentLocalName=state1,localName=sfl))\" on state \"Policy:0.0.1:NULL:state1\" " + "does not exist", + ex.getMessage()); } axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", savedSfl); @@ -317,19 +319,19 @@ public class StateMachineExecutorTest { AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1"); try { axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key) - .setStateTaskOutputType(AxStateTaskOutputType.UNDEFINED); + .setStateTaskOutputType(AxStateTaskOutputType.UNDEFINED); executor.setContext(null, axPolicy, internalContextMock); fail("test should throw an exception"); } catch (Exception ex) { assertEquals("invalid state output type on task reference \"AxStateTaskReference:(stateKey=AxReferenceKey:" - + "(parentKeyName=Policy,parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1)," - + "outputType=UNDEFINED,output=AxReferenceKey:(parentKeyName=Policy," - + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=sfl))\" " - + "on state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); + + "(parentKeyName=Policy,parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1)," + + "outputType=UNDEFINED,output=AxReferenceKey:(parentKeyName=Policy," + + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=sfl))\" " + + "on state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); } axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key) - .setStateTaskOutputType(AxStateTaskOutputType.LOGIC); + .setStateTaskOutputType(AxStateTaskOutputType.LOGIC); executor.setContext(null, axPolicy, internalContextMock); dummyTsle.setTaskNo(0); @@ -346,8 +348,8 @@ public class StateMachineExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("State execution of state \"Policy:0.0.1:NULL:state1\" on task \"task1:0.0.1\" failed: " - + "state output definition for state output \"stateOutputBad\" not found for " - + "state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); + + "state output definition for state output \"stateOutputBad\" not found for " + + "state \"Policy:0.0.1:NULL:state1\"", ex.getMessage()); } dummyTsle.setTaskNo(0); @@ -360,15 +362,16 @@ public class StateMachineExecutorTest { try { executor.cleanUp(); + fail("test should throw an exception"); } catch (Exception ex) { - fail("test should not throw an exception"); + assertEquals("cleanUp() not implemented on class", ex.getMessage()); } } @Test public void testStateOutput() { - StateOutput output = new StateOutput( - axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0")); + StateOutput output = + new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0")); assertNotNull(output); assertEquals("stateOutput0", output.getStateOutputDefinition().getKey().getLocalName()); @@ -401,7 +404,7 @@ public class StateMachineExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("field definitions and values do not match for event Event1:0.0.1\n[]\n[key]", - ex.getMessage()); + ex.getMessage()); } AxField axBadFieldDefinition = new AxField(); diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java index 81b7d9424..a9218ea98 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java @@ -32,6 +32,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; + import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -208,7 +209,7 @@ public class TaskExecutorTest { executor.executePost(true); assertThatThrownBy(() -> executor.executePre(0, null, incomingFields)) - .hasMessageContaining("executionProperties is marked @NonNull but is null"); + .hasMessageMatching("^executionProperties is marked .*on.*ull but is null$"); } @Test diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java index 8e907e12a..817b1615f 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2020 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +21,7 @@ package org.onap.policy.apex.core.engine.executor; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -151,7 +153,7 @@ public class TaskSelectExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute-post: task selection logic failed on state \"State0Parent:0.0.1:Parent:State0\"", - ex.getMessage()); + ex.getMessage()); } executor.getExecutionContext().setMessage("Execution message"); @@ -160,7 +162,7 @@ public class TaskSelectExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("execute-post: task selection logic failed on state \"State0Parent:0.0.1:Parent:State0\", " - + "user message: Execution message", ex.getMessage()); + + "user message: Execution message", ex.getMessage()); } try { @@ -188,7 +190,7 @@ public class TaskSelectExecutorTest { fail("test should throw an exception"); } catch (Exception ex) { assertEquals("task \"IDontExist:0.0.0\" returned by task selection logic not defined " - + "on state \"State0Parent:0.0.1:Parent:State0\"", ex.getMessage()); + + "on state \"State0Parent:0.0.1:Parent:State0\"", ex.getMessage()); } try { @@ -206,11 +208,7 @@ public class TaskSelectExecutorTest { fail("test should not throw an exception"); } - try { - executor.executePre(0, null, incomingEvent); - fail("test should throw an exception"); - } catch (Exception ex) { - assertEquals("executionProperties is marked @NonNull but is null", ex.getMessage()); - } + assertThatThrownBy(() -> executor.executePre(0, null, incomingEvent)) + .hasMessageMatching("^executionProperties is marked .*on.*ull but is null$"); } } diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java index bef0a81c8..c8e38bc54 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestDummyGrpcServer.java @@ -17,17 +17,21 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.onap.policy.apex.examples.grpc; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; + import io.grpc.Server; import io.grpc.netty.NettyServerBuilder; import io.grpc.stub.StreamObserver; + import java.io.IOException; import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Paths; + import org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc.BluePrintProcessingServiceImplBase; import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; @@ -40,12 +44,18 @@ import org.onap.policy.apex.service.engine.event.ApexEventRuntimeException; public class GrpcTestDummyGrpcServer { private Server server; + /** + * Dummy server for gRPC. + * + * @param host hostname of the server + * @param port port of the server + */ public GrpcTestDummyGrpcServer(String host, int port) { // Implement the dummy gRPC server BluePrintProcessingServiceImplBase testCdsBlueprintServerImpl = new BluePrintProcessingServiceImplBase() { @Override - public StreamObserver<ExecutionServiceInput> process( - final StreamObserver<ExecutionServiceOutput> responseObserver) { + public StreamObserver<ExecutionServiceInput> + process(final StreamObserver<ExecutionServiceOutput> responseObserver) { return new StreamObserver<ExecutionServiceInput>() { @Override public void onNext(final ExecutionServiceInput executionServiceInput) { diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java index ae35d1ff2..fcdf55322 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java @@ -47,14 +47,14 @@ public class GrpcTestServerSim { restServer.addServletClass(null, GrpcTestRestSimEndpoint.class.getName()); restServer.setSerializationProvider(GsonMessageBodyHandler.class.getName()); restServer.start(); - if (!NetworkUtil.isTcpPortOpen(HOST, restServerPort, 2000, 1L)) { + if (!NetworkUtil.isTcpPortOpen(HOST, restServerPort, 50, 200L)) { throw new IllegalStateException("port " + restServerPort + " is still not in use"); } int grpcServerPort = 54322; grpcServer = new GrpcTestDummyGrpcServer(HOST, grpcServerPort); grpcServer.start(); - if (!NetworkUtil.isTcpPortOpen(HOST, grpcServerPort, 2000, 1L)) { + if (!NetworkUtil.isTcpPortOpen(HOST, grpcServerPort, 50, 200L)) { throw new IllegalStateException("port " + grpcServerPort + " is still not in use"); } } diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java index 06d1d33f9..05d6e4ce5 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.onap.policy.apex.examples.grpc; import static org.awaitility.Awaitility.await; @@ -25,18 +26,20 @@ import static org.junit.Assert.assertEquals; import java.nio.file.Files; import java.nio.file.Paths; import java.util.concurrent.TimeUnit; + import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.Response; + import org.junit.Test; import org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain; import org.onap.policy.apex.service.engine.main.ApexMain; /** - * Test class to run an example policy for APEX-CDS interaction over gRPC. - * Event received on unauthenticated.DCAE_CL_OUTPUT DMaaP topic (dummy REST Endpoint here) triggers the policy - * Based on the event, a create/delete subscription gRPC request is triggered to the CDS (a dummy gRPC server here). - * Response received from CDS is used to send a final output Log event on POLICY_CL_MGT topic. + * Test class to run an example policy for APEX-CDS interaction over gRPC. Event received on + * unauthenticated.DCAE_CL_OUTPUT DMaaP topic (dummy REST Endpoint here) triggers the policy Based on the event, a + * create/delete subscription gRPC request is triggered to the CDS (a dummy gRPC server here). Response received from + * CDS is used to send a final output Log event on POLICY_CL_MGT topic. */ public class TestApexGrpcExample { @Test @@ -65,21 +68,25 @@ public class TestApexGrpcExample { }; // @formatter:on - GrpcTestServerSim sim = new GrpcTestServerSim(); + final GrpcTestServerSim sim = new GrpcTestServerSim(); + final Client client = ClientBuilder.newClient(); - String expectedLoggedOutputEvent = Files - .readString(Paths.get("src/main/resources/examples/events/APEXgRPC/LogEvent.json")).replaceAll("\r", ""); final ApexMain apexMain = new ApexMain(apexArgs); + await().atMost(5000, TimeUnit.MILLISECONDS).until(() -> apexMain.isAlive()); + String getLoggedEventUrl = "http://localhost:54321/GrpcTestRestSim/sim/event/getLoggedEvent"; // wait for success response code to be received, until a timeout - await().atMost(5000, TimeUnit.MILLISECONDS).until(() -> { + await().atMost(20000, TimeUnit.MILLISECONDS).until(() -> { return 200 == client.target(getLoggedEventUrl).request("application/json").get().getStatus(); }); apexMain.shutdown(); Response response = client.target(getLoggedEventUrl).request("application/json").get(); sim.tearDown(); String responseEntity = response.readEntity(String.class); + + String expectedLoggedOutputEvent = Files + .readString(Paths.get("src/main/resources/examples/events/APEXgRPC/LogEvent.json")).replaceAll("\r", ""); assertEquals(expectedLoggedOutputEvent, responseEntity); } } diff --git a/examples/examples-myfirstpolicy/pom.xml b/examples/examples-myfirstpolicy/pom.xml index 16b49552c..6eebf6320 100644 --- a/examples/examples-myfirstpolicy/pom.xml +++ b/examples/examples-myfirstpolicy/pom.xml @@ -19,173 +19,217 @@ ============LICENSE_END========================================================= --> <project - xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.onap.policy.apex-pdp.examples</groupId> - <artifactId>examples</artifactId> - <version>2.3.1-SNAPSHOT</version> - </parent> + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.policy.apex-pdp.examples</groupId> + <artifactId>examples</artifactId> + <version>2.3.1-SNAPSHOT</version> + </parent> - <artifactId>examples-myfirstpolicy</artifactId> - <name>${project.artifactId}</name> - <description>Specific code for the Apex MyFirstPolicy Example</description> + <artifactId>examples-myfirstpolicy</artifactId> + <name>${project.artifactId}</name> + <description>Specific code for the Apex MyFirstPolicy Example</description> - <properties> - <policymodel1m.name>MyFirstPolicyModelMvel_0.0.1</policymodel1m.name> - <policymodel1j.name>MyFirstPolicyModelJavascript_0.0.1</policymodel1j.name> - <policymodel2.name>MyFirstPolicyModel_0.0.1</policymodel2.name> - </properties> + <properties> + <policymodel1m.name>MyFirstPolicyModelMvel_0.0.1</policymodel1m.name> + <policymodel1j.name>MyFirstPolicyModelJavascript_0.0.1</policymodel1j.name> + <policymodel2.name>MyFirstPolicyModel_0.0.1</policymodel2.name> + <policymodel3.name>MyFirstPolicyModelSFL_0.0.1</policymodel3.name> + </properties> - <dependencies> - <dependency> - <groupId>org.onap.policy.apex-pdp.model</groupId> - <artifactId>policy-model</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onap.policy.apex-pdp.core</groupId> - <artifactId>core-engine</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.apex-pdp.core</groupId> - <artifactId>core-infrastructure</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.apex-pdp.auth</groupId> - <artifactId>cli-editor</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onap.policy.apex-pdp.plugins.plugins-executor</groupId> - <artifactId>plugins-executor-mvel</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.onap.policy.apex-pdp.plugins.plugins-executor</groupId> - <artifactId>plugins-executor-javascript</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>org.onap.policy.apex-pdp.model</groupId> + <artifactId>policy-model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.apex-pdp.core</groupId> + <artifactId>core-engine</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.apex-pdp.core</groupId> + <artifactId>core-infrastructure</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.apex-pdp.auth</groupId> + <artifactId>cli-editor</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.onap.policy.apex-pdp.plugins.plugins-executor</groupId> + <artifactId>plugins-executor-mvel</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.apex-pdp.plugins.plugins-executor</groupId> + <artifactId>plugins-executor-javascript</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + </dependencies> - <build> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <!-- Generate the APEX Policy JSON files from the APEX CLI command --> + <execution> + <id>generate-policy1m</id> + <phase>compile</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> + <classpathScope>compile</classpathScope> + <arguments> + <argument> + --command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/1/${policymodel1m.name}.apex + </argument> + <argument> + --output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/1/${policymodel1m.name}.json + </argument> + <argument> + --log-file=${project.build.directory}/${policymodel1m.name}_policygeneration.log + </argument> + <argument>--working-dir=${project.basedir}</argument> + </arguments> + </configuration> + </execution> + <execution> + <id>generate-policy1j</id> + <phase>compile</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> + <classpathScope>compile</classpathScope> + <arguments> + <argument> + --command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/1/${policymodel1j.name}.apex + </argument> + <argument> + --output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/1/${policymodel1j.name}.json + </argument> + <argument> + --log-file=${project.build.directory}/${policymodel1j.name}_policygeneration.log + </argument> + <argument>--working-dir=${project.basedir}</argument> + </arguments> + </configuration> + </execution> + <execution> + <id>generate-policy2</id> + <phase>compile</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> + <classpathScope>compile</classpathScope> + <arguments> + <argument> + --command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/2/${policymodel2.name}.apex + </argument> + <argument> + --output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/2/${policymodel2.name}.json + </argument> + <argument> + --log-file=${project.build.directory}/${policymodel2.name}_policygeneration.log + </argument> + <argument>--working-dir=${project.basedir}</argument> + </arguments> + </configuration> + </execution> + <execution> + <id>generate-policy3</id> + <phase>compile</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> + <classpathScope>compile</classpathScope> + <arguments> + <argument> + --command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/3/${policymodel3.name}.apex + </argument> + <argument> + --output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/3/${policymodel3.name}.json + </argument> + <argument> + --log-file=${project.build.directory}/${policymodel3.name}_policygeneration.log + </argument> + <argument>--working-dir=${project.basedir}</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>apexSite</id> + <activation> + <property> + <name>apexSite</name> + </property> + </activation> + <properties> + <adsite-examples-myfirstpolicy-dir>${project.basedir}/src + </adsite-examples-myfirstpolicy-dir> + </properties> + <distributionManagement> + <site> + <id>${project.artifactId}-site</id> + <url>${apex.adsite.prefix}/modules/${project.parent.artifactId}/${project.artifactId}/ + </url> + </site> + </distributionManagement> + <build> <plugins> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <executions> - <!-- Generate the APEX Policy JSON files from the APEX CLI command --> - <execution> - <id>generate-policy1m</id> - <phase>compile</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> - <classpathScope>compile</classpathScope> - <arguments> - <argument>--command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/1/${policymodel1m.name}.apex</argument> - <argument>--output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/1/${policymodel1m.name}.json</argument> - <argument>--log-file=${project.build.directory}/${policymodel1.name}_policygeneration.log</argument> - <argument>--working-dir=${project.basedir}</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>generate-policy1j</id> - <phase>compile</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> - <classpathScope>compile</classpathScope> - <arguments> - <argument>--command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/1/${policymodel1j.name}.apex</argument> - <argument>--output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/1/${policymodel1j.name}.json</argument> - <argument>--log-file=${project.build.directory}/${policymodel1.name}_policygeneration.log</argument> - <argument>--working-dir=${project.basedir}</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>generate-policy2</id> - <phase>compile</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>org.onap.policy.apex.auth.clieditor.ApexCommandLineEditorMain</mainClass> - <classpathScope>compile</classpathScope> - <arguments> - <argument>--command-file=${project.basedir}/src/main/resources/examples/models/MyFirstPolicy/2/${policymodel2.name}.apex</argument> - <argument>--output-model-file=${project.build.directory}/classes/examples/models/MyFirstPolicy/2/${policymodel2.name}.json</argument> - <argument>--log-file=${project.build.directory}/${policymodel2.name}_policygeneration.log</argument> - <argument>--working-dir=${project.basedir}</argument> - </arguments> - </configuration> - </execution> - </executions> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>3.0.2</version> + <executions> + <execution> + <id>copy-domain-mfp-images</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <resources> + <resource> + <directory>${project.basedir}/src/site-docs/adoc/resources/images</directory> + <includes> + <include>**/*.jpg</include> + <include>**/*.png</include> + </includes> + </resource> + </resources> + <outputDirectory>${project.build.directory}/site/images</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> </plugins> - </build> - - <profiles> - <profile> - <id>apexSite</id> - <activation> - <property> - <name>apexSite</name> - </property> - </activation> - <properties> - <adsite-examples-myfirstpolicy-dir>${project.basedir}/src</adsite-examples-myfirstpolicy-dir> - </properties> - <distributionManagement> - <site> - <id>${project.artifactId}-site</id> - <url>${apex.adsite.prefix}/modules/${project.parent.artifactId}/${project.artifactId}/</url> - </site> - </distributionManagement> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-resources-plugin</artifactId> - <version>3.0.2</version> - <executions> - <execution> - <id>copy-domain-mfp-images</id> - <phase>initialize</phase> - <goals> - <goal>copy-resources</goal> - </goals> - <configuration> - <resources> - <resource> - <directory>${project.basedir}/src/site-docs/adoc/resources/images</directory> - <includes> - <include>**/*.jpg</include> - <include>**/*.png</include> - </includes> - </resource> - </resources> - <outputDirectory>${project.build.directory}/site/images</outputDirectory> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> - </profile> - </profiles> + </build> + </profile> + </profiles> </project> diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigFile2StdoutJsonEvent.json b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigFile2StdoutJsonEvent.json new file mode 100644 index 000000000..655945963 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigFile2StdoutJsonEvent.json @@ -0,0 +1,46 @@ +{ + "engineServiceParameters": { + "name": "MyFirstPolicyApexEngine", + "version": "0.0.1", + "id": 103, + "instanceCount": 4, + "deploymentPort": 12345, + "policyModelFileName": "examples/models/MyFirstPolicy/3/MyFirstPolicyModelSFL_0.0.1.json", + "engineParameters": { + "executorParameters": { + "MVEL": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters" + }, + "JAVASCRIPT": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" + } + } + } + }, + "eventOutputParameters": { + "FirstProducer": { + "carrierTechnologyParameters": { + "carrierTechnology": "FILE", + "parameters": { + "standardIo": true + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + }, + "eventInputParameters": { + "FirstConsumer": { + "carrierTechnologyParameters": { + "carrierTechnology": "FILE", + "parameters": { + "fileName": "examples/events/MyFirstPolicy/3/EventsIn.json.txt" + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + } +} diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigStdin2StdoutJsonEvent.json b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigStdin2StdoutJsonEvent.json new file mode 100644 index 000000000..6084d8d34 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigStdin2StdoutJsonEvent.json @@ -0,0 +1,46 @@ +{ + "engineServiceParameters": { + "name": "MyFirstPolicyApexEngine", + "version": "0.0.1", + "id": 101, + "instanceCount": 4, + "deploymentPort": 12345, + "policyModelFileName": "C:\\Users\\adityaputhuparambil\\onap\\apex\\examples\\examples-myfirstpolicy\\target\\examples\\models\\MyFirstPolicy\\3\\MyFirstPolicyModelSFL_0.0.1.json", + "engineParameters": { + "executorParameters": { + "MVEL": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters" + }, + "JAVASCRIPT": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" + } + } + } + }, + "eventOutputParameters": { + "FirstProducer": { + "carrierTechnologyParameters": { + "carrierTechnology": "FILE", + "parameters": { + "standardIo": true + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + }, + "eventInputParameters": { + "FirstConsumer": { + "carrierTechnologyParameters": { + "carrierTechnology": "FILE", + "parameters": { + "standardIo": true + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + } +} diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigWs2WsServerJsonEvent.json b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigWs2WsServerJsonEvent.json new file mode 100644 index 000000000..14d6a43b0 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/config/MyFirstPolicy/3/MyFirstPolicyConfigWs2WsServerJsonEvent.json @@ -0,0 +1,50 @@ +{ + "engineServiceParameters": { + "name": "MyFirstPolicyApexEngine", + "version": "0.0.1", + "id": 101, + "instanceCount": 4, + "deploymentPort": 12345, + "policyModelFileName": "examples/models/MyFirstPolicy/3/MyFirstPolicyModelSFL_0.0.1.json", + "engineParameters": { + "executorParameters": { + "MVEL": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters" + }, + "JAVASCRIPT": { + "parameterClassName": "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" + } + } + } + }, + "eventOutputParameters": { + "aProducer": { + "carrierTechnologyParameters": { + "carrierTechnology": "WEBSOCKET", + "parameterClassName": "org.onap.policy.apex.plugins.event.carrier.websocket.WebSocketCarrierTechnologyParameters", + "parameters": { + "wsClient": false, + "port": 4000 + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + }, + "eventInputParameters": { + "aConsumer": { + "carrierTechnologyParameters": { + "carrierTechnology": "WEBSOCKET", + "parameterClassName": "org.onap.policy.apex.plugins.event.carrier.websocket.WebSocketCarrierTechnologyParameters", + "parameters": { + "wsClient": false, + "port": 3000 + } + }, + "eventProtocolParameters": { + "eventProtocol": "JSON" + } + } + } +} diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_084106GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_084106GMT.json new file mode 100644 index 000000000..4c5af6c2d --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_084106GMT.json @@ -0,0 +1,12 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1483346466000, + "sale_ID": 99999992, + "amount": 1249, + "item_ID": 1012, + "quantity": 1, + "assistant_ID": 12, + "branch_ID": 2 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_201713GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_201713GMT.json new file mode 100644 index 000000000..cc18e7ddd --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_BoozeItem_201713GMT.json @@ -0,0 +1,12 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1482265033000, + "sale_ID": 99999993, + "amount": 4799, + "item_ID": 1943, + "quantity": 2, + "assistant_ID": 9, + "branch_ID": 3 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_NonBoozeItem_101309GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_NonBoozeItem_101309GMT.json new file mode 100644 index 000000000..1cdc4992c --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventIn_NonBoozeItem_101309GMT.json @@ -0,0 +1,13 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1483351989000, + "sale_ID": 99999991, + "amount": 299, + "item_ID": 5123, + "quantity": 1, + "assistant_ID": 23, + "branch_ID": 1, + "notes": "Special Offer!!" +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_084106GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_084106GMT.json new file mode 100644 index 000000000..3625f908f --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_084106GMT.json @@ -0,0 +1,17 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_AUTH", + "version": "0.0.1", + "source": "", + "target": "", + "amount": 1249, + "assistant_ID": 12, + "authorised": false, + "branch_ID": 2, + "item_ID": 1012, + "message": "Sale not authorised by policy task MorningBoozeCheck for time 08:41:06 GMT. Alcohol can not be sold between 00:00:00 GMT and 11:30:00 GMT", + "notes": null, + "quantity": 1, + "sale_ID": 99999992, + "time": 1483346466000 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_201713GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_201713GMT.json new file mode 100644 index 000000000..2b760d5f1 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_BoozeItem_201713GMT.json @@ -0,0 +1,17 @@ +{ + "name": "SALE_AUTH", + "version": "0.0.1", + "nameSpace": "com.hyperm", + "source": "", + "target": "", + "amount": 4799, + "assistant_ID": 9, + "authorised": true, + "branch_ID": 3, + "item_ID": 1943, + "message": "Sale authorised by policy task MorningBoozeCheck for time 20:17:13 GMT", + "notes": null, + "quantity": 2, + "sale_ID": 99999993, + "time": 1482265033000 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_NonBoozeItem_101309GMT.json b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_NonBoozeItem_101309GMT.json new file mode 100644 index 000000000..b90c6fa0c --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventOut_NonBoozeItem_101309GMT.json @@ -0,0 +1,17 @@ +{ + "name": "SALE_AUTH", + "version": "0.0.1", + "nameSpace": "com.hyperm", + "source": "", + "target": "", + "amount": 299, + "assistant_ID": 23, + "authorised": true, + "branch_ID": 1, + "item_ID": 5123, + "message": "Sale authorised by policy task MorningBoozeCheck for time 10:13:09 GMT", + "notes": "Special Offer!!", + "quantity": 1, + "sale_ID": 99999991, + "time": 1483351989000 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsIn.json.txt b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsIn.json.txt new file mode 100644 index 000000000..a9570f989 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsIn.json.txt @@ -0,0 +1,37 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1483346466000, + "sale_ID": 99999992, + "amount": 1249, + "item_ID": 1012, + "quantity": 1, + "assistant_ID": 12, + "branch_ID": 2 +} +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1482265033000, + "sale_ID": 99999993, + "amount": 4799, + "item_ID": 1943, + "quantity": 2, + "assistant_ID": 9, + "branch_ID": 3 +} +{ + "nameSpace": "com.hyperm", + "name": "SALE_INPUT", + "version": "0.0.1", + "time": 1483351989000, + "sale_ID": 99999991, + "amount": 299, + "item_ID": 5123, + "quantity": 1, + "assistant_ID": 23, + "branch_ID": 1, + "notes": "Special Offer!!" +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsOut.json.txt b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsOut.json.txt new file mode 100644 index 000000000..46fd887f4 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/events/MyFirstPolicy/3/EventsOut.json.txt @@ -0,0 +1,51 @@ +{ + "nameSpace": "com.hyperm", + "name": "SALE_AUTH", + "version": "0.0.1", + "source": "", + "target": "", + "amount": 1249, + "assistant_ID": 12, + "authorised": false, + "branch_ID": 2, + "item_ID": 1012, + "message": "Sale not authorised by policy task MorningBoozeCheck for time 08:41:06 GMT. Alcohol can not be sold between 00:00:00 GMT and 11:30:00 GMT", + "notes": null, + "quantity": 1, + "sale_ID": 99999992, + "time": 1483346466000 +} +{ + "name": "SALE_AUTH", + "version": "0.0.1", + "nameSpace": "com.hyperm", + "source": "", + "target": "", + "amount": 4799, + "assistant_ID": 9, + "authorised": true, + "branch_ID": 3, + "item_ID": 1943, + "message": "Sale authorised by policy task MorningBoozeCheck for time 20:17:13 GMT", + "notes": null, + "quantity": 2, + "sale_ID": 99999993, + "time": 1482265033000 +} +{ + "name": "SALE_AUTH", + "version": "0.0.1", + "nameSpace": "com.hyperm", + "source": "", + "target": "", + "amount": 299, + "assistant_ID": 23, + "authorised": true, + "branch_ID": 1, + "item_ID": 5123, + "message": "Sale authorised by policy task MorningBoozeCheck for time 10:13:09 GMT", + "notes": "Special Offer!!", + "quantity": 1, + "sale_ID": 99999991, + "time": 1483351989000 +}
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/AlternateRecommendationCreate.mvel b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/AlternateRecommendationCreate.mvel new file mode 100644 index 000000000..3c98c9f3b --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/AlternateRecommendationCreate.mvel @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) (C) 2020 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); + +outFields.put("sale_ID" , inFields.get("sale_ID")); +outFields.put("message", "Please choose a non -alcoholic drink :)"); +return true; + +/* +This task provides recommendation to buy a non alcoholic drink. :-) +*/ diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/BoozeConcessionCheck.mvel b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/BoozeConcessionCheck.mvel new file mode 100644 index 000000000..b12933348 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/BoozeConcessionCheck.mvel @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); + +outFields.put("sale_ID" , inFields.get("sale_ID")); + +if(inFields.get("quantity") != null && inFields.get("quantity") >2){ + outFields.put("message", false); + outFields.put("message", "Sale authorised by policy task "+subject.taskName+ + " concession 10%"); + return true; +} +else{ + outFields.put("message", "Sale authorised by policy task "+subject.taskName+ + " is not eligible for concession"); + return true; +} + +/* +This task checks if a sale quantity for an item that is approved for sale. +If the quantity is greater than 2 , the user is eligible for 10 % concession. +*/ diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MorningBoozeCheck.mvel b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MorningBoozeCheck.mvel new file mode 100644 index 000000000..fc669dc3a --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MorningBoozeCheck.mvel @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +import java.util.Date; +import java.util.Calendar; +import java.util.TimeZone; +import java.text.SimpleDateFormat; + +logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); + +outFields.put("amount" , inFields.get("amount")); +outFields.put("assistant_ID", inFields.get("assistant_ID")); +outFields.put("notes" , inFields.get("notes")); +outFields.put("quantity" , inFields.get("quantity")); +outFields.put("branch_ID" , inFields.get("branch_ID")); +outFields.put("item_ID" , inFields.get("item_ID")); +outFields.put("time" , inFields.get("time")); +outFields.put("sale_ID" , inFields.get("sale_ID")); + +item_id = inFields.get("item_ID"); + +//The events used later to test this task use GMT timezone! +gmt = TimeZone.getTimeZone("GMT"); +timenow = Calendar.getInstance(gmt); +df = new SimpleDateFormat("HH:mm:ss z"); +df.setTimeZone(gmt); +timenow.setTimeInMillis(inFields.get("time")); + +midnight = timenow.clone(); +midnight.set( + timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), + timenow.get(Calendar.DATE),0,0,0); +eleven30 = timenow.clone(); +eleven30.set( + timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), + timenow.get(Calendar.DATE),11,30,0); + +itemisalcohol = false; +if(item_id != null && item_id >=1000 && item_id < 2000) + itemisalcohol = true; + +if( itemisalcohol + && timenow.after(midnight) && timenow.before(eleven30)){ + outFields.put("authorised", false); + outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ + " for time "+df.format(timenow.getTime())+ + ". Alcohol can not be sold between "+df.format(midnight.getTime())+ + " and "+df.format(eleven30.getTime())); + return true; +} +else{ + outFields.put("authorised", true); + outFields.put("message", "Sale authorised by policy task "+subject.taskName+ + " for time "+df.format(timenow.getTime())); + return true; +} + +/* +This task checks if a sale request is for an item that is an alcoholic drink. +If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not +authorised. Otherwise the sale is authorised. +In this implementation we assume that items with item_ID value between 1000 and +2000 are all alcoholic drinks :-) +*/ diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicyModelSFL_0.0.1.apex b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicyModelSFL_0.0.1.apex new file mode 100644 index 000000000..48491d030 --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicyModelSFL_0.0.1.apex @@ -0,0 +1,162 @@ +#------------------------------------------------------------------------------- +# ============LICENSE_START======================================================= +# Copyright (C) 2020 Nordix Foundation. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= +#------------------------------------------------------------------------------- + +model create name=MyFirstPolicyModel version=0.0.1 uuid=540226fb-55ee-4f0e-a444-983a0494818e description="This is my first Apex Policy Model." + +schema create name=assistant_ID_type version=0.0.1 uuid=36df4c71-9616-4206-8b53-976a5cd4bd87 description="A type for 'assistant_ID' values" flavour=Java schema=java.lang.Long + +schema create name=authorised_type version=0.0.1 uuid=d48b619e-d00d-4008-b884-02d76ea4350b description="A type for 'authorised' values" flavour=Java schema=java.lang.Boolean + +schema create name=branch_ID_type version=0.0.1 uuid=6468845f-4122-4128-8e49-0f52c26078b5 description="A type for 'branch_ID' values" flavour=Java schema=java.lang.Long + +schema create name=item_ID_type version=0.0.1 uuid=4f227ff1-aee0-453a-b6b6-9a4b2e0da932 description="A type for 'item_ID' values" flavour=Java schema=java.lang.Long + +schema create name=message_type version=0.0.1 uuid=ad1431bb-3155-4e73-b5a3-b89bee498749 description="A type for 'message' values" flavour=Java schema=java.lang.String + +schema create name=notes_type version=0.0.1 uuid=eecfde90-896c-4343-8f9c-2603ced94e2d description="A type for 'notes' values" flavour=Java schema=java.lang.String + +schema create name=price_type version=0.0.1 uuid=52c2fc45-fd8c-463c-bd6f-d91b0554aea7 description="A type for 'amount'/'price' values" flavour=Java schema=java.lang.Long + +schema create name=quantity_type version=0.0.1 uuid=ac3d9842-80af-4a98-951c-bd79a431c613 description="A type for 'quantity' values" flavour=Java schema=java.lang.Integer + +schema create name=sale_ID_type version=0.0.1 uuid=cca47d74-7754-4a61-b163-ca31f66b157b description="A type for 'sale_ID' values" flavour=Java schema=java.lang.Long + +schema create name=timestamp_type version=0.0.1 uuid=fd594e88-411d-4a94-b2be-697b3a0d7adf description="A type for 'time' values" flavour=Java schema=java.lang.Long + +task create name=MorningBoozeCheck version=0.0.1 uuid=3351b0f4-cf06-4fa2-8823-edf67bd30223 description=LS +This task checks if the sales request is for an item that contains alcohol. +If the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. +In this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-) +LE +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 +task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true + +task logic create name=MorningBoozeCheck version=0.0.1 logicFlavour=MVEL logic=LS +#MACROFILE:"src/main/resources/examples/models/MyFirstPolicy/3/MorningBoozeCheck.mvel" +LE + +task create name=BoozeConcessionCheck version=0.0.1 description=LS +This task checks if the approved sales item is eligible for concession +In this implementation we assume that all items with quantity greater than 2 is eligible for concession :-) +LE +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 +task inputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true +task outputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task outputfield create name=BoozeConcessionCheck version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true + +task logic create name=BoozeConcessionCheck version=0.0.1 logicFlavour=MVEL logic=LS +#MACROFILE:"src/main/resources/examples/models/MyFirstPolicy/3/BoozeConcessionCheck.mvel" +LE + +task create name=AlternateRecommendationCreate version=0.0.1 description=LS +This task checks if the approved sales item is rejected for sale +In this implementation we assume that all denied customers will be recommended to buy non alcoholic drinks :-) +LE +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 +task inputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true +task outputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +task outputfield create name=AlternateRecommendationCreate version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true + +task logic create name=AlternateRecommendationCreate version=0.0.1 logicFlavour=MVEL logic=LS +#MACROFILE:"src/main/resources/examples/models/MyFirstPolicy/3/AlternateRecommendationCreate.mvel" +LE + +event create name=SALE_AUTH version=0.0.1 uuid=c4500941-3f98-4080-a9cc-5b9753ed050b description="An event emitted by the Policy to indicate whether the sale of an item has been authorised" nameSpace=com.hyperm source="APEX" target="POS" +event parameter create name=SALE_AUTH version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=authorised schemaName=authorised_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=message schemaName=message_type schemaVersion=0.0.1 optional=true +event parameter create name=SALE_AUTH version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +event parameter create name=SALE_AUTH version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_AUTH version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 + +event create name=SALE_INPUT version=0.0.1 uuid=4f04aa98-e917-4f4a-882a-c75ba5a99374 description="An event raised by the PoS system each time an item is scanned for purchase" nameSpace=com.hyperm source="POS" target="APEX" +event parameter create name=SALE_INPUT version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true +event parameter create name=SALE_INPUT version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_INPUT version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 + +event create name=SALE_CONCESSION version=0.0.1 description="An event raised by the PoS system each time an item is approved for sale" nameSpace=com.hyperm source="POS" target="APEX" +event parameter create name=SALE_CONCESSION version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_CONCESSION version=0.0.1 parName=message schemaName=message_type schemaVersion=0.0.1 optional=true + +event create name=SALE_RECOMMEND version=0.0.1 description="An event raised by the PoS system each time an item is not approved for sale" nameSpace=com.hyperm source="POS" target="APEX" +event parameter create name=SALE_RECOMMEND version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 +event parameter create name=SALE_RECOMMEND version=0.0.1 parName=message schemaName=message_type schemaVersion=0.0.1 optional=true + +policy create name=MyFirstPolicy version=0.0.1 description="This is my first Apex policy. It checks if a sale should be authorised or not." template=FREEFORM firstState=BoozeAuthDecide +policy state create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide triggerName=SALE_INPUT triggerVersion=0.0.1 defaultTaskName=MorningBoozeCheck defaultTaskVersion=0.0.1 +policy state create name=MyFirstPolicy version=0.0.1 stateName=BoozeConcessionDecide triggerName=SALE_AUTH triggerVersion=0.0.1 defaultTaskName=BoozeConcessionCheck defaultTaskVersion=0.0.1 +policy state create name=MyFirstPolicy version=0.0.1 stateName=AlternateRecommendation triggerName=SALE_AUTH triggerVersion=0.0.1 defaultTaskName=AlternateRecommendationCreate defaultTaskVersion=0.0.1 +policy state output create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide outputName=MorningBoozeCheck_Output_Approved eventName=SALE_AUTH eventVersion=0.0.1 nextState=BoozeConcessionDecide +policy state output create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide outputName=MorningBoozeCheck_Output_Denied eventName=SALE_AUTH eventVersion=0.0.1 nextState=AlternateRecommendation + +policy state finalizerlogic create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide finalizerLogicName=MorningBoozeCheck_Output_logic logicFlavour=JAVASCRIPT logic=LS +#MACROFILE:"src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicy_SFL.js" +LE +policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide taskLocalName=MorningBoozeCheck taskName=MorningBoozeCheck taskVersion=0.0.1 outputType=LOGIC outputName=MorningBoozeCheck_Output_logic + +policy state output create name=MyFirstPolicy version=0.0.1 stateName=BoozeConcessionDecide outputName=BoozeConcessionCheck_Output eventName=SALE_CONCESSION eventVersion=0.0.1 nextState=NULL +policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=BoozeConcessionDecide taskLocalName=BoozeConcessionCheck taskName=BoozeConcessionCheck taskVersion=0.0.1 outputType=DIRECT outputName=BoozeConcessionCheck_Output + +policy state output create name=MyFirstPolicy version=0.0.1 stateName=AlternateRecommendation outputName=AlternateRecommendationCreate_Output eventName=SALE_RECOMMEND eventVersion=0.0.1 nextState=NULL +policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=AlternateRecommendation taskLocalName=AlternateRecommendationCreate taskName=AlternateRecommendationCreate taskVersion=0.0.1 outputType=DIRECT outputName=AlternateRecommendationCreate_Output + +validate +quit
\ No newline at end of file diff --git a/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicy_SFL.js b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicy_SFL.js new file mode 100644 index 000000000..2088f7dda --- /dev/null +++ b/examples/examples-myfirstpolicy/src/main/resources/examples/models/MyFirstPolicy/3/MyFirstPolicy_SFL.js @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +executor.logger.info("finalizer execution: " + executor.subject.id); + +if (executor.fields.get("authorised") == true) { + executor.logger.info("finalizer if block "); + executor.setSelectedStateOutputName("MorningBoozeCheck_Output_Approved"); +} else { + executor.logger.info("finalizer else block "); + executor.setSelectedStateOutputName("MorningBoozeCheck_Output_Denied"); +} + +executor.logger.info("finalizer outputs ##2##: " + executor.stateOutputNames); +executor.logger.info( + "finalizer outputs:##2##: ##" + executor.selectedStateOutputName + "##"); + +true; + +/* +State Finaliser logic to decide the next state on the basis if the sale is approved or denied. +If the sale is approved, MorningBoozeCheck_Output_Approved is set as the state output. +If the sale is rejected, MorningBoozeCheck_Output_Denied is set as the state output. +*/ diff --git a/plugins/plugins-context/plugins-context-distribution/plugins-context-distribution-infinispan/pom.xml b/plugins/plugins-context/plugins-context-distribution/plugins-context-distribution-infinispan/pom.xml index 7cd3cd03c..cf4be2128 100644 --- a/plugins/plugins-context/plugins-context-distribution/plugins-context-distribution-infinispan/pom.xml +++ b/plugins/plugins-context/plugins-context-distribution/plugins-context-distribution-infinispan/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-core</artifactId> - <version>9.3.1.Final</version> + <version>10.1.5.Final</version> <exclusions> <exclusion> <groupId>org.jboss.slf4j</groupId> @@ -60,4 +60,5 @@ </distributionManagement> </profile> </profiles> -</project>
\ No newline at end of file +</project> + diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java index f7bafdd74..a33a129af 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java @@ -26,6 +26,11 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; + import org.apache.commons.lang3.StringUtils; import org.mozilla.javascript.Context; import org.mozilla.javascript.Script; @@ -48,6 +53,13 @@ public class JavascriptExecutor implements Runnable { // Recurring string constants private static final String WITH_MESSAGE = " with message: "; + @Setter(AccessLevel.PROTECTED) + private static TimeUnit timeunit4Latches = TimeUnit.SECONDS; + @Setter(AccessLevel.PROTECTED) + private static int intializationLatchTimeout = 60; + @Setter(AccessLevel.PROTECTED) + private static int cleanupLatchTimeout = 60; + // The key of the subject that wants to execute Javascript code final AxKey subjectKey; @@ -58,9 +70,10 @@ public class JavascriptExecutor implements Runnable { private final BlockingQueue<Object> executionQueue = new LinkedBlockingQueue<>(); private final BlockingQueue<Boolean> resultQueue = new LinkedBlockingQueue<>(); - private final Thread executorThread; - private CountDownLatch intializationLatch = new CountDownLatch(1); - private CountDownLatch shutdownLatch = new CountDownLatch(1); + @Getter(AccessLevel.PROTECTED) + private Thread executorThread; + private CountDownLatch intializationLatch; + private CountDownLatch cleanupLatch; private AtomicReference<StateMachineException> executorException = new AtomicReference<>(null); /** @@ -70,9 +83,6 @@ public class JavascriptExecutor implements Runnable { */ public JavascriptExecutor(final AxKey subjectKey) { this.subjectKey = subjectKey; - - executorThread = new Thread(this); - executorThread.setName(this.getClass().getSimpleName() + ":" + subjectKey.getId()); } /** @@ -81,39 +91,44 @@ public class JavascriptExecutor implements Runnable { * @param javascriptCode the Javascript code to execute * @throws StateMachineException thrown when instantiation of the executor fails */ - public void init(final String javascriptCode) throws StateMachineException { + public synchronized void init(@NonNull final String javascriptCode) throws StateMachineException { LOGGER.debug("JavascriptExecutor {} starting ... ", subjectKey.getId()); - if (executorThread.isAlive()) { - throw new StateMachineException( - "initiation failed, executor " + subjectKey.getId() + " is already running"); + if (executorThread != null) { + throw new StateMachineException("initiation failed, executor " + subjectKey.getId() + + " already initialized, run cleanUp to clear executor"); } - if (StringUtils.isEmpty(javascriptCode)) { - throw new StateMachineException("no logic specified for " + subjectKey.getId()); + if (StringUtils.isBlank(javascriptCode)) { + throw new StateMachineException("initiation failed, no logic specified for executor " + subjectKey.getId()); } this.javascriptCode = javascriptCode; + executorThread = new Thread(this); + executorThread.setName(this.getClass().getSimpleName() + ":" + subjectKey.getId()); + intializationLatch = new CountDownLatch(1); + cleanupLatch = new CountDownLatch(1); + try { executorThread.start(); - } catch (Exception e) { + } catch (IllegalThreadStateException e) { throw new StateMachineException("initiation failed, executor " + subjectKey.getId() + " failed to start", e); } try { - if (!intializationLatch.await(60, TimeUnit.SECONDS)) { - LOGGER.warn("JavascriptExecutor {}, initiation timed out", subjectKey.getId()); + if (!intializationLatch.await(intializationLatchTimeout, timeunit4Latches)) { + executorThread.interrupt(); + throw new StateMachineException("JavascriptExecutor " + subjectKey.getId() + + " initiation timed out after " + intializationLatchTimeout + " " + timeunit4Latches); } } catch (InterruptedException e) { LOGGER.debug("JavascriptExecutor {} interrupted on execution thread startup", subjectKey.getId(), e); Thread.currentThread().interrupt(); } - if (executorException.get() != null) { - clearAndThrowExecutorException(); - } + checkAndThrowExecutorException(); LOGGER.debug("JavascriptExecutor {} started ... ", subjectKey.getId()); } @@ -125,9 +140,14 @@ public class JavascriptExecutor implements Runnable { * @return true if execution was successful, false otherwise * @throws StateMachineException on execution errors */ - public boolean execute(final Object executionContext) throws StateMachineException { + public synchronized boolean execute(final Object executionContext) throws StateMachineException { + if (executorThread == null) { + throw new StateMachineException("execution failed, executor " + subjectKey.getId() + " is not initialized"); + } + if (!executorThread.isAlive()) { - throw new StateMachineException("execution failed, executor " + subjectKey.getId() + " is not running"); + throw new StateMachineException("execution failed, executor " + subjectKey.getId() + + " is not running, run cleanUp to clear executor and init to restart executor"); } executionQueue.add(executionContext); @@ -137,13 +157,13 @@ public class JavascriptExecutor implements Runnable { try { result = resultQueue.take(); } catch (final InterruptedException e) { - LOGGER.debug("JavascriptExecutor {} interrupted on execution result wait", subjectKey.getId(), e); + executorThread.interrupt(); Thread.currentThread().interrupt(); + throw new StateMachineException( + "JavascriptExecutor " + subjectKey.getId() + "interrupted on execution result wait", e); } - if (executorException.get() != null) { - clearAndThrowExecutorException(); - } + checkAndThrowExecutorException(); return result; } @@ -153,25 +173,30 @@ public class JavascriptExecutor implements Runnable { * * @throws StateMachineException thrown when cleanup of the executor fails */ - public void cleanUp() throws StateMachineException { - if (!executorThread.isAlive()) { - throw new StateMachineException("cleanup failed, executor " + subjectKey.getId() + " is not running"); + public synchronized void cleanUp() throws StateMachineException { + if (executorThread == null) { + throw new StateMachineException("cleanup failed, executor " + subjectKey.getId() + " is not initialized"); } - executorThread.interrupt(); + if (executorThread.isAlive()) { + executorThread.interrupt(); - try { - if (!shutdownLatch.await(60, TimeUnit.SECONDS)) { - LOGGER.warn("JavascriptExecutor {}, shutdown timed out", subjectKey.getId()); + try { + if (!cleanupLatch.await(cleanupLatchTimeout, timeunit4Latches)) { + executorException.set(new StateMachineException("JavascriptExecutor " + subjectKey.getId() + + " cleanup timed out after " + cleanupLatchTimeout + " " + timeunit4Latches)); + } + } catch (InterruptedException e) { + LOGGER.debug("JavascriptExecutor {} interrupted on execution cleanup wait", subjectKey.getId(), e); + Thread.currentThread().interrupt(); } - } catch (InterruptedException e) { - LOGGER.debug("JavascriptExecutor {} interrupted on execution clkeanup wait", subjectKey.getId(), e); - Thread.currentThread().interrupt(); } - if (executorException.get() != null) { - clearAndThrowExecutorException(); - } + executorThread = null; + executionQueue.clear(); + resultQueue.clear(); + + checkAndThrowExecutorException(); } @Override @@ -181,9 +206,10 @@ public class JavascriptExecutor implements Runnable { try { initExecutor(); } catch (StateMachineException sme) { - LOGGER.warn("JavascriptExecutor {} initialization failed", sme); + LOGGER.warn("JavascriptExecutor {} initialization failed", subjectKey.getId(), sme); executorException.set(sme); intializationLatch.countDown(); + cleanupLatch.countDown(); return; } @@ -192,14 +218,12 @@ public class JavascriptExecutor implements Runnable { LOGGER.debug("JavascriptExecutor {} executing ... ", subjectKey.getId()); // Take jobs from the execution queue of the worker and execute them - while (!executorThread.isInterrupted()) { + while (!Thread.currentThread().isInterrupted()) { try { Object contextObject = executionQueue.take(); - if (contextObject == null) { - break; - } - resultQueue.add(executeScript(contextObject)); + boolean result = executeScript(contextObject); + resultQueue.add(result); } catch (final InterruptedException e) { LOGGER.debug("execution was interruped for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e); resultQueue.add(false); @@ -217,7 +241,7 @@ public class JavascriptExecutor implements Runnable { "executor close failed to close for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e)); } - shutdownLatch.countDown(); + cleanupLatch.countDown(); LOGGER.debug("JavascriptExecutor {} completed processing", subjectKey.getId()); } @@ -262,14 +286,10 @@ public class JavascriptExecutor implements Runnable { return (boolean) returnObject; } - private void clearAndThrowExecutorException() throws StateMachineException { + private void checkAndThrowExecutorException() throws StateMachineException { StateMachineException exceptionToThrow = executorException.getAndSet(null); if (exceptionToThrow != null) { throw exceptionToThrow; } } - - protected Thread getExecutorThread() { - return executorThread; - } } diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java index 9a6b8c7a6..5078c9730 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorFullApexTest.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.apex.model.basicmodel.concepts.ApexException; import org.onap.policy.apex.service.engine.main.ApexMain; @@ -36,7 +35,6 @@ import org.onap.policy.common.utils.resources.TextFileUtils; public class JavascriptExecutorFullApexTest { - @Ignore @Test public void testFullApexPolicy() throws ApexException { final String[] args = {"src/test/resources/prodcons/File2File.json"}; diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java new file mode 100644 index 000000000..53781e870 --- /dev/null +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutorTest.java @@ -0,0 +1,335 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.plugins.executor.javascript; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; + +public class JavascriptExecutorTest { + private AtomicBoolean concurrentResult = new AtomicBoolean(); + + @Before + public void beforeSetTimeouts() { + JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); + JavascriptExecutor.setIntializationLatchTimeout(60); + JavascriptExecutor.setCleanupLatchTimeout(10); + } + + @Test + public void testJavescriptExecutorConcurrencyNormal() throws StateMachineException, IOException { + JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); + JavascriptExecutor.setIntializationLatchTimeout(60); + JavascriptExecutor.setCleanupLatchTimeout(10); + + JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); + + assertThatThrownBy(() -> { + executor.init(null); + }).hasMessageMatching("^javascriptCode is marked .*on.*ull but is null$"); + + assertThatThrownBy(() -> { + executor.init(" "); + }).hasMessage("initiation failed, no logic specified for executor executor:0.0.1"); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.init("var x = 1;"); + }).hasMessage("initiation failed, executor executor:0.0.1 already initialized, run cleanUp to clear executor"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.cleanUp(); + }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); + + assertThatThrownBy(() -> { + executor.execute("Hello"); + }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.execute("Hello"); + }).hasMessage( + "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); + + assertThatThrownBy(() -> { + executor.execute("Hello"); + }).hasMessage( + "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); + + assertThatThrownBy(() -> { + executor.execute("Hello"); + }).hasMessage( + "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); + + assertThatThrownBy(() -> { + executor.execute("Hello"); + }).hasMessage( + "execute: logic for executor:0.0.1 returned a non-boolean value org.mozilla.javascript.Undefined@0"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.cleanUp(); + }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); + + assertThatThrownBy(() -> { + executor.execute("hello"); + }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); + } + + @Test + public void testJavescriptExecutorConcurrencyLatchTimeout() throws StateMachineException, IOException { + JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS); + JavascriptExecutor.setIntializationLatchTimeout(1); + JavascriptExecutor.setCleanupLatchTimeout(10000000); + + JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); + + assertThatThrownBy(() -> { + executor.init("var x = 1;"); + }).hasMessage("JavascriptExecutor executor:0.0.1 initiation timed out after 1 MICROSECONDS"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + JavascriptExecutor.setTimeunit4Latches(TimeUnit.SECONDS); + JavascriptExecutor.setIntializationLatchTimeout(60); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + JavascriptExecutor.setTimeunit4Latches(TimeUnit.MICROSECONDS); + JavascriptExecutor.setIntializationLatchTimeout(60000000); + JavascriptExecutor.setCleanupLatchTimeout(1); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.cleanUp(); + }).hasMessage("JavascriptExecutor executor:0.0.1 cleanup timed out after 1 MICROSECONDS"); + + JavascriptExecutor.setCleanupLatchTimeout(10000000); + assertThatThrownBy(() -> { + executor.cleanUp(); + }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + } + + @Test + public void testJavescriptExecutorBadStates() throws StateMachineException, IOException { + JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); + + assertThatThrownBy(() -> { + executor.execute("hello"); + }).hasMessage("execution failed, executor executor:0.0.1 is not initialized"); + + assertThatThrownBy(() -> { + executor.cleanUp(); + }).hasMessage("cleanup failed, executor executor:0.0.1 is not initialized"); + + assertThatCode(() -> { + executor.init("var x = 1;"); + }).doesNotThrowAnyException(); + + executor.getExecutorThread().interrupt(); + await().atMost(10, TimeUnit.SECONDS).until(() -> !executor.getExecutorThread().isAlive()); + + assertThatThrownBy(() -> { + executor.execute("hello"); + }).hasMessage("execution failed, executor executor:0.0.1 is not running, " + + "run cleanUp to clear executor and init to restart executor"); + + assertThatThrownBy(() -> { + executor.execute("hello"); + }).hasMessage("execution failed, executor executor:0.0.1 is not running, " + + "run cleanUp to clear executor and init to restart executor"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + } + + @Test + public void testJavescriptExecutorExecution() throws StateMachineException, IOException { + JavascriptExecutor executor = new JavascriptExecutor(new AxArtifactKey("executor:0.0.1")); + + assertThatCode(() -> { + executor.init("true;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertTrue(executor.execute("hello")); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("false;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertFalse(executor.execute("hello")); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + executor.init("aaaaa = \"sss"); + }).hasMessage( + "logic failed to compile for executor:0.0.1 with message: unterminated string literal (executor:0.0.1#1)"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("true;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertTrue(executor.execute("hello")); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("throw \"this is an error\";"); + }).doesNotThrowAnyException(); + + assertThatThrownBy(() -> { + assertTrue(executor.execute("hello")); + }).hasMessage("logic failed to run for executor:0.0.1 with message: this is an error (executor:0.0.1#1)"); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("while (true) { x = 1; }; true;"); + }).doesNotThrowAnyException(); + + concurrentResult.set(true); + + // Execute an infinite loop in Javascript + (new Thread() { + public void run() { + try { + concurrentResult.set(executor.execute("hello")); + } catch (StateMachineException e) { + e.printStackTrace(); + } + } + }).start(); + + executor.getExecutorThread().interrupt(); + + await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> !concurrentResult.get()); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("true;"); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + assertTrue(executor.execute("hello")); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + + assertThatCode(() -> { + executor.init("x = 1; true;"); + }).doesNotThrowAnyException(); + + concurrentResult.set(true); + + // Execute an infinite loop in Javascript + Thread executionThread = new Thread() { + public void run() { + try { + while (executor.execute("hello")) { + ; + } + } catch (StateMachineException e) { + ; + } + } + }; + executionThread.start(); + + executionThread.interrupt(); + + await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executionThread.isAlive()); + await().atMost(300, TimeUnit.MILLISECONDS).until(() -> !executor.getExecutorThread().isAlive()); + + assertThatCode(() -> { + executor.cleanUp(); + }).doesNotThrowAnyException(); + } +} diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java index 62471797f..243a1d977 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutorTest.java @@ -31,7 +31,6 @@ import java.util.Properties; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.apex.context.parameters.ContextParameterConstants; import org.onap.policy.apex.context.parameters.DistributorParameters; @@ -77,7 +76,6 @@ public class JavascriptStateFinalizerExecutorTest { ParameterService.deregister(EngineParameterConstants.MAIN_GROUP_NAME); } - @Ignore @Test public void testJavaStateFinalizerExecutor() throws Exception { JavascriptStateFinalizerExecutor jsfe = new JavascriptStateFinalizerExecutor(); @@ -104,15 +102,17 @@ public class JavascriptStateFinalizerExecutorTest { Map<String, Object> incomingParameters1 = new HashMap<>(); assertThatThrownBy(() -> { jsfe.execute(-1, new Properties(), incomingParameters1); - }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not running"); + }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not running, " + + "run cleanUp to clear executor and init to restart executor"); assertThatThrownBy(() -> { jsfe.prepare(); - }).hasMessage("initiation failed, executor NULL:0.0.0:NULL:NULL failed to start"); + }).hasMessage( + "initiation failed, executor NULL:0.0.0:NULL:NULL already initialized, run cleanUp to clear executor"); - assertThatThrownBy(() -> { + assertThatCode(() -> { jsfe.cleanUp(); - }).hasMessage("cleanup failed, executor NULL:0.0.0:NULL:NULL is not running"); + }).doesNotThrowAnyException(); JavascriptStateFinalizerExecutor jsfe1 = new JavascriptStateFinalizerExecutor(); stateFinalizerLogic.setLogic("java.lang.String"); diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java index fe71d3c0e..4fc7507ed 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java @@ -32,7 +32,6 @@ import java.util.Properties; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.apex.context.ContextAlbum; import org.onap.policy.apex.context.ContextException; @@ -98,7 +97,6 @@ public class JavascriptTaskExecutorTest { ParameterService.clear(); } - @Ignore @Test public void testJavascriptTaskExecutor() throws Exception { assertThatThrownBy(() -> { @@ -129,7 +127,7 @@ public class JavascriptTaskExecutorTest { assertThatThrownBy(() -> { jte.prepare(); - }).hasMessage("initiation failed, executor TestTask:0.0.1 is already running"); + }).hasMessage("initiation failed, executor TestTask:0.0.1 already initialized, run cleanUp to clear executor"); assertThatThrownBy(() -> { jte.execute(-1, new Properties(), null); @@ -166,7 +164,6 @@ public class JavascriptTaskExecutorTest { }).doesNotThrowAnyException(); } - @Ignore @Test public void testJavascriptTaskExecutorLogic() throws Exception { JavascriptTaskExecutor jte = new JavascriptTaskExecutor(); diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java index de5df5787..fa494ced9 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutorTest.java @@ -30,7 +30,6 @@ import java.util.Properties; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.apex.context.parameters.ContextParameterConstants; import org.onap.policy.apex.context.parameters.DistributorParameters; @@ -69,7 +68,6 @@ public class JavascriptTaskSelectExecutorTest { ParameterService.deregister(ContextParameterConstants.PERSISTENCE_GROUP_NAME); } - @Ignore @Test public void testJavascriptTaskSelectExecutor() throws Exception { JavascriptTaskSelectExecutor jtse = new JavascriptTaskSelectExecutor(); @@ -86,14 +84,18 @@ public class JavascriptTaskSelectExecutorTest { assertThatThrownBy(() -> { jtse.prepare(); - }).hasMessage("no logic specified for NULL:0.0.0:NULL:NULL"); + }).hasMessage("initiation failed, no logic specified for executor NULL:0.0.0:NULL:NULL"); AxEvent axEvent1 = new AxEvent(new AxArtifactKey("Event", "0.0.1")); EnEvent event1 = new EnEvent(axEvent1); assertThatThrownBy(() -> { jtse.execute(-1, new Properties(), event1); - }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not running"); + }).hasMessage("execution failed, executor NULL:0.0.0:NULL:NULL is not initialized"); + + assertThatThrownBy(() -> { + jtse.cleanUp(); + }).hasMessage("cleanup failed, executor NULL:0.0.0:NULL:NULL is not initialized"); state.getTaskSelectionLogic().setLogic("java.lang.String"); jtse.prepare(); @@ -119,7 +121,8 @@ public class JavascriptTaskSelectExecutorTest { assertThatThrownBy(() -> { jtse.prepare(); - }).hasMessage("initiation failed, executor NULL:0.0.0:NULL:NULL is already running"); + }).hasMessage( + "initiation failed, executor NULL:0.0.0:NULL:NULL already initialized, run cleanUp to clear executor"); assertThatCode(() -> { jtse.cleanUp(); @@ -44,8 +44,8 @@ <version.commons-cli>1.4</version.commons-cli> <version.kafka>2.3.0</version.kafka> <version.hibernate>5.3.7.Final</version.hibernate> - <version.policy.common>1.6.2</version.policy.common> - <version.policy.models>2.2.2</version.policy.models> + <version.policy.common>1.6.3-SNAPSHOT</version.policy.common> + <version.policy.models>2.2.3-SNAPSHOT</version.policy.models> <version.jackson>2.10.0.pr3</version.jackson> <version.jgroups>4.1.5.Final</version.jgroups> <version.commons-codec>20041127.091804</version.commons-codec> |