aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Cruz <dc443y@att.com>2019-03-06 10:45:09 -0600
committerDaniel Cruz <dc443y@att.com>2019-03-13 12:11:55 -0500
commit57a44626324326fc3b29042398d2ccdaec5a7758 (patch)
tree1b26cdc89743306b337d0a22c7820effd5272d5b
parent5bee2c177fb15cad0ed3f78d5df999dac62da6a7 (diff)
Add Network Logging Feature
This is part 1 of introducing the mdc filter feature. Network logging has to have interception points in order to pre/post process messages coming in from a network endpoint. The OrderedService interface and OrderedServiceImpl of the drools-pdp project have now been migrated to common but is also left in drools-pdp to mitigate disruption to existing features. However for features that need to use common's OrderedServiceImpl and drools-pdp version of OrderedServiceImpl there will be a conflict with getSequenceNumber(). So a migration of the other features is suggested. Network logging is moved to its own util class so that feature hooks can be invoked any time an event is being logged by a network logger. This util class will also be accessible to drools-applications in the case where drools-applications would like to invoke network logging features for REST events. Change-Id: I83d7c46e5abb351486f841c3be4d9009f7992476 Issue-ID: POLICY-1499 Signed-off-by: Daniel Cruz <dc443y@att.com>
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicEndpoint.java16
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSink.java7
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSource.java3
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSink.java9
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSource.java12
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/features/NetLoggerFeatureApi.java62
-rw-r--r--policy-endpoints/src/main/java/org/onap/policy/common/endpoints/utils/NetLoggerUtil.java153
-rw-r--r--policy-endpoints/src/test/java/org/onap/policy/common/endpoints/utils/NetLoggerUtilTest.java268
-rw-r--r--policy-endpoints/src/test/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi1
-rw-r--r--policy-endpoints/src/test/resources/logback-test.xml10
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/services/OrderedService.java (renamed from utils/src/main/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapper.java)36
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/services/OrderedServiceImpl.java135
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java4
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/services/OrderedServiceImplTest.java205
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapperTest.java52
-rw-r--r--utils/src/test/resources/META-INF/services/org.onap.policy.common.utils.services.OrderedServiceImplTest$GenericService2
16 files changed, 876 insertions, 99 deletions
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicEndpoint.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicEndpoint.java
index a2ad4d3d..ef002f52 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicEndpoint.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicEndpoint.java
@@ -23,7 +23,8 @@ package org.onap.policy.common.endpoints.event.comm.bus;
import java.util.List;
import org.onap.policy.common.endpoints.event.comm.bus.internal.TopicBase;
-import org.onap.policy.common.utils.slf4j.LoggerFactoryWrapper;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,11 +39,6 @@ public abstract class NoopTopicEndpoint extends TopicBase {
private static Logger logger = LoggerFactory.getLogger(NoopTopicEndpoint.class);
/**
- * Network logger.
- */
- private static final Logger netLogger = LoggerFactoryWrapper.getNetworkLogger();
-
- /**
* {@inheritDoc}.
*/
public NoopTopicEndpoint(List<String> servers, String topic) {
@@ -52,10 +48,11 @@ public abstract class NoopTopicEndpoint extends TopicBase {
/**
* I/O.
*
+ * @param type "IN" or "OUT".
* @param message message.
- * @return true if sucessful.
+ * @return true if successful.
*/
- protected boolean io(String message) {
+ protected boolean io(EventType type, String message) {
if (message == null || message.isEmpty()) {
throw new IllegalArgumentException("Message is empty");
@@ -70,8 +67,7 @@ public abstract class NoopTopicEndpoint extends TopicBase {
this.recentEvents.add(message);
}
- netLogger.info("[OUT|{}|{}]{}{}", this.getTopicCommInfrastructure(), this.topic, System.lineSeparator(),
- message);
+ NetLoggerUtil.log(type, this.getTopicCommInfrastructure(), this.topic, message);
broadcast(message);
} catch (Exception e) {
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSink.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSink.java
index f6ad433d..d3745940 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSink.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSink.java
@@ -7,9 +7,9 @@
* 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.
@@ -22,6 +22,7 @@ package org.onap.policy.common.endpoints.event.comm.bus;
import java.util.List;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
/**
* No Operation Topic Sink.
@@ -45,7 +46,7 @@ public class NoopTopicSink extends NoopTopicEndpoint implements TopicSink {
*/
@Override
public boolean send(String message) {
- return super.io(message);
+ return super.io(EventType.OUT, message);
}
/**
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSource.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSource.java
index c3215e04..95ed0fe6 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSource.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/NoopTopicSource.java
@@ -22,6 +22,7 @@ package org.onap.policy.common.endpoints.event.comm.bus;
import java.util.List;
import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
/**
* No Operation Topic Source.
@@ -45,7 +46,7 @@ public class NoopTopicSource extends NoopTopicEndpoint implements TopicSource {
*/
@Override
public boolean offer(String event) {
- return super.io(event);
+ return super.io(EventType.IN, event);
}
/**
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSink.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSink.java
index d6ca824e..e94bdffa 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSink.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSink.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* Modifications Copyright (C) 2018-2019 Samsung Electronics Co., Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,7 +24,8 @@ package org.onap.policy.common.endpoints.event.comm.bus.internal;
import java.util.UUID;
import org.onap.policy.common.endpoints.event.comm.bus.BusTopicSink;
-import org.onap.policy.common.utils.slf4j.LoggerFactoryWrapper;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +40,6 @@ public abstract class InlineBusTopicSink extends BusTopicBase implements BusTopi
* Loggers.
*/
private static Logger logger = LoggerFactory.getLogger(InlineBusTopicSink.class);
- private static final Logger netLogger = LoggerFactoryWrapper.getNetworkLogger();
/**
* The partition key to publish to.
@@ -140,8 +140,7 @@ public abstract class InlineBusTopicSink extends BusTopicBase implements BusTopi
this.recentEvents.add(message);
}
- netLogger.info("[OUT|{}|{}]{}{}", this.getTopicCommInfrastructure(), this.topic, System.lineSeparator(),
- message);
+ NetLoggerUtil.log(EventType.OUT, this.getTopicCommInfrastructure(), this.topic, message);
publisher.send(this.partitionId, message);
broadcast(message);
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSource.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSource.java
index 83f3760b..98e30e27 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSource.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSource.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* policy-endpoints
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* Modifications Copyright (C) 2018-2019 Samsung Electronics Co., Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,8 +28,9 @@ import org.onap.policy.common.endpoints.event.comm.FilterableTopicSource;
import org.onap.policy.common.endpoints.event.comm.TopicListener;
import org.onap.policy.common.endpoints.event.comm.bus.BusTopicSource;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusConsumer.FilterableBusConsumer;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
import org.onap.policy.common.utils.network.NetworkUtil;
-import org.onap.policy.common.utils.slf4j.LoggerFactoryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,6 @@ public abstract class SingleThreadedBusTopicSource extends BusTopicBase
* that in a single file in a concise format.
*/
private static Logger logger = LoggerFactory.getLogger(InlineBusTopicSink.class);
- private static final Logger netLogger = LoggerFactoryWrapper.getNetworkLogger();
/**
* Bus consumer group.
@@ -228,8 +228,7 @@ public abstract class SingleThreadedBusTopicSource extends BusTopicBase
this.recentEvents.add(event);
}
- netLogger.info("[IN|{}|{}]{}{}", this.getTopicCommInfrastructure(), this.topic,
- System.lineSeparator(), event);
+ NetLoggerUtil.log(EventType.IN, this.getTopicCommInfrastructure(), this.topic, event);
broadcast(event);
@@ -255,8 +254,7 @@ public abstract class SingleThreadedBusTopicSource extends BusTopicBase
this.recentEvents.add(event);
}
- netLogger.info("[IN|{}|{}]{}{}", this.getTopicCommInfrastructure(), this.topic, System.lineSeparator(), event);
-
+ NetLoggerUtil.log(EventType.IN, this.getTopicCommInfrastructure(), this.topic, event);
return broadcast(event);
}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/features/NetLoggerFeatureApi.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/features/NetLoggerFeatureApi.java
new file mode 100644
index 00000000..4e7d4444
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/features/NetLoggerFeatureApi.java
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * policy-endpoints
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.features;
+
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
+import org.onap.policy.common.utils.services.OrderedService;
+import org.onap.policy.common.utils.services.OrderedServiceImpl;
+import org.slf4j.Logger;
+
+/**
+ * Logging Feature API. Provides interception points before and after logging a message.
+ */
+public interface NetLoggerFeatureApi extends OrderedService {
+
+ /**
+ * Feature providers implementing this interface.
+ */
+ OrderedServiceImpl<NetLoggerFeatureApi> providers =
+ new OrderedServiceImpl<>(NetLoggerFeatureApi.class);
+
+ /**
+ * Intercepts a message before it is logged.
+ *
+ * @return true if this feature intercepts and takes ownership of the operation
+ * preventing the invocation of lower priority features. False, otherwise.
+ */
+ default boolean beforeLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,
+ String message) {
+ return false;
+ }
+
+ /**
+ * Intercepts a message after it is logged.
+ *
+ * @return true if this feature intercepts and takes ownership of the operation
+ * preventing the invocation of lower priority features. False, otherwise.
+ */
+ default boolean afterLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,
+ String message) {
+ return false;
+ }
+
+}
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/utils/NetLoggerUtil.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/utils/NetLoggerUtil.java
new file mode 100644
index 00000000..f82e6a8c
--- /dev/null
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/utils/NetLoggerUtil.java
@@ -0,0 +1,153 @@
+/*
+ * ============LICENSE_START=======================================================
+ * policy-endpoints
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.utils;
+
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.features.NetLoggerFeatureApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A network logging utility class that allows drools applications code to access the
+ * network log (or other specified loggers) and logging features.
+ *
+ */
+public class NetLoggerUtil {
+
+ /**
+ * Loggers.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(NetLoggerUtil.class);
+ private static final Logger netLogger = LoggerFactory.getLogger("network");
+
+ /**
+ * Constant for the system line separator.
+ */
+ public static final String SYSTEM_LS = System.lineSeparator();
+
+ /**
+ * Specifies if the message is coming in or going out.
+ */
+ public enum EventType {
+ IN, OUT
+ }
+
+ /**
+ * Get Network Logger.
+ *
+ * @return logger instance
+ */
+ public static Logger getNetworkLogger() {
+ return netLogger;
+ }
+
+ /**
+ * Logs a message to the network logger.
+ *
+ * @param type can either be IN or OUT
+ * @param protocol the protocol used to receive/send the message
+ * @param topic the topic the message came from or null if the type is REST
+ * @param message message to be logged
+ */
+ public static void log(EventType type, CommInfrastructure protocol, String topic, String message) {
+ log(netLogger, type, protocol, topic, message);
+ }
+
+ /**
+ * Logs a message to the specified logger (i.e. a controller logger).
+ *
+ * @param eventLogger the logger that will have the message appended
+ * @param type can either be IN or OUT
+ * @param protocol the protocol used to receive/send the message
+ * @param topic the topic the message came from or null if the type is REST
+ * @param message message to be logged
+ */
+ public static void log(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,
+ String message) {
+ if (eventLogger == null) {
+ logger.debug("the logger is null, defaulting to network logger");
+ eventLogger = netLogger;
+ }
+
+ if (featureBeforeLog(eventLogger, type, protocol, topic, message)) {
+ return;
+ }
+
+ eventLogger.info("[{}|{}|{}]{}{}", type, protocol, topic, SYSTEM_LS, message);
+
+ featureAfterLog(eventLogger, type, protocol, topic, message);
+ }
+
+ /**
+ * Executes features that pre-process a message before it is logged.
+ *
+ * @param eventLogger the logger that will have the message appended
+ * @param type can either be IN or OUT
+ * @param protocol the protocol used to receive/send the message
+ * @param topic the topic the message came from or null if the type is REST
+ * @param message message to be logged
+ *
+ * @return true if this feature intercepts and takes ownership of the operation
+ * preventing the invocation of lower priority features. False, otherwise
+ */
+ private static boolean featureBeforeLog(Logger eventLogger, EventType type, CommInfrastructure protocol,
+ String topic, String message) {
+ for (NetLoggerFeatureApi feature : NetLoggerFeatureApi.providers.getList()) {
+ try {
+ if (feature.beforeLog(eventLogger, type, protocol, topic, message)) {
+ return true;
+ }
+ } catch (Exception e) {
+ logger.error("feature {} before-log failure because of {}", feature.getClass().getName(),
+ e.getMessage(), e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Executes features that post-process a message after it is logged.
+ *
+ * @param eventLogger the logger that will have the message appended
+ * @param type can either be IN or OUT
+ * @param protocol the protocol used to receive/send the message
+ * @param topic the topic the message came from or null if the type is rest
+ * @param message message to be logged
+ *
+ * @return true if this feature intercepts and takes ownership of the operation
+ * preventing the invocation of lower priority features. False, otherwise
+ */
+ private static boolean featureAfterLog(Logger eventLogger, EventType type, CommInfrastructure protocol,
+ String topic, String message) {
+ for (NetLoggerFeatureApi feature : NetLoggerFeatureApi.providers.getList()) {
+ try {
+ if (feature.afterLog(eventLogger, type, protocol, topic, message)) {
+ return true;
+ }
+ } catch (Exception e) {
+ logger.error("feature {} after-log failure because of {}", feature.getClass().getName(), e.getMessage(),
+ e);
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/utils/NetLoggerUtilTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/utils/NetLoggerUtilTest.java
new file mode 100644
index 00000000..6e84c137
--- /dev/null
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/utils/NetLoggerUtilTest.java
@@ -0,0 +1,268 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-endpoints
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.endpoints.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.features.NetLoggerFeatureApi;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
+import org.slf4j.Logger;
+
+/**
+ * Test class for network log utilities such as logging and feature invocation.
+ */
+public class NetLoggerUtilTest {
+
+ private static final String MESSAGE = "hello world!";
+ /**
+ * Test feature used for junits.
+ */
+ private static NetLoggerFeature netLoggerFeature;
+
+ /**
+ * Obtains the test implementation of NetLoggerFeatureApi.
+ */
+ @BeforeClass
+ public static void setUp() {
+ netLoggerFeature = (NetLoggerFeature) NetLoggerFeatureApi.providers.getList().get(0);
+ }
+
+ /**
+ * Clears events list and resets return/exceptions flags before invoking every unit test.
+ */
+ @Before
+ public void reset() {
+ TestAppender.clear();
+ netLoggerFeature.setReturnValue(false, false);
+ netLoggerFeature.setExceptions(false, false);
+ }
+
+ /**
+ * Tests obtaining the network logger instance.
+ */
+ @Test
+ public void getNetworkLoggerTest() {
+ assertEquals("network", NetLoggerUtil.getNetworkLogger().getName());
+ }
+
+ /**
+ * Tests logging a message to the network logger and invoking features before/after logging.
+ */
+ @Test
+ public void logTest() {
+ NetLoggerUtil.log(EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(3, TestAppender.events.size());
+ }
+
+ /**
+ * Tests that the network logger is used to log messages if a logger is not passed in.
+ */
+ @Test
+ public void logDefaultTest() {
+ NetLoggerUtil.log(null, EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(3, TestAppender.events.size());
+ assertEquals("network", TestAppender.events.get(0).getLoggerName());
+ }
+
+ /**
+ * Tests a NetLoggerFeature that replaces base implementation before logging.
+ */
+ @Test
+ public void beforeLogReturnTrueTest() {
+ netLoggerFeature.setReturnValue(true, false);
+ NetLoggerUtil.log(null, EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(1, TestAppender.events.size());
+ }
+
+ /**
+ * Tests a NetLoggerFeature that post processes a logged message.
+ */
+ @Test
+ public void afterLogReturnTrueTest() {
+ netLoggerFeature.setReturnValue(false, true);
+ NetLoggerUtil.log(null, EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(3, TestAppender.events.size());
+ }
+
+ /**
+ * Tests throwing an exception in the before hook.
+ */
+ @Test
+ public void beforeLogExceptionTest() {
+ netLoggerFeature.setExceptions(true, false);
+ NetLoggerUtil.log(null, EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(2, TestAppender.events.size());
+ }
+
+ /**
+ * Tests throwing an exception in the after hook.
+ */
+ @Test
+ public void afterLogExceptionTest() {
+ netLoggerFeature.setExceptions(false, true);
+ NetLoggerUtil.log(null, EventType.IN, CommInfrastructure.NOOP, "test-topic", MESSAGE);
+ assertEquals(2, TestAppender.events.size());
+ }
+
+ /**
+ * A custom list appender to track messages being logged to the network logger.
+ * NOTE: Check src/test/resources/logback-test.xml for network logger configurations.
+ */
+ public static class TestAppender extends AppenderBase<ILoggingEvent> {
+
+ /**
+ * List of logged events.
+ */
+ public static List<ILoggingEvent> events = new ArrayList<>();
+
+ /**
+ * Called after every unit test to clear list of events.
+ */
+ public static void clear() {
+ events.clear();
+ }
+
+ /**
+ * Appends each event to the event list.
+ */
+ @Override
+ protected void append(ILoggingEvent event) {
+ events.add(event);
+ }
+
+ }
+
+ /**
+ * Test implementation of NetLoggerFeatureApi to be used by junits.
+ */
+ public static class NetLoggerFeature implements NetLoggerFeatureApi {
+
+ /**
+ * Used for setting the return values of before/after hooks.
+ */
+ private boolean beforeReturn = false;
+ private boolean afterReturn = false;
+
+ /**
+ * Used for throwing an exception in the before/after hooks.
+ */
+ private boolean beforeException = false;
+ private boolean afterException = false;
+
+
+ /**
+ * Gets sequence number.
+ */
+ @Override
+ public int getSequenceNumber() {
+ return 0;
+ }
+
+ /**
+ * Get beforeLog return value.
+ */
+ public boolean getBeforeReturn() {
+ return this.beforeReturn;
+ }
+
+ /**
+ * Get afterLog return value.
+ */
+ public boolean getAfterReturn() {
+ return this.afterReturn;
+ }
+
+ /**
+ * Sets the return value for the before/after hooks.
+ *
+ * @param beforeVal beforeLog() return value
+ * @param afterVal afterLog() return value
+ */
+ public void setReturnValue(boolean beforeVal, boolean afterVal) {
+ this.beforeReturn = beforeVal;
+ this.afterReturn = afterVal;
+ }
+
+ /**
+ * Gets beforeException boolean.
+ */
+ public boolean getBeforeException() {
+ return this.beforeException;
+ }
+
+ /**
+ * Gets afterException boolean.
+ */
+ public boolean getAfterException() {
+ return this.afterException;
+ }
+
+ /**
+ * Sets before/after flags to determine if the feature should throw an exception.
+ */
+ public void setExceptions(boolean beforeException, boolean afterException) {
+ this.beforeException = beforeException;
+ this.afterException = afterException;
+ }
+
+ /**
+ * Simple beforeLog message.
+ */
+ @Override
+ public boolean beforeLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,
+ String message) {
+
+ if (beforeException) {
+ throw new RuntimeException("beforeLog exception");
+ }
+
+ eventLogger.info("before feature test");
+
+ return this.beforeReturn;
+ }
+
+ /**
+ * Simple afterLog message.
+ */
+ @Override
+ public boolean afterLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,
+ String message) {
+
+ if (afterException) {
+ throw new RuntimeException("afterLog exception");
+ }
+
+ eventLogger.info("after feature test");
+
+ return this.afterReturn;
+ }
+
+ }
+
+}
diff --git a/policy-endpoints/src/test/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi b/policy-endpoints/src/test/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi
new file mode 100644
index 00000000..c861ad18
--- /dev/null
+++ b/policy-endpoints/src/test/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi
@@ -0,0 +1 @@
+org.onap.policy.common.endpoints.utils.NetLoggerUtilTest$NetLoggerFeature
diff --git a/policy-endpoints/src/test/resources/logback-test.xml b/policy-endpoints/src/test/resources/logback-test.xml
index b3feef90..4edcc9db 100644
--- a/policy-endpoints/src/test/resources/logback-test.xml
+++ b/policy-endpoints/src/test/resources/logback-test.xml
@@ -2,7 +2,7 @@
============LICENSE_START=======================================================
ONAP
================================================================================
- Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ Copyright (C) 2018-2019 AT&T Intellectual Property. 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.
@@ -27,8 +27,14 @@
</encoder>
</appender>
+ <appender name="testAppender" class="org.onap.policy.common.endpoints.utils.NetLoggerUtilTest$TestAppender"/>
+
<logger name="org.onap.policy.drools.http.server.test" level="INFO"/>
-
+
+ <logger name="network" level="INFO">
+ <appender-ref ref="testAppender" />
+ </logger>
+
<root level="WARN">
<appender-ref ref="STDOUT"/>
</root>
diff --git a/utils/src/main/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapper.java b/utils/src/main/java/org/onap/policy/common/utils/services/OrderedService.java
index 6f800015..c5050c83 100644
--- a/utils/src/main/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapper.java
+++ b/utils/src/main/java/org/onap/policy/common/utils/services/OrderedService.java
@@ -1,9 +1,8 @@
/*
* ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
+ * utils
* ================================================================================
- * Copyright (C) 2019 Samsung Electronics. All rights reserved.
- * Modifications Copyright (C) 2019 AT&T Intellectual Property.
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
@@ -19,29 +18,30 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.policy.common.utils.slf4j;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+package org.onap.policy.common.utils.services;
/**
- * Helper class to retrieve particular types of loggers without storing the logger name everywhere in ths code.
+ * This is a base interface that is used to control the order of a list
+ * of services (features) discovered via 'ServiceLoader'. See
+ * 'OrderedServiceImpl' for more details.
*/
-public class LoggerFactoryWrapper {
-
+@FunctionalInterface
+public interface OrderedService {
/**
- * Constructs the object.
+ * Get sequence number.
+ *
+ * @return an integer sequence number, which determines the order of a list
+ * of objects implementing this interface
*/
- private LoggerFactoryWrapper() {
- super();
- }
+ public int getSequenceNumber();
+
/**
- * Get Network Logger.
+ * Get the name.
*
- * @return logger instance
+ * @return the name of the ordered service
*/
- public static Logger getNetworkLogger() {
- return LoggerFactory.getLogger("network");
+ public default String getName() {
+ return this.getClass().getName();
}
}
diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/OrderedServiceImpl.java b/utils/src/main/java/org/onap/policy/common/utils/services/OrderedServiceImpl.java
new file mode 100644
index 00000000..bbd30220
--- /dev/null
+++ b/utils/src/main/java/org/onap/policy/common/utils/services/OrderedServiceImpl.java
@@ -0,0 +1,135 @@
+/*
+ * ============LICENSE_START=======================================================
+ * utils
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.services;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is a template for building a sorted list of service instances,
+ * which are discovered and created using 'ServiceLoader'.
+ */
+public class OrderedServiceImpl<T extends OrderedService> {
+ // logger
+ private static Logger logger = LoggerFactory.getLogger(OrderedServiceImpl.class);
+
+ // sorted list of instances implementing the service
+ private List<T> implementers = null;
+
+ // 'ServiceLoader' that is used to discover and create the services
+ private ServiceLoader<T> serviceLoader = null;
+
+ // use this to ensure that we only use one unique instance of each class
+ @SuppressWarnings("rawtypes")
+ private static HashMap<Class,OrderedService> classToSingleton = new HashMap<>();
+
+ /**
+ * Constructor - create the 'ServiceLoader' instance.
+ *
+ * @param clazz the class object associated with 'T' (I supposed it could
+ * be a subclass, but I'm not sure this is useful)
+ */
+ public OrderedServiceImpl(Class<T> clazz) {
+ // This constructor wouldn't be needed if 'T.class' was legal
+ serviceLoader = ServiceLoader.load(clazz);
+ }
+
+ /**
+ * Get List of implementers.
+ *
+ * @return the sorted list of services implementing interface 'T' discovered
+ * by 'ServiceLoader'.
+ */
+ public synchronized List<T> getList() {
+ if (implementers == null) {
+ rebuildList();
+ }
+ return implementers;
+ }
+
+ /**
+ * This method is called by 'getList', but could also be called directly if
+ * we were running with a 'ClassLoader' that supported the dynamic addition
+ * of JAR files. In this case, it could be invoked in order to discover any
+ * new services implementing interface 'T'. This is probably a relatively
+ * expensive operation in terms of CPU and elapsed time, so it is best if it
+ * isn't invoked too frequently.
+ *
+ * @return the sorted list of services implementing interface 'T' discovered
+ * by 'ServiceLoader'.
+ */
+ @SuppressWarnings("unchecked")
+ public synchronized List<T> rebuildList() {
+ // build a list of all of the current implementors
+ List<T> tmp = new LinkedList<>();
+ for (T service : serviceLoader) {
+ tmp.add((T)getSingleton(service));
+ }
+
+ // Sort the list according to sequence number, and then alphabetically
+ // according to full class name.
+ Collections.sort(tmp, (o1, o2) -> {
+ int s1 = o1.getSequenceNumber();
+ int s2 = o2.getSequenceNumber();
+ if (s1 < s2) {
+ return -1;
+ } else if (s1 > s2) {
+ return 1;
+ } else {
+ return o1.getClass().getName().compareTo(o2.getClass().getName());
+ }
+ });
+
+ // create an unmodifiable version of this list
+ implementers = Collections.unmodifiableList(tmp);
+ logger.info("***** OrderedServiceImpl implementers:\n {}", implementers);
+ return implementers;
+ }
+
+ /**
+ * If a service implements multiple APIs managed by 'ServiceLoader', a
+ * separate instance is created for each API. This method ensures that
+ * the first instance is used in all of the lists.
+ *
+ * @param service this is the object created by ServiceLoader
+ * @return the object to use in place of 'service'. If 'service' is the first
+ * object of this class created by ServiceLoader, it is returned. If not,
+ * the object of this class that was initially created is returned
+ * instead.
+ */
+ private static synchronized OrderedService getSingleton(OrderedService service) {
+ // see if we already have an instance of this class
+ OrderedService rval = classToSingleton.get(service.getClass());
+ if (rval == null) {
+ // No previous instance of this class exists -- use the supplied
+ // instance, and place it in the table.
+ rval = service;
+ classToSingleton.put(service.getClass(), service);
+ }
+ return rval;
+ }
+}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java b/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
index eb918d35..e5a79bc3 100644
--- a/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
+++ b/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
@@ -250,7 +250,9 @@ public class ResourceUtilsTest {
assertNull(theString);
theString = ResourceUtils.getResourceAsString("");
- assertEquals("logback-test.xml\norg\ntestdir\n", theString);
+
+ assertEquals("logback-test.xml\nMETA-INF\norg\ntestdir\n", theString);
+
}
@Test
diff --git a/utils/src/test/java/org/onap/policy/common/utils/services/OrderedServiceImplTest.java b/utils/src/test/java/org/onap/policy/common/utils/services/OrderedServiceImplTest.java
new file mode 100644
index 00000000..39c8a2be
--- /dev/null
+++ b/utils/src/test/java/org/onap/policy/common/utils/services/OrderedServiceImplTest.java
@@ -0,0 +1,205 @@
+/*
+ * ============LICENSE_START=======================================================
+ * utils
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.services;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class OrderedServiceImplTest {
+
+ private static final int HIGH_PRIORITY_NUM = -1000;
+ private static final int LOW_PRIORITY_NUM = 1000;
+
+ private static GenericService highPrioService;
+ private static GenericService lowPrioService;
+
+ /**
+ * Saves the original state of the ordered service list to restore after each test.
+ */
+ @BeforeClass
+ public static void setup() {
+ List<GenericService> implementers = GenericService.providers.getList();
+ highPrioService = implementers.get(0);
+ lowPrioService = implementers.get(1);
+ }
+
+ /**
+ * Restores original state after each test.
+ */
+ @Before
+ public void resetOrder() {
+ highPrioService.setSequenceNumber(HIGH_PRIORITY_NUM);
+ lowPrioService.setSequenceNumber(LOW_PRIORITY_NUM);
+ }
+
+ /**
+ * Tests obtaining a list of service implementers.
+ */
+ @Test
+ public void getListTest() {
+ List<GenericService> implementers = GenericService.providers.getList();
+ assertEquals(2, implementers.size());
+
+ assertEquals(highPrioService, implementers.get(0));
+ assertEquals(HIGH_PRIORITY_NUM, highPrioService.getSequenceNumber());
+
+ assertEquals(lowPrioService, implementers.get(1));
+ assertEquals(LOW_PRIORITY_NUM, lowPrioService.getSequenceNumber());
+ }
+
+ /**
+ * Tests inverting the priority of two services to ensure the list is rebuilt
+ * with the new order.
+ */
+ @Test
+ public void rebuildListInvertedPriorityTest() {
+
+ List<GenericService> implementers = GenericService.providers.getList();
+ assertEquals(2, implementers.size());
+
+ assertEquals(highPrioService, implementers.get(0));
+ assertEquals(HIGH_PRIORITY_NUM, highPrioService.getSequenceNumber());
+
+ assertEquals(lowPrioService, implementers.get(1));
+ assertEquals(LOW_PRIORITY_NUM, lowPrioService.getSequenceNumber());
+
+ highPrioService.setSequenceNumber(LOW_PRIORITY_NUM);
+ lowPrioService.setSequenceNumber(HIGH_PRIORITY_NUM);
+
+ implementers = GenericService.providers.rebuildList();
+ assertEquals(2, implementers.size());
+
+ assertEquals(lowPrioService, implementers.get(0));
+ assertEquals(HIGH_PRIORITY_NUM, lowPrioService.getSequenceNumber());
+
+ assertEquals(highPrioService, implementers.get(1));
+ assertEquals(LOW_PRIORITY_NUM, highPrioService.getSequenceNumber());
+
+ }
+
+ /**
+ * Tests that the service list is ordered alphabetically by class names
+ * if the priorities are equivalent.
+ */
+ @Test
+ public void rebuildListEqualPriorityTest() {
+
+ List<GenericService> implementers = GenericService.providers.getList();
+ assertEquals(2, implementers.size());
+
+ assertEquals(highPrioService, implementers.get(0));
+ assertEquals(HIGH_PRIORITY_NUM, highPrioService.getSequenceNumber());
+
+ assertEquals(lowPrioService, implementers.get(1));
+ assertEquals(LOW_PRIORITY_NUM, lowPrioService.getSequenceNumber());
+
+ highPrioService.setSequenceNumber(LOW_PRIORITY_NUM);
+ lowPrioService.setSequenceNumber(LOW_PRIORITY_NUM);
+
+ implementers = GenericService.providers.rebuildList();
+ assertEquals(2, implementers.size());
+
+ assertEquals(highPrioService, implementers.get(0));
+ assertEquals(LOW_PRIORITY_NUM, highPrioService.getSequenceNumber());
+
+ assertEquals(lowPrioService, implementers.get(1));
+ assertEquals(LOW_PRIORITY_NUM, lowPrioService.getSequenceNumber());
+
+ }
+
+ /**
+ * Test interface that extends OrderedService to allow changing the sequence number.
+ */
+ public static interface GenericService extends OrderedService {
+
+ /**
+ * Providers of the GenericService interface.
+ */
+ OrderedServiceImpl<GenericService> providers = new OrderedServiceImpl<>(GenericService.class);
+
+ /**
+ * Sets the sequence number of the service.
+ */
+ public void setSequenceNumber(int seqNum);
+
+ }
+
+ /**
+ * A high priority service class.
+ */
+ public static class HighPriorityService implements GenericService {
+
+ /**
+ * Defaults to a high priority.
+ */
+ private int seqNum = HIGH_PRIORITY_NUM;
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public int getSequenceNumber() {
+ return this.seqNum;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void setSequenceNumber(int seqNum) {
+ this.seqNum = seqNum;
+ }
+
+ }
+
+ /**
+ * A low priority service class.
+ */
+ public static class LowPriorityService implements GenericService {
+
+ /**
+ * Defaults to a low priority.
+ */
+ private int seqNum = LOW_PRIORITY_NUM;
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public int getSequenceNumber() {
+ return this.seqNum;
+ }
+
+ /**
+ * {@inheritDoc}.
+ */
+ @Override
+ public void setSequenceNumber(int seqNum) {
+ this.seqNum = seqNum;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/utils/src/test/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapperTest.java b/utils/src/test/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapperTest.java
deleted file mode 100644
index 4bf8db30..00000000
--- a/utils/src/test/java/org/onap/policy/common/utils/slf4j/LoggerFactoryWrapperTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * Copyright (C) 2019 Samsung Electronics. All rights reserved.
- * Modifications Copyright (C) 2019 AT&T Intellectual Property.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-
-package org.onap.policy.common.utils.slf4j;
-
-import static org.junit.Assert.assertSame;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(LoggerFactory.class)
-public class LoggerFactoryWrapperTest {
- @Test
- public void test_get_network_logger() {
- String netLoggerName = "network";
- Logger mockLogger = mock(Logger.class);
-
- PowerMockito.mockStatic(LoggerFactory.class);
-
- PowerMockito.when(LoggerFactory.getLogger(netLoggerName)).thenReturn(mockLogger);
- assertSame(mockLogger, LoggerFactoryWrapper.getNetworkLogger());
- }
-}
diff --git a/utils/src/test/resources/META-INF/services/org.onap.policy.common.utils.services.OrderedServiceImplTest$GenericService b/utils/src/test/resources/META-INF/services/org.onap.policy.common.utils.services.OrderedServiceImplTest$GenericService
new file mode 100644
index 00000000..1e920f46
--- /dev/null
+++ b/utils/src/test/resources/META-INF/services/org.onap.policy.common.utils.services.OrderedServiceImplTest$GenericService
@@ -0,0 +1,2 @@
+org.onap.policy.common.utils.services.OrderedServiceImplTest$HighPriorityService
+org.onap.policy.common.utils.services.OrderedServiceImplTest$LowPriorityService \ No newline at end of file