From abbbaf088ace3917f6cd7839279bd07816e94f80 Mon Sep 17 00:00:00 2001
From: Luke Parker
Date: Tue, 8 May 2018 19:32:41 +1000
Subject: SLF4J adapter (in 'common') + call graph demo
Issue-ID: LOG-115
Change-Id: I0ba28c64b1aaeb571094409704f4f00313afdf36
Signed-off-by: Luke Parker
---
.../logging/ref/slf4j/common/ONAPLogAdapter.java | 611 +++++++++++++++++++++
.../logging/ref/slf4j/common/ONAPLogConstants.java | 228 ++++++++
.../logging/ref/slf4j/common/package-info.java | 32 ++
.../ref/slf4j/demo/SLF4JRefApplication.java | 42 ++
.../logging/ref/slf4j/demo/bean/AbstractBean.java | 96 ++++
.../onap/logging/ref/slf4j/demo/bean/Request.java | 64 +++
.../onap/logging/ref/slf4j/demo/bean/Response.java | 63 +++
.../logging/ref/slf4j/demo/bean/package-info.java | 26 +
.../slf4j/demo/component/AbstractComponent.java | 278 ++++++++++
.../slf4j/demo/component/alpha/ComponentAlpha.java | 53 ++
.../slf4j/demo/component/alpha/package-info.java | 26 +
.../slf4j/demo/component/beta/ComponentBeta.java | 53 ++
.../slf4j/demo/component/beta/package-info.java | 26 +
.../slf4j/demo/component/delta/ComponentDelta.java | 53 ++
.../slf4j/demo/component/delta/package-info.java | 26 +
.../slf4j/demo/component/gamma/ComponentGamma.java | 53 ++
.../slf4j/demo/component/gamma/package-info.java | 26 +
.../ref/slf4j/demo/component/package-info.java | 26 +
.../onap/logging/ref/slf4j/demo/package-info.java | 30 +
19 files changed, 1812 insertions(+)
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapter.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogConstants.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java
create mode 100644 reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java
(limited to 'reference/slf4j-reference/src/main/java')
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapter.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapter.java
new file mode 100644
index 0000000..898cfb3
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapter.java
@@ -0,0 +1,611 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.common;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.event.Level;
+
+/**
+ * Extensible adapter for cheaply meeting ONAP logging obligations using
+ * an SLF4J facade.
+ *
+ * This can be used with any SLF4J-compatible logging provider, with
+ * appropriate provider configuration.
+ *
+ * The basics are that:
+ *
+ * - {@link #entering} sets all MDCs.
+ * - {@link #exiting} unsets all MDCs *and* logs response information.
+ * - {@link #invoke} logs and returns a UUID to passed during invocation,
+ * and optionally sets these for you on your downstream request by way of
+ * an adapter.
+ * - Call {@link #getServiceDescriptor()} and its setters to set service-related MDCs.
+ * - Call {@link #getResponseDescriptor()} and its setters to set response-related MDCs.
+ *
+ *
+ *
+ * Minimal usage is:
+ *
+ * - #entering(RequestAdapter)
+ * - #invoke, #invoke, ...
+ * - #getResponse + setters (or #setResponse)
+ * - #exiting
+ *
+ *
+ *
+ * ... if you're happy for service information to be automatically derived as follows:
+ *
+ * - ServiceName - from HttpServletRequest#getRequestURI()
+ * - InstanceUUID - classloader-scope UUID.
+ *
+ *
+ *
+ * ... and if those defaults don't suit, then you can override using properties on
+ * {@link #getServiceDescriptor()}, or by injecting your own adapter using
+ * {@link #setServiceDescriptor(ServiceDescriptor)}, or by overriding
+ * a protected methods like{@link #setEnteringMDCs}.
+ *
+ * For everything else:
+ *
+ * - The underlying SLF4J {@link Logger} can be retrieved using {@link #unwrap}.
+ * Use this or create your own using the usual SLF4J factor.
+ * - Set whatever MDCs you like.
+ * - Log whatever else you like.
+ *
+ *
+ */
+public class ONAPLogAdapter {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constants.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /** String constant for messages ENTERING, EXITING, etc. */
+ private static final String EMPTY_MESSAGE = "";
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Fields.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /** Automatic UUID, overrideable per adapter or per invocation. */
+ private static UUID sInstanceUUID = UUID.randomUUID();
+
+ /** Logger delegate. */
+ private Logger mLogger;
+
+ /** Overrideable descriptor for the service doing the logging. */
+ private ServiceDescriptor mServiceDescriptor = new ServiceDescriptor();
+
+ /** Overrideable descriptor for the response returned by the service doing the logging. */
+ private ResponseDescriptor mResponseDescriptor = new ResponseDescriptor();
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Construct adapter.
+ *
+ * @param logger non-null logger.
+ */
+ public ONAPLogAdapter(final Logger logger) {
+ this.mLogger = checkNotNull(logger);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Public methods.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Get logger.
+ *
+ * @return unwrapped logger.
+ */
+ public Logger unwrap() {
+ return this.mLogger;
+ }
+
+ /**
+ * Report ENTERING marker.
+ *
+ * @param request non-null incoming request (wrapper).
+ * @return this.
+ */
+ public ONAPLogAdapter entering(final RequestAdapter request) {
+
+ checkNotNull(request);
+
+ // Default the service name.
+
+ this.setEnteringMDCs(request);
+ this.mLogger.info(ONAPLogConstants.Markers.ENTRY, EMPTY_MESSAGE);
+
+ return this;
+ }
+
+ /**
+ * Report ENTERING marker.
+ *
+ * @param request non-null incoming request.
+ * @return this.
+ */
+ public ONAPLogAdapter entering(final HttpServletRequest request) {
+ return this.entering(new HttpServletRequestAdapter(checkNotNull(request)));
+ }
+
+ /**
+ * Report EXITING marker.
+ *
+ * @return this.
+ */
+ public ONAPLogAdapter exiting() {
+ try {
+ this.mResponseDescriptor.setMDCs();
+ this.mLogger.info(ONAPLogConstants.Markers.EXIT, EMPTY_MESSAGE);
+ }
+ finally {
+ MDC.clear();
+ }
+ return this;
+ }
+
+ /**
+ * Report pending invocation with INVOKE marker.
+ *
+ * If you call this variant, then YOU are assuming responsibility for
+ * setting the requisite ONAP headers.
+ *
+ * @param sync whether synchronous.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final ONAPLogConstants.InvocationMode sync) {
+
+ final UUID invocationID = UUID.randomUUID();
+
+ // Derive SYNC/ASYNC marker.
+
+ final Marker marker = (sync == null) ? ONAPLogConstants.Markers.INVOKE : sync.getMarker();
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+
+ this.mLogger.info(marker, "{}", invocationID);
+ return invocationID;
+ }
+
+ /**
+ * Report pending invocation with INVOKE marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param builder request builder, for setting headers.
+ * @param sync whether synchronous, nullable.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final RequestBuilder builder,
+ final ONAPLogConstants.InvocationMode sync) {
+
+ // Sync can be defaulted. Builder cannot.
+
+ checkNotNull(builder);
+
+ // Log INVOKE, and retain invocation ID for header + return.
+
+ final UUID invocationID = this.invoke(sync);
+
+ // Set standard HTTP headers on (southbound request) builder.
+
+ builder.setHeader(ONAPLogConstants.Headers.REQUEST_ID,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)));
+ builder.setHeader(ONAPLogConstants.Headers.INVOCATION_ID,
+ defaultToEmpty(invocationID));
+ builder.setHeader(ONAPLogConstants.Headers.PARTNER_NAME,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.PARTNER_NAME)));
+
+ return invocationID;
+ }
+
+ /**
+ * Report vanilla INVOKE marker.
+ *
+ * @param builder builder for downstream requests, if you want the
+ * standard ONAP headers to be added automatically.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final RequestBuilder builder) {
+ return this.invoke(builder, (ONAPLogConstants.InvocationMode)null);
+ }
+
+ /**
+ * Get descriptor, for overriding service details.
+ * @return non-null descriptor.
+ */
+ public ServiceDescriptor getServiceDescriptor() {
+ return checkNotNull(this.mServiceDescriptor);
+ }
+
+ /**
+ * Override {@link ServiceDescriptor}.
+ * @param d non-null override.
+ * @return this.
+ */
+ public ONAPLogAdapter setServiceDescriptor(final ServiceDescriptor d) {
+ this.mServiceDescriptor = checkNotNull(d);
+ return this;
+ }
+
+ /**
+ * Get descriptor, for setting response details.
+ * @return non-null descriptor.
+ */
+ public ResponseDescriptor getResponseDescriptor() {
+ return checkNotNull(this.mResponseDescriptor);
+ }
+
+ /**
+ * Override {@link ResponseDescriptor}.
+ * @param d non-null override.
+ * @return this.
+ */
+ public ONAPLogAdapter setResponseDescriptor(final ResponseDescriptor d) {
+ this.mResponseDescriptor = checkNotNull(d);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Protected methods.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Set MDCs that persist for the duration of an invocation.
+ *
+ * It would be better to roll this into {@link #entering}, like
+ * with {@link #exiting}. Then it would be easier to do, but it
+ * would mean more work.
+ *
+ * @param request incoming HTTP request.
+ * @return this.
+ */
+ protected ONAPLogAdapter setEnteringMDCs(final RequestAdapter> request) {
+
+ // Extract MDC values from standard HTTP headers.
+
+ final String requestID = defaultToUUID(request.getHeader(ONAPLogConstants.Headers.REQUEST_ID));
+ final String invocationID = defaultToUUID(request.getHeader(ONAPLogConstants.Headers.INVOCATION_ID));
+ final String partnerName = defaultToEmpty(request.getHeader(ONAPLogConstants.Headers.PARTNER_NAME));
+
+ // Set standard MDCs. Override this entire method if you want to set
+ // others, OR set them BEFORE or AFTER the invocation of #entering,
+ // depending on where you need them to appear, OR extend the
+ // ServiceDescriptor to add them.
+
+ MDC.put(ONAPLogConstants.MDCs.ENTRY_TIMESTAMP, LocalDateTime.now().toString());
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestID);
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationID);
+ MDC.put(ONAPLogConstants.MDCs.PARTNER_NAME, partnerName);
+ MDC.put(ONAPLogConstants.MDCs.CLIENT_IP_ADDRESS, defaultToEmpty(request.getClientAddress()));
+ MDC.put(ONAPLogConstants.MDCs.SERVER_FQDN, defaultToEmpty(request.getServerAddress()));
+
+ // Delegate to the service adapter, for service-related DMCs.
+
+ this.mServiceDescriptor.setMDCs();
+
+ // Default the service name to the requestURI, in the event that
+ // no value has been provided.
+
+ if (MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME) == null) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, request.getRequestURI());
+ }
+
+ return this;
+ }
+
+ /**
+ * Dependency-free nullcheck.
+ *
+ * @param in to be checked.
+ * @param argument (and return) type.
+ * @return input arg.
+ */
+ protected static T checkNotNull(final T in) {
+ if (in == null) {
+ throw new NullPointerException();
+ }
+ return in;
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered.
+ * @return input string or null.
+ */
+ protected static String defaultToEmpty(final Object in) {
+ if (in == null) {
+ return "";
+ }
+ return in.toString();
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered.
+ * @return input string or null.
+ */
+ protected static String defaultToUUID(final String in) {
+ if (in == null) {
+ return UUID.randomUUID().toString();
+ }
+ return in;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Extensible descriptor for reporting service details.
+ *
+ * In most cases extension isn't required.
+ */
+ public static class ServiceDescriptor {
+
+ /** ServiceName. */
+ protected String mName;
+
+ /** InstanceUUID. */
+ protected String mUUID = sInstanceUUID.toString();
+
+ /**
+ * Set name.
+ * @param name ServiceName.
+ * @return this.
+ */
+ public ServiceDescriptor setServiceName(final String name) {
+ this.mName = name;
+ return this;
+ }
+
+ /**
+ * Set name.
+ * @param uuid InstanceUUID.
+ * @return this.
+ */
+ public ServiceDescriptor setServiceUUID(final String uuid) {
+ this.mUUID = uuid;
+ return this;
+ }
+
+ /**
+ * Set MDCs. Once set they remain set until everything is cleared.
+ */
+ protected void setMDCs() {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, defaultToEmpty(this.mName));
+ MDC.put(ONAPLogConstants.MDCs.INSTANCE_UUID, defaultToEmpty(this.mUUID));
+ }
+ }
+
+ /**
+ * Response is different in that response MDCs are normally only
+ * reported once, for a single log message. (But there's no method
+ * for clearing them, because this is only expected to be called
+ * during #exiting.)
+ */
+ public static class ResponseDescriptor {
+
+ /** Response errorcode. */
+ protected String mCode;
+
+ /** Response description. */
+ protected String mDescription;
+
+ /** Response severity. */
+ protected Level mSeverity;
+
+ /** Response status, of {COMPLETED, ERROR}. */
+ protected ONAPLogConstants.ResponseStatus mStatus;
+
+ /**
+ * Setter.
+ *
+ * @param code response (error) code.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseCode(final String code) {
+ this.mCode = code;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param description response description.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseDescription(final String description) {
+ this.mDescription = description;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param severity response outcome severity.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseSeverity(final Level severity) {
+ this.mSeverity = severity;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param status response overall status.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseStatus(final ONAPLogConstants.ResponseStatus status) {
+ this.mStatus = status;
+ return this;
+ }
+
+ /**
+ * Overrideable method to set MDCs based on property values.
+ */
+ protected void setMDCs() {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, defaultToEmpty(this.mCode));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, defaultToEmpty(this.mDescription));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_SEVERITY, defaultToEmpty(this.mSeverity));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS, defaultToEmpty(this.mStatus));
+ }
+ }
+
+ /**
+ * Adapter for reading information from an incoming HTTP request.
+ *
+ * Incoming is generally easy, because in most cases you'll be able to
+ * get your hands on the HttpServletRequest.
+ *
+ * Perhaps should be generalized to refer to constants instead of
+ * requiring the implementation of specific methods.
+ *
+ * @param type, for chaining.
+ */
+ public interface RequestAdapter {
+
+ /**
+ * Get header by name.
+ * @param name header name.
+ * @return header value, or null.
+ */
+ String getHeader(String name);
+
+ /**
+ * Get client address.
+ * @return address, if available.
+ */
+ String getClientAddress();
+
+ /**
+ * Get server address.
+ * @return address, if available.
+ */
+ String getServerAddress();
+
+ /**
+ * Get default service name, from service URI.
+ * @return service name default.
+ */
+ String getRequestURI();
+ }
+
+ /**
+ * Default {@link RequestBuilder} impl for {@link HttpServletRequest}, which
+ * will should available for most incoming REST requests.
+ */
+ public static class HttpServletRequestAdapter implements RequestAdapter {
+
+ /** Wrapped HTTP request. */
+ private final HttpServletRequest mRequest;
+
+ /**
+ * Construct adapter for HTTP request.
+ * @param request to be wrapped;
+ */
+ public HttpServletRequestAdapter(final HttpServletRequest request) {
+ this.mRequest = checkNotNull(request);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHeader(final String name) {
+ return this.mRequest.getHeader(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getClientAddress() {
+ return this.mRequest.getRemoteAddr();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getServerAddress() {
+ return this.mRequest.getServerName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getRequestURI() {
+ return this.mRequest.getRequestURI();
+ }
+ }
+
+ /**
+ * Header builder, which (unlike {@link RequestAdapter} will tend to
+ * vary a lot from caller to caller, since they each get to choose their
+ * own REST (or HTTP, or whatever) client APIs.
+ *
+ * No default implementation, because there's no HTTP client that's
+ * sufficiently ubiquitous to warrant incurring a mandatory dependency.
+ *
+ * @param type, for chaining.
+ */
+ public interface RequestBuilder {
+
+ /**
+ * Set HTTP header.
+ * @param name header name.
+ * @param value header value.
+ * @return this.
+ */
+ T setHeader(String name, String value);
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogConstants.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogConstants.java
new file mode 100644
index 0000000..0274f80
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogConstants.java
@@ -0,0 +1,228 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.common;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * Constants for standard ONAP headers, MDCs, etc.
+ *
+ * See package-info.java.
+ */
+public final class ONAPLogConstants {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private ONAPLogConstants() {
+ throw new UnsupportedOperationException();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Marker constants.
+ */
+ public static final class Markers {
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ /** Marker reporting synchronous invocation. */
+ public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS");
+
+ /** Marker reporting asynchronous invocation. */
+ public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS");
+
+ /** Marker reporting entry into a component. */
+ public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+
+ /** Marker reporting exit from a component. */
+ public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
+
+ /**
+ * Build nested, detached marker.
+ * @param m1 top token.
+ * @param m2 sub-token.
+ * @return detached Marker.
+ */
+ private static Marker build(final String m1, final String m2) {
+ final Marker marker = MarkerFactory.getDetachedMarker(m1);
+ marker.add(MarkerFactory.getDetachedMarker(m2));
+ return marker;
+ }
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Markers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * MDC name constants.
+ */
+ public static final class MDCs {
+
+ /** MDC correlating messages for a logical transaction. */
+ public static final String REQUEST_ID = "RequestID";
+
+ /** MDC correlating messages for an invocation. */
+ public static final String INVOCATION_ID = "InvocationID";
+
+ /** MDC recording current service. */
+ public static final String SERVICE_NAME = "ServiceName";
+
+ /** MDC recording calling service. */
+ public static final String PARTNER_NAME = "PartnerName";
+
+ /** MDC recording current service instance. */
+ public static final String INSTANCE_UUID = "InstanceUUID";
+
+ /** MDC recording caller address. */
+ public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+
+ /** MDC recording server address. */
+ public static final String SERVER_FQDN = "ServerFQDN";
+
+ /** MDC recording timestamp at the start of the current invocation. */
+ public static final String ENTRY_TIMESTAMP = "EntryTimestamp";
+
+ /** MDC reporting outcome code. */
+ public static final String RESPONSE_CODE = "ResponseCode";
+
+ /** MDC reporting outcome description. */
+ public static final String RESPONSE_DESCRIPTION = "ResponseDescription";
+
+ /** MDC reporting outcome error level. */
+ public static final String RESPONSE_SEVERITY = "Severity";
+
+ /** MDC reporting outcome error level. */
+ public static final String RESPONSE_STATUS = "StatusCode";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private MDCs() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Header name constants.
+ */
+ public static final class Headers {
+
+ /** HTTP X-ONAP-RequestID header. */
+ public static final String REQUEST_ID = "X-ONAP-RequestID";
+
+ /** HTTP X-ONAP-InvocationID header. */
+ public static final String INVOCATION_ID = "X-ONAP-InvocationID";
+
+ /** HTTP X-ONAP-PartnerName header. */
+ public static final String PARTNER_NAME = "X-ONAP-PartnerName";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Headers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Enums.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Response success or not, for setting StatusCode.
+ */
+ public enum ResponseStatus {
+
+ /** Success. */
+ COMPLETED,
+
+ /** Not. */
+ ERROR,
+ }
+
+ /**
+ * Synchronous or asynchronous execution, for setting invocation marker.
+ */
+ public enum InvocationMode {
+
+ /** Synchronous, blocking. */
+ SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
+
+ /** Asynchronous, non-blocking. */
+ ASYNCHRONOUS("", Markers.INVOKE_ASYNCHRONOUS);
+
+ /** Enum value. */
+ private String mString;
+
+ /** Corresponding marker. */
+ private Marker mMarker;
+
+ /**
+ * Construct enum.
+ *
+ * @param s enum value.
+ * @param m corresponding Marker.
+ */
+ InvocationMode(final String s, final Marker m) {
+ this.mString = s;
+ this.mMarker = m;
+ }
+
+ /**
+ * Get Marker for enum.
+ *
+ * @return Marker.
+ */
+ public Marker getMarker() {
+ return this.mMarker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return this.mString;
+ }
+ }
+
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/package-info.java
new file mode 100644
index 0000000..d5c4375
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/package-info.java
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.common;
+
+/**
+ * Code in here has potential application outside this reference
+ * example, and accordingly:
+ *
+ * - Packaged in common.
+ * - Has minimal dependencies.
+ *
+ *
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java
new file mode 100644
index 0000000..ae6aa92
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Spring launcher, for testing invocations via REST.
+ */
+@SpringBootApplication
+public class SLF4JRefApplication {
+
+ /**
+ * Launch from CLI.
+ * @param args command-line args.
+ * @throws Exception launch error.
+ */
+ public static void main(final String[] args) throws Exception {
+ System.getProperties().setProperty("SLF4J_OUTPUT_DIRECTORY", ".");
+ SpringApplication.run(SLF4JRefApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java
new file mode 100644
index 0000000..6c6060d
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java
@@ -0,0 +1,96 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.bean;
+
+import org.json.JSONObject;
+
+/**
+ * Base class for {@link Request} and {@link Response} beans, since
+ * they're almost the same thing.
+ */
+public abstract class AbstractBean {
+
+ /** Bean property. */
+ private String mService;
+
+ /** Bean property. */
+ private String mCode;
+
+ /** Bean property. */
+ private String mSeverity;
+
+ /**
+ * Getter.
+ * @return bean property.
+ */
+ public String getService() {
+ return this.mService;
+ }
+
+ /**
+ * Setter.
+ * @param service bean property.
+ */
+ public void setService(final String service) {
+ this.mService = service;
+ }
+
+ /**
+ * Getter.
+ * @return bean property.
+ */
+ public String getCode() {
+ return this.mCode;
+ }
+
+ /**
+ * Setter.
+ * @param code bean property.
+ */
+ public void setCode(final String code) {
+ this.mCode = code;
+ }
+
+ /**
+ * Getter.
+ * @return bean property.
+ */
+ public String getSeverity() {
+ return this.mSeverity;
+ }
+
+ /**
+ * Setter.
+ * @param severity bean property.
+ */
+ public void setSeverity(final String severity) {
+ this.mSeverity = severity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return new JSONObject(this).toString(4);
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java
new file mode 100644
index 0000000..5318333
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.bean;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * Test class, describing a request to be executed.
+ */
+public class Request extends AbstractBean {
+
+ /** Subrequests to be executed. */
+ private final List mRequests = new ArrayList<>();
+
+ /**
+ * Get subrequests.
+ * @return subrequests.
+ */
+ public List getRequests() {
+ return mRequests;
+ }
+
+ /**
+ * Parse from serialized form.
+ * @param in JSON.
+ * @return parsed.
+ */
+ public static Request fromJSON(final JSONObject in) {
+ final Request request = new Request();
+ request.setService(in.optString("service"));
+ request.setCode(in.optString("code"));
+ request.setSeverity(in.optString("severity"));
+ final JSONArray requests = in.optJSONArray("requests");
+ if (requests != null) {
+ for (int i = 0 ; i < requests.length() ; i++) {
+ request.getRequests().add(Request.fromJSON(requests.getJSONObject(i)));
+ }
+ }
+ return request;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java
new file mode 100644
index 0000000..b0c6a4a
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java
@@ -0,0 +1,63 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.bean;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * Test class, describing an outcome that should be reported.
+ */
+public class Response extends AbstractBean {
+
+ /** Delegate responses. */
+ private final List mResponses = new ArrayList<>();
+
+ /**
+ * Get delegate responses.
+ * @return responses.
+ */
+ public List getResponses() {
+ return mResponses;
+ }
+
+ /**
+ * Parse from serialized form.
+ * @param in JSON.
+ * @return parsed.
+ */
+ public static Response fromJSON(final JSONObject in) {
+ final Response request = new Response();
+ request.setCode(in.optString("code"));
+ request.setSeverity(in.optString("severity"));
+ final JSONArray responses = in.optJSONArray("responses");
+ if (responses != null) {
+ for (int i = 0 ; i < responses.length() ; i++) {
+ request.getResponses().add(Response.fromJSON(responses.getJSONObject(i)));
+ }
+ }
+ return request;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java
new file mode 100644
index 0000000..2364f9f
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.bean;
+
+/**
+ * Simple request/responses beans for testcases.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java
new file mode 100644
index 0000000..236345f
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java
@@ -0,0 +1,278 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.mashape.unirest.http.HttpResponse;
+import com.mashape.unirest.http.JsonNode;
+import com.mashape.unirest.http.Unirest;
+import com.mashape.unirest.http.exceptions.UnirestException;
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
+import org.onap.logging.ref.slf4j.common.ONAPLogAdapter;
+import org.onap.logging.ref.slf4j.common.ONAPLogConstants;
+import org.onap.logging.ref.slf4j.demo.bean.Request;
+import org.onap.logging.ref.slf4j.demo.bean.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.http.MediaType;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Base class for Alpha, Beta and Gamma
+ * and Delta controllers, implementing all the actual logic.
+ *
+ * (The subclasses provide nothing but identifiers to allow them
+ * to be distinguished from one another, for the purposes of addressing
+ * requests and generating the call graph from their logger output.)
+ */
+@RestController
+public abstract class AbstractComponent {
+
+ /**
+ * Test switch, routing invocations between components in-process,
+ * rather than via REST over HTTP.
+ */
+ private static boolean sInProcess;
+
+ /**
+ * Get service identifier, used to derive {@link #getServiceName()},
+ * PartnerName, etc.
+ * @return alpha, beta, gamma.
+ */
+ protected abstract String getId();
+
+ /**
+ * Get component UUID.
+ * @return globally unique ID string.
+ */
+ protected abstract String getInstanceUUID();
+
+ /**
+ * Execute REST request.
+ * @param request request data.
+ * @param http HTTP request.
+ * @return response data.
+ * @throws UnirestException REST error.
+ */
+ @RequestMapping(value = "/invoke",
+ method = RequestMethod.POST,
+ consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE)
+ public Response execute(final Request request,
+ final HttpServletRequest http) throws UnirestException {
+
+ final ONAPLogAdapter adapter = new ONAPLogAdapter(this.getLogger());
+
+ try {
+
+ adapter.entering(new ONAPLogAdapter.HttpServletRequestAdapter(http));
+
+ final Response response = new Response();
+ response.setService(request.getService());
+ final String code = StringUtils.defaultString(request.getCode(), "OK").toUpperCase();
+ response.setCode(this.getId() + "." + code);
+ response.setSeverity(StringUtils.defaultString(request.getSeverity(), "INFO"));
+
+ for (final Request target : request.getRequests()) {
+ final Response targetResponse = this.executeDelegate(target, http, adapter);
+ response.getResponses().add(targetResponse);
+ }
+
+ return response;
+ }
+ finally {
+ adapter.exiting();
+ }
+ }
+
+ /**
+ * Set in-process mode, for unit testing.
+ */
+ static void setInProcess() {
+ sInProcess = true;
+ }
+
+ /**
+ * Execute request.
+ * @param request to be executed.
+ * @param http incoming HTTP request.
+ * @param logger logging adapter.
+ * @return response
+ */
+ private Response executeDelegate(final Request request,
+ final HttpServletRequest http,
+ final ONAPLogAdapter logger) {
+
+
+ notNull(request);
+ notNull(http);
+
+ // Downstream call.
+
+ try {
+
+ if (sInProcess) {
+ return this.executeInProcess(request, logger);
+ }
+
+ return this.executeREST(request, http, logger);
+ }
+ catch (final UnirestException | ReflectiveOperationException e) {
+ logger.unwrap().error("Execute error", e);
+ final Response response = new Response();
+ response.setCode((this.getServiceName() + ".INVOKE_ERROR").toUpperCase(Locale.getDefault()));
+ response.setSeverity("ERROR");
+ return response;
+ }
+ }
+
+ /**
+ * Execute invocation over REST.
+ * @param request mock request to be executed.
+ * @param http HTTP request, used (only) to address the outgoing request.
+ * @param logger logger adapter.
+ * @return invocation response.
+ * @throws UnirestException REST error.
+ */
+ private Response executeREST(final Request request,
+ final HttpServletRequest http,
+ final ONAPLogAdapter logger) throws UnirestException {
+ // Otherwise via REST.
+
+ logger.unwrap().info("Sending:\n{}", request);
+ final StringBuilder url = new StringBuilder();
+ url.append(http.getProtocol()).append("://");
+ url.append(http.getServerName()).append(':');
+ url.append(http.getServerPort()).append("/services/").append(request.getService());
+
+ final UUID invocationID = logger.invoke(ONAPLogConstants.InvocationMode.SYNCHRONOUS);
+ final HttpResponse response =
+ Unirest.post(url.toString())
+ .header(ONAPLogConstants.Headers.REQUEST_ID, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID))
+ .header(ONAPLogConstants.Headers.INVOCATION_ID, invocationID.toString())
+ .header(ONAPLogConstants.Headers.PARTNER_NAME, this.getServiceName())
+ .header("Accept", MediaType.APPLICATION_JSON_VALUE)
+ .header("Content-Type", MediaType.APPLICATION_JSON_VALUE)
+ .body(request)
+ .asJson();
+
+ // Parse response.
+
+ final JSONObject responseJSON = response.getBody().getObject();
+ logger.unwrap().info("Received:\n{}", responseJSON);
+ return Response.fromJSON(responseJSON);
+ }
+
+ /**
+ * Execute request in-process.
+ * @param request mock request to be executed.
+ * @param logger logger adapter.
+ * @return invocation response.
+ * @throws ReflectiveOperationException error loading target class.
+ * @throws UnirestException REST error.
+ */
+ private Response executeInProcess(final Request request,
+ final ONAPLogAdapter logger) throws ReflectiveOperationException, UnirestException {
+
+ logger.unwrap().info("Executing in-process:\n{}", request);
+
+ // Derive the name of the delegate class.
+
+ final String delegateClass
+ = AbstractComponent.class.getPackage().getName() + "." + request.getService()
+ + ".Component" + request.getService().substring(0, 1).toUpperCase()
+ + request.getService().substring(1);
+ logger.unwrap().info("Invoking in-process [{}].", delegateClass);
+ final AbstractComponent component = (AbstractComponent)Class.forName(delegateClass).newInstance();
+
+ // Using Spring mock since we're not *actually* going over HTTP.
+
+ final MockHttpServletRequest mock = new MockHttpServletRequest();
+
+ // Generate INVOCATION_ID, and set MDCs aside for safekeeping.
+ // (This is because when mocking, everything happens in the same thread.)
+
+ final UUID invocationID = logger.invoke(ONAPLogConstants.InvocationMode.SYNCHRONOUS);
+ final String requestID = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
+ final Map safekeeping = MDC.getCopyOfContextMap();
+
+ // Set headers.
+
+ mock.addHeader(ONAPLogConstants.Headers.REQUEST_ID, StringUtils.defaultString(requestID));
+ mock.addHeader(ONAPLogConstants.Headers.INVOCATION_ID, invocationID.toString());
+ mock.addHeader(ONAPLogConstants.Headers.PARTNER_NAME, this.getServiceName());
+
+ try {
+
+ MDC.clear();
+
+ // Execute.
+
+ return component.execute(request, mock);
+ }
+ finally {
+
+ // Restore MDCs.
+
+ safekeeping.forEach((k, v) -> MDC.put(k, v));
+ }
+ }
+
+ /**
+ * Ensure non-nullness.
+ * @param in to be checked.
+ * @param type.
+ * @return input value, not null.
+ */
+ private static T notNull(final T in) {
+ if (in == null) {
+ throw new AssertionError("");
+ }
+ return in;
+ }
+
+ /**
+ * Get service name, with default.
+ * @return service name, suitable for logging as MDC.
+ */
+ private String getServiceName() {
+ return "service." + StringUtils.defaultString(this.getId(), "unnamed");
+ }
+
+ /**
+ * Get logger instance.
+ * @return logger.
+ */
+ private Logger getLogger() {
+ return LoggerFactory.getLogger(this.getClass());
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java
new file mode 100644
index 0000000..d5cf182
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.alpha;
+
+import java.util.UUID;
+
+import org.onap.logging.ref.slf4j.demo.component.AbstractComponent;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Discrete service, identical to the others but with its own identifiers.
+ */
+@RequestMapping("/services/alpha")
+public class ComponentAlpha extends AbstractComponent {
+
+ /** Component instance UUID constant. */
+ private static final String INSTANCE_UUID = UUID.randomUUID().toString();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getId() {
+ return "alpha";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getInstanceUUID() {
+ return INSTANCE_UUID;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java
new file mode 100644
index 0000000..4fa0fbc
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.alpha;
+
+/**
+ * Example service.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java
new file mode 100644
index 0000000..9a4e6eb
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.beta;
+
+import java.util.UUID;
+
+import org.onap.logging.ref.slf4j.demo.component.AbstractComponent;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Discrete service, identical to the others but with its own identifiers.
+ */
+@RequestMapping("/services/beta")
+public class ComponentBeta extends AbstractComponent {
+
+ /** Component instance UUID constant. */
+ private static final String INSTANCE_UUID = UUID.randomUUID().toString();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getId() {
+ return "beta";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getInstanceUUID() {
+ return INSTANCE_UUID;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java
new file mode 100644
index 0000000..68d7f74
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.beta;
+
+/**
+ * Example service.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java
new file mode 100644
index 0000000..d63d80a
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.delta;
+
+import java.util.UUID;
+
+import org.onap.logging.ref.slf4j.demo.component.AbstractComponent;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Discrete service, identical to the others but with its own identifiers.
+ */
+@RequestMapping("/services/delta")
+public class ComponentDelta extends AbstractComponent {
+
+ /** Component instance UUID constant. */
+ private static final String INSTANCE_UUID = UUID.randomUUID().toString();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getId() {
+ return "delta";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getInstanceUUID() {
+ return INSTANCE_UUID;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java
new file mode 100644
index 0000000..4b02ab4
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.delta;
+
+/**
+ * Example service.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java
new file mode 100644
index 0000000..9294743
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.gamma;
+
+import java.util.UUID;
+
+import org.onap.logging.ref.slf4j.demo.component.AbstractComponent;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Discrete service, identical to the others but with its own identifiers.
+ */
+@RequestMapping("/services/gamma")
+public class ComponentGamma extends AbstractComponent {
+
+ /** Component instance UUID constant. */
+ private static final String INSTANCE_UUID = UUID.randomUUID().toString();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getId() {
+ return "gamma";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getInstanceUUID() {
+ return INSTANCE_UUID;
+ }
+}
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java
new file mode 100644
index 0000000..7f5e30a
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component.gamma;
+
+/**
+ * Example service.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java
new file mode 100644
index 0000000..c650948
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo.component;
+
+/**
+ * Components that demonstrate usage and participate in the test.
+ */
\ No newline at end of file
diff --git a/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java
new file mode 100644
index 0000000..feb5e85
--- /dev/null
+++ b/reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java
@@ -0,0 +1,30 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j.demo;
+
+/**
+ * Minimal, spring-boot refernce example.
+ *
+ * Code that exists for testing can have whatever dependencies
+ * it likes, but take care with the contents of common,
+ * since it may be useful elsewhere.
+ */
\ No newline at end of file
--
cgit 1.2.3-korg