Merge "Controller Blueprints Microservice"
authorDan Timoney <dt5972@att.com>
Tue, 4 Sep 2018 15:14:31 +0000 (15:14 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 4 Sep 2018 15:14:31 +0000 (15:14 +0000)
20 files changed:
ms/controllerblueprints/README.md
ms/controllerblueprints/application/etc/logback.xml
ms/controllerblueprints/application/etc/run.source
ms/controllerblueprints/application/opt/app/onap/config/application.properties
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplication.java
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/CorsConfig.java [deleted file]
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/SwaggerConfig.java
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/WebConfig.java
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java [new file with mode: 0644]
ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/CorsFilter.java [new file with mode: 0644]
ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java [new file with mode: 0644]
ms/controllerblueprints/application/src/test/resources/application.properties
ms/controllerblueprints/distribution/src/main/dc/docker-compose.yaml
ms/controllerblueprints/modules/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintConstants.kt
ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/ConfigModelService.java
ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ConfigModelRest.java
ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ModelTypeRest.java
ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ResourceDictionaryRest.java
ms/controllerblueprints/parent/pom.xml

index 070a541..4079daf 100755 (executable)
@@ -1,5 +1,8 @@
 Application VM Arguments :\r
 \r
+-DappName=ControllerBluePrints\r
+-Dms_name=org.onap.ccsdk.apps.controllerblueprints\r
+-DappVersion=1.0.0\r
 -Dlogging.config=etc/logback.xml\r
 -Dspring.config.location=opt/app/onap/config/\r
 -Dspring.datasource.url=jdbc:mysql://127.0.0.1:3306/sdnctl\r
index 44e9a8a..0a75e60 100644 (file)
   -->\r
 \r
 <configuration>\r
+\r
+    <property name="localPattern" value="%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n" />\r
+\r
+    <property name="defaultPattern" value="%date{ISO8601,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Timer}| %msg%n" />\r
+\r
+    <property name="debugLoggerPattern" value="%date{ISO8601,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Timer}|[%caller{3}]| %msg%n" />\r
+\r
     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
         <!-- encoders are assigned the type\r
              ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->\r
         <encoder>\r
-            <pattern>%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n</pattern>\r
+            <pattern>${defaultPattern}</pattern>\r
         </encoder>\r
     </appender>\r
 \r
index cba5e1d..fc1b4e5 100644 (file)
@@ -4,7 +4,7 @@ java -classpath "/etc:${APP_HOME}/lib/*:/lib/*:/src:/schema:/generated-sources:$
 -DVERSION_ROUTEOFFER_ENVCONTEXT=${BUNDLEVERSION}/${STICKYSELECTORKEY}/${ENVCONTEXT} \
 -DSecurityFilePath=/etc \
 -DREST_NAME_NORMALIZER_PATTERN_FILE=/etc/PatternInputs.txt \
--Dms_name=org.onap.ccsdk.apps.controllerblueprints.ControllerBlueprints \
+-Dms_name=org.onap.ccsdk.apps.controllerblueprints \
 -Dlogging.config=${APP_CONFIG_HOME}/logback.xml \
 -Djava.security.egd=file:/dev/./urandom \
 -DAPPNAME=${APP_NAME} -DAPPENV=${APP_ENV} -DAPPVERSION=${APP_VERSION} -DNAMESPACE=${NAMESPACE} \
index f075b57..3b6033e 100644 (file)
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+appName=ControllerBluePrints
+ms_name=org.onap.ccsdk.apps.controllerblueprints
+appVersion=1.0.0
 
 #logging.pattern.console=%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr($ threadId: {PID:- }){magenta} %clr(---){faint} %clr([ hostname: %X{hostname} serviceName: %X{serviceName} version: %X{version} transactionId: %X{transactionId} requestTimeStamp: %X{requestTimestamp}  responseTimeStamp: %X{responseTimestamp} duration: %X{duration}]){yellow} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex
 
@@ -23,6 +26,11 @@ logging.level.org.hibernate.type.descriptor.sql=debug
 #To Remove Null in JSON API Response
 spring.jackson.default-property-inclusion=non_null
 
+#Swagger Configuration
+swagger.contact.name=Brinda Santh Muthuramalingam
+swagger.contact.url=www.onap.com
+swagger.contact.email=brindasanth@onap.com
+
 spring.jpa.properties.hibernate.show_sql=true
 spring.jpa.properties.hibernate.use_sql_comments=true
 spring.jpa.properties.hibernate.format_sql=true
index 0a403b8..6e9dcd7 100644 (file)
@@ -22,6 +22,9 @@ import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException;
 import org.onap.ccsdk.apps.controllerblueprints.service.common.ErrorMessage;\r
 import org.springframework.http.HttpStatus;\r
 import org.springframework.http.ResponseEntity;\r
+import org.springframework.http.converter.HttpMessageNotReadableException;\r
+import org.springframework.web.HttpRequestMethodNotSupportedException;\r
+import org.springframework.web.bind.MethodArgumentNotValidException;\r
 import org.springframework.web.bind.annotation.ControllerAdvice;\r
 import org.springframework.web.bind.annotation.ExceptionHandler;\r
 import org.springframework.web.bind.annotation.RestController;\r
@@ -32,17 +35,26 @@ import org.springframework.web.context.request.WebRequest;
 @SuppressWarnings("unused")\r
 public class ApplicationExceptionHandler {\r
     private static EELFLogger log = EELFManager.getInstance().getLogger(ApplicationExceptionHandler.class);\r
+\r
     @ExceptionHandler(Exception.class)\r
     public final ResponseEntity<ErrorMessage> handleAllExceptions(Exception ex, WebRequest request) {\r
         log.error("Application Exception", ex);\r
-        ErrorMessage exceptionResponse = new ErrorMessage( ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getLocalizedMessage());\r
+        ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getLocalizedMessage());\r
         return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);\r
     }\r
 \r
+    @ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class,\r
+            HttpRequestMethodNotSupportedException.class})\r
+    public final ResponseEntity<ErrorMessage> handleBadRequest(Exception ex, WebRequest request) {\r
+        log.error("Bad Request Exception", ex);\r
+        ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), HttpStatus.BAD_REQUEST.value(), ex.getLocalizedMessage());\r
+        return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);\r
+    }\r
+\r
     @ExceptionHandler(BluePrintException.class)\r
     public final ResponseEntity<ErrorMessage> handleBlueprintException(BluePrintException ex, WebRequest request) {\r
         log.error("Application Blueprint Exception", ex);\r
-        ErrorMessage exceptionResponse = new ErrorMessage( ex.getMessage(), ex.getCode(), ex.getLocalizedMessage());\r
+        ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), ex.getCode(), ex.getLocalizedMessage());\r
         return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);\r
     }\r
 }\r
index 447e196..6b0efd8 100644 (file)
@@ -35,7 +35,7 @@ public class ControllerBluprintsApplication {
     private static EELFLogger log = EELFManager.getInstance().getLogger(ControllerBluprintsApplication.class);\r
 \r
     public static void main(String[] args) {\r
-        log.info("****** Starting Controller Bluprints Application **************");\r
+        log.info("****** Starting Controlled Blueprints Application ******");\r
         SpringApplication.run(ControllerBluprintsApplication.class, args);\r
     }\r
 \r
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/CorsConfig.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/CorsConfig.java
deleted file mode 100644 (file)
index d00d2c8..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*\r
- *  Copyright © 2017-2018 AT&T Intellectual Property.\r
- *\r
- *  Licensed under the Apache License, Version 2.0 (the "License");\r
- *  you may not use this file except in compliance with the License.\r
- *  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- *  Unless required by applicable law or agreed to in writing, software\r
- *  distributed under the License is distributed on an "AS IS" BASIS,\r
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- *  See the License for the specific language governing permissions and\r
- *  limitations under the License.\r
- */\r
-\r
-package org.onap.ccsdk.apps.controllerblueprints;\r
-\r
-\r
-import org.springframework.context.annotation.Bean;\r
-import org.springframework.context.annotation.Configuration;\r
-import org.springframework.web.cors.CorsConfiguration;\r
-import org.springframework.web.cors.reactive.CorsWebFilter;\r
-import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;\r
-import java.util.Arrays;\r
-\r
-/**\r
- * CorsConfig.java Purpose: Provide Configuration Generator CorsConfig Information\r
- *\r
- * @author Brinda Santh\r
- * @version 1.0\r
- */\r
-@Configuration\r
-public class CorsConfig {\r
-    /**\r
-     * This is a CORS Implementation for different Orgin GUI to access.\r
-     *\r
-     * @return CorsFilter\r
-     */\r
-    @Bean\r
-    CorsWebFilter corsWebFilter() {\r
-        CorsConfiguration corsConfig = new CorsConfiguration();\r
-        corsConfig.setAllowedOrigins(Arrays.asList("*"));\r
-        corsConfig.setMaxAge(8000L);\r
-        corsConfig.addAllowedMethod("*");\r
-\r
-        UrlBasedCorsConfigurationSource source =\r
-                new UrlBasedCorsConfigurationSource();\r
-        source.registerCorsConfiguration("/**", corsConfig);\r
-\r
-        return new CorsWebFilter(source);\r
-    }\r
-\r
-\r
-}\r
index 67e3e5d..cfcccf3 100644 (file)
 \r
 package org.onap.ccsdk.apps.controllerblueprints;\r
 \r
+import com.google.common.collect.Lists;\r
+import org.jetbrains.annotations.NotNull;\r
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;\r
+import org.springframework.beans.factory.annotation.Value;\r
 import org.springframework.context.annotation.Bean;\r
 import org.springframework.context.annotation.Configuration;\r
+import org.springframework.http.HttpStatus;\r
+import org.springframework.web.bind.annotation.RequestMethod;\r
 import springfox.documentation.builders.PathSelectors;\r
 import springfox.documentation.builders.RequestHandlerSelectors;\r
+import springfox.documentation.builders.ResponseMessageBuilder;\r
+import springfox.documentation.schema.ModelRef;\r
 import springfox.documentation.service.ApiInfo;\r
 import springfox.documentation.service.Contact;\r
+import springfox.documentation.service.Header;\r
+import springfox.documentation.service.ResponseMessage;\r
 import springfox.documentation.spi.DocumentationType;\r
 import springfox.documentation.spring.web.plugins.Docket;\r
 import springfox.documentation.swagger2.annotations.EnableSwagger2;\r
+\r
 import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
 \r
 /**\r
  * SwaggerConfig\r
@@ -36,10 +50,23 @@ import java.util.Collections;
 @EnableSwagger2\r
 @SuppressWarnings("unused")\r
 public class SwaggerConfig {\r
+    @Value("${appVersion}")\r
+    private String appVersion;\r
+    @Value("${swagger.contact.name}")\r
+    private String contactName;\r
+    @Value("${swagger.contact.url}")\r
+    private String contactUrl;\r
+    @Value("${swagger.contact.email}")\r
+    private String contactEmail;\r
+\r
     @Bean\r
     @SuppressWarnings("unused")\r
     public Docket api() {\r
         return new Docket(DocumentationType.SWAGGER_2)\r
+                .globalResponseMessage(RequestMethod.GET, getDefaultGetResponseMessages())\r
+                .globalResponseMessage(RequestMethod.POST, getDefaultPostResponseMessages())\r
+                .globalResponseMessage(RequestMethod.PUT, getDefaultPutResponseMessages())\r
+                .globalResponseMessage(RequestMethod.DELETE, getDefaultDeleteResponseMessages())\r
                 .select()\r
                 .apis(RequestHandlerSelectors.any())\r
                 .paths(PathSelectors.any())\r
@@ -51,11 +78,77 @@ public class SwaggerConfig {
         return new ApiInfo(\r
                 "Controller Blueprints API",\r
                 "Controller blueprints API for VNF Self Service.",\r
-                "1.0.0",\r
+                appVersion,\r
                 "Terms of service",\r
-                new Contact("Brinda Santh", "www.onap.com", "brindasanth@onap.com"),\r
+                new Contact(contactName, contactUrl, contactEmail),\r
                 "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", Collections.emptyList());\r
     }\r
 \r
+    private List<ResponseMessage> getDefaultGetResponseMessages() {\r
+        List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();\r
+        Map<String, Header> defaultHeaders = getDefaultResponseHeaders();\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.NOT_FOUND, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));\r
+        return defaultResponseMessages;\r
+    }\r
+\r
+    private List<ResponseMessage> getDefaultPostResponseMessages() {\r
+        List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();\r
+        Map<String, Header> defaultHeaders = getDefaultResponseHeaders();\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.CREATED, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));\r
+        return defaultResponseMessages;\r
+    }\r
+\r
+    private List<ResponseMessage> getDefaultPutResponseMessages() {\r
+        List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();\r
+        Map<String, Header> defaultHeaders = getDefaultResponseHeaders();\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));\r
+        return defaultResponseMessages;\r
+    }\r
+\r
+    private List<ResponseMessage> getDefaultDeleteResponseMessages() {\r
+        List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();\r
+        Map<String, Header> defaultHeaders = getDefaultResponseHeaders();\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));\r
+        defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));\r
+        return defaultResponseMessages;\r
+    }\r
 \r
+    private ResponseMessage getResponseBuilder(@NotNull HttpStatus httpStatus, Map<String, Header> defaultHeaders) {\r
+        ResponseMessageBuilder responseMessageBuilder = new ResponseMessageBuilder();\r
+        responseMessageBuilder.code(httpStatus.value())\r
+                .message(httpStatus.getReasonPhrase())\r
+                .headersWithDescription(defaultHeaders)\r
+                .build();\r
+        return responseMessageBuilder.build();\r
+    }\r
+\r
+    private Map<String, Header> getDefaultResponseHeaders() {\r
+        Map<String, Header> defaultHeaders = new HashMap<>();\r
+        defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID,\r
+                new Header(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID, "Transaction Id", new ModelRef("string")));\r
+        defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION,\r
+                new Header(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION, "API Latest Version", new ModelRef("string")));\r
+        defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION,\r
+                new Header(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION, "API Minor Version", new ModelRef("string")));\r
+        defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION,\r
+                new Header(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION, "API Patch Version", new ModelRef("string")));\r
+        return defaultHeaders;\r
+    }\r
 }\r
index 1eba97c..c5cdee6 100644 (file)
@@ -26,6 +26,7 @@ import org.springframework.web.reactive.config.WebFluxConfigurationSupport;
  * @author Brinda Santh 8/13/2018\r
  */\r
 @Configuration\r
+@SuppressWarnings("unused")\r
 public class WebConfig extends WebFluxConfigurationSupport {\r
     public void addResourceHandlers(ResourceHandlerRegistry registry) {\r
         registry.addResourceHandler("swagger-ui.html")\r
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java
new file mode 100644 (file)
index 0000000..9a556e7
--- /dev/null
@@ -0,0 +1,81 @@
+/*\r
+ *  Copyright © 2017-2018 AT&T Intellectual Property.\r
+ *\r
+ *  Licensed under the Apache License, Version 2.0 (the "License");\r
+ *  you may not use this file except in compliance with the License.\r
+ *  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+\r
+package org.onap.ccsdk.apps.controllerblueprints.filters;\r
+\r
+import com.google.common.base.Preconditions;\r
+import org.apache.commons.lang3.StringUtils;\r
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;\r
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.slf4j.MDC;\r
+import org.springframework.beans.factory.annotation.Value;\r
+import org.springframework.stereotype.Component;\r
+\r
+import javax.servlet.*;\r
+import javax.servlet.annotation.WebFilter;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * ApplicationLoggingFilter\r
+ *\r
+ * @author Brinda Santh 8/14/2018\r
+ */\r
+@Component\r
+@WebFilter(asyncSupported = true, urlPatterns = {"/*"})\r
+@SuppressWarnings("unused")\r
+public class ApplicationLoggingFilter implements Filter {\r
+    private static Logger log = LoggerFactory.getLogger(ApplicationLoggingFilter.class);\r
+\r
+    @SuppressWarnings("unused")\r
+    @Value("${appVersion}")\r
+    private String appVersion;\r
+\r
+    public void doFilter(ServletRequest request,\r
+                         ServletResponse response,\r
+                         FilterChain chain) throws IOException, ServletException {\r
+\r
+        HttpServletRequest req = (HttpServletRequest) request;\r
+        HttpServletResponse res = (HttpServletResponse) response;\r
+\r
+        ONAPLogAdapter onapLogAdapter = new ONAPLogAdapter(log);\r
+        onapLogAdapter.entering(req);\r
+\r
+        String[] tokens = StringUtils.split(appVersion, '.');\r
+        Preconditions.checkNotNull(tokens, "failed to split application versions");\r
+        Preconditions.checkArgument(tokens.length == 3, "failed to tokenize application versions");\r
+        res.addHeader(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID, MDC.get("RequestID"));\r
+        res.addHeader(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION, tokens[1]);\r
+        res.addHeader(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION, tokens[2]);\r
+        res.addHeader(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION, appVersion);\r
+        chain.doFilter(request, response);\r
+        // Clean the MDC info\r
+        onapLogAdapter.exiting();\r
+    }\r
+\r
+    @Override\r
+    public void init(FilterConfig filterConfig) {\r
+\r
+    }\r
+\r
+    @Override\r
+    public void destroy() {\r
+\r
+    }\r
+}
\ No newline at end of file
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/CorsFilter.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/CorsFilter.java
new file mode 100644 (file)
index 0000000..91cc731
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ *  Copyright © 2017-2018 AT&T Intellectual Property.\r
+ *\r
+ *  Licensed under the Apache License, Version 2.0 (the "License");\r
+ *  you may not use this file except in compliance with the License.\r
+ *  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+\r
+package org.onap.ccsdk.apps.controllerblueprints.filters;\r
+\r
+import org.springframework.http.HttpMethod;\r
+import org.springframework.stereotype.Component;\r
+import javax.servlet.*;\r
+import javax.servlet.annotation.WebFilter;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import java.io.IOException;\r
+/**\r
+ * CorsFilter.java Purpose: Provide Configuration Generator CorsFilter Information\r
+ *\r
+ * @author Brinda Santh\r
+ */\r
+@Component\r
+@WebFilter(asyncSupported = true, urlPatterns = {"/*"})\r
+@SuppressWarnings("unused")\r
+public class CorsFilter implements Filter {\r
+\r
+    public void destroy() {\r
+    }\r
+\r
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)\r
+            throws IOException, ServletException {\r
+\r
+        HttpServletRequest request = (HttpServletRequest) servletRequest;\r
+        HttpServletResponse response = (HttpServletResponse) servletResponse;\r
+\r
+        response.addHeader("Access-Control-Allow-Origin", "*");\r
+        response.addHeader("Access-Control-Allow-Methods", "*");\r
+        response.addHeader("Access-Control-Allow-Headers",\r
+                "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range");\r
+\r
+        if (request.getMethod().equals(HttpMethod.OPTIONS.toString())) {\r
+            response.addHeader("Access-Control-Max-Age", "1728000");\r
+            response.setStatus(HttpServletResponse.SC_ACCEPTED);\r
+            return;\r
+        }\r
+        chain.doFilter(request, servletResponse);\r
+    }\r
+\r
+    public void init(FilterConfig fConfig) throws ServletException {\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java
new file mode 100644 (file)
index 0000000..9445e1d
--- /dev/null
@@ -0,0 +1,36 @@
+/*\r
+ *  Copyright © 2017-2018 AT&T Intellectual Property.\r
+ *\r
+ *  Licensed under the Apache License, Version 2.0 (the "License");\r
+ *  you may not use this file except in compliance with the License.\r
+ *  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ */\r
+\r
+package org.onap.ccsdk.apps.controllerblueprints;\r
+\r
+import org.apache.commons.lang3.StringUtils;\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+/**\r
+ * VersionSplitTest\r
+ *\r
+ * @author Brinda Santh\r
+ */\r
+public class VersionSplitTest {\r
+\r
+    @Test\r
+    public void testVersionSplit() {\r
+        String version = "1.03.04";\r
+        String[] tokens = StringUtils.split(version, '.');\r
+        Assert.assertNotNull("failed to tokenize", tokens);\r
+        Assert.assertEquals("failed to three token ", 3, tokens.length );\r
+    }\r
+}
\ No newline at end of file
index a147034..a63ed5b 100644 (file)
 # See the License for the specific language governing permissions and\r
 # limitations under the License.\r
 #\r
+appName=ControllerBluePrints\r
+ms_name=org.onap.ccsdk.apps.controllerblueprints\r
+appVersion=1.0.0\r
+\r
+#To Remove Null in JSON API Response\r
 spring.jackson.default-property-inclusion=non_null\r
+\r
+#Swagger Configuration\r
+swagger.contact.name=Brinda Santh Muthuramalingam\r
+swagger.contact.url=www.onap.com\r
+swagger.contact.email=brindasanth@onap.com\r
+\r
 #Load Blueprints\r
 # blueprints.load.initial-data may be overridden by ENV variables\r
 blueprints.load.initial-data=true\r
index 9450f30..493d438 100644 (file)
@@ -26,11 +26,12 @@ services:
        - ~/share/vm_ms/controllerblueprints/config:/opt/app/onap/config\r
        - ~/share/vm_ms/controllerblueprints/logs:/logs\r
      environment:\r
+       APPLICATIONNAME : ControllerBluePrints\r
+       BUNDLEVERSION: 1.0.0\r
+       APP_CONFIG_HOME: /opt/app/onap/config\r
        DB_URL: jdbc:mysql://db:3306/sdnctl\r
        DB_USER: sdnctl\r
        DB_PASSWORD: sdnctl\r
        INIT_DATA_LOAD: "true"\r
-       APP_CONFIG_HOME: /opt/app/onap/config\r
-       BUNDLEVERSION: 1.0.0\r
        STICKYSELECTORKEY:\r
        ENVCONTEXT: DEV
\ No newline at end of file
index 2e3edb6..4ae1f4d 100644 (file)
 \r
 package org.onap.ccsdk.apps.controllerblueprints.core\r
 /**\r
- *\r
+ * BluePrintConstants\r
  *\r
  * @author Brinda Santh\r
  */\r
 object BluePrintConstants {\r
 \r
+    const val RESPONSE_HEADER_TRANSACTION_ID: String = "X-ONAP-RequestID"\r
+    const val RESPONSE_HEADER_MINOR_VERSION: String = "X-MinorVersion"\r
+    const val RESPONSE_HEADER_PATCH_VERSION: String = "X-PatchVersion"\r
+    const val RESPONSE_HEADER_LATEST_VERSION: String = "X-LatestVersion"\r
+\r
     const val TYPE_DEFAULT: String = "default"\r
 \r
     const val DATA_TYPE_STRING: String = "string"\r
index 534394a..a2f653c 100644 (file)
@@ -19,6 +19,7 @@ package org.onap.ccsdk.apps.controllerblueprints.service;
 \r
 import org.apache.commons.collections.CollectionUtils;\r
 import org.apache.commons.lang3.StringUtils;\r
+import org.jetbrains.annotations.NotNull;\r
 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;\r
 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException;\r
 import org.onap.ccsdk.apps.controllerblueprints.core.ConfigModelConstant;\r
@@ -68,6 +69,7 @@ public class ConfigModelService {
         this.configModelRepository = configModelRepository;\r
         this.configModelContentRepository = configModelContentRepository;\r
         this.configModelCreateService = configModelCreateService;\r
+        log.info("Config Model Service Initiated...");\r
     }\r
 \r
     /**\r
@@ -143,8 +145,8 @@ public class ConfigModelService {
      * @param version version\r
      * @return ConfigModel\r
      */\r
-    public ConfigModel getConfigModelByNameAndVersion(String name, String version) {\r
-        ConfigModel configModel = null;\r
+    public ConfigModel getConfigModelByNameAndVersion(@NotNull String name, String version) throws BluePrintException {\r
+        ConfigModel configModel;\r
         Optional<ConfigModel> dbConfigModel;\r
         if (StringUtils.isNotBlank(version)) {\r
             dbConfigModel = configModelRepository.findByArtifactNameAndArtifactVersion(name, version);\r
@@ -153,6 +155,8 @@ public class ConfigModelService {
         }\r
         if (dbConfigModel.isPresent()) {\r
             configModel = dbConfigModel.get();\r
+        } else {\r
+            throw new BluePrintException(String.format("failed to get config model name(%s), version(%s) from repo", name, version));\r
         }\r
         return configModel;\r
     }\r
@@ -162,15 +166,17 @@ public class ConfigModelService {
      *\r
      * @param id id\r
      * @return ConfigModel\r
+     * @throws BluePrintException BluePrintException\r
      */\r
-    public ConfigModel getConfigModel(Long id) {\r
-        ConfigModel configModel = null;\r
-        if (id != null) {\r
-            Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);\r
-            if (dbConfigModel.isPresent()) {\r
-                configModel = dbConfigModel.get();\r
-            }\r
+    public ConfigModel getConfigModel(@NotNull Long id) throws BluePrintException {\r
+        ConfigModel configModel;\r
+        Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);\r
+        if (dbConfigModel.isPresent()) {\r
+            configModel = dbConfigModel.get();\r
+        } else {\r
+            throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));\r
         }\r
+\r
         return configModel;\r
     }\r
 \r
@@ -179,54 +185,56 @@ public class ConfigModelService {
      *\r
      * @param id id\r
      * @return ConfigModel\r
+     * @throws BluePrintException BluePrintException\r
      */\r
 \r
-    public ConfigModel getCloneConfigModel(Long id) {\r
+    public ConfigModel getCloneConfigModel(@NotNull Long id) throws BluePrintException {\r
 \r
         ConfigModel configModel;\r
-        ConfigModel cloneConfigModel = null;\r
-        if (id != null) {\r
-            Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);\r
-            if (dbConfigModel.isPresent()) {\r
-                configModel = dbConfigModel.get();\r
-                cloneConfigModel = configModel;\r
-                cloneConfigModel.setUpdatedBy("xxxxx@xxx.com");\r
-                cloneConfigModel.setArtifactName("XXXX");\r
-                cloneConfigModel.setPublished("XXXX");\r
-                cloneConfigModel.setPublished("XXXX");\r
-                cloneConfigModel.setUpdatedBy("XXXX");\r
-                cloneConfigModel.setId(null);\r
-                cloneConfigModel.setTags(null);\r
-                cloneConfigModel.setCreatedDate(new Date());\r
-                List<ConfigModelContent> configModelContents = cloneConfigModel.getConfigModelContents();\r
-\r
-                if (CollectionUtils.isNotEmpty(configModelContents)) {\r
-                    for (ConfigModelContent configModelContent : configModelContents) {\r
-                        if (configModelContent != null && StringUtils.isNotBlank(configModelContent.getContentType())) {\r
-                            configModelContent.setId(null);\r
-                            configModelContent.setCreationDate(new Date());\r
-\r
-                            if (ConfigModelConstant.MODEL_CONTENT_TYPE_TOSCA_JSON\r
-                                    .equalsIgnoreCase(configModelContent.getContentType())) {\r
-                                ServiceTemplate serviceTemplate = JacksonUtils\r
-                                        .readValue(configModelContent.getContent(), ServiceTemplate.class);\r
-                                if (serviceTemplate != null && serviceTemplate.getMetadata() != null) {\r
-                                    serviceTemplate.getMetadata()\r
-                                            .put(BluePrintConstants.METADATA_TEMPLATE_AUTHOR, "XXXX");\r
-                                    serviceTemplate.getMetadata()\r
-                                            .put(BluePrintConstants.METADATA_TEMPLATE_VERSION, "1.0.0");\r
-                                    serviceTemplate.getMetadata()\r
-                                            .put(BluePrintConstants.METADATA_TEMPLATE_NAME, "XXXXXX");\r
-\r
-                                    configModelContent.setContent(JacksonUtils.getJson(serviceTemplate));\r
-                                }\r
+        ConfigModel cloneConfigModel;\r
+        Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);\r
+        if (dbConfigModel.isPresent()) {\r
+            configModel = dbConfigModel.get();\r
+            cloneConfigModel = configModel;\r
+            cloneConfigModel.setUpdatedBy("xxxxx@xxx.com");\r
+            cloneConfigModel.setArtifactName("XXXX");\r
+            cloneConfigModel.setPublished("XXXX");\r
+            cloneConfigModel.setPublished("XXXX");\r
+            cloneConfigModel.setUpdatedBy("XXXX");\r
+            cloneConfigModel.setId(null);\r
+            cloneConfigModel.setTags(null);\r
+            cloneConfigModel.setCreatedDate(new Date());\r
+            List<ConfigModelContent> configModelContents = cloneConfigModel.getConfigModelContents();\r
+\r
+            if (CollectionUtils.isNotEmpty(configModelContents)) {\r
+                for (ConfigModelContent configModelContent : configModelContents) {\r
+                    if (configModelContent != null && StringUtils.isNotBlank(configModelContent.getContentType())) {\r
+                        configModelContent.setId(null);\r
+                        configModelContent.setCreationDate(new Date());\r
+\r
+                        if (ConfigModelConstant.MODEL_CONTENT_TYPE_TOSCA_JSON\r
+                                .equalsIgnoreCase(configModelContent.getContentType())) {\r
+                            ServiceTemplate serviceTemplate = JacksonUtils\r
+                                    .readValue(configModelContent.getContent(), ServiceTemplate.class);\r
+                            if (serviceTemplate != null && serviceTemplate.getMetadata() != null) {\r
+                                serviceTemplate.getMetadata()\r
+                                        .put(BluePrintConstants.METADATA_TEMPLATE_AUTHOR, "XXXX");\r
+                                serviceTemplate.getMetadata()\r
+                                        .put(BluePrintConstants.METADATA_TEMPLATE_VERSION, "1.0.0");\r
+                                serviceTemplate.getMetadata()\r
+                                        .put(BluePrintConstants.METADATA_TEMPLATE_NAME, "XXXXXX");\r
+\r
+                                configModelContent.setContent(JacksonUtils.getJson(serviceTemplate));\r
                             }\r
                         }\r
-\r
                     }\r
+\r
                 }\r
             }\r
+        } else {\r
+            throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));\r
         }\r
+\r
         return cloneConfigModel;\r
     }\r
 \r
@@ -234,14 +242,17 @@ public class ConfigModelService {
      * This is a deleteConfigModel method\r
      *\r
      * @param id id\r
+     * @throws BluePrintException BluePrintException\r
      */\r
 \r
     @Transactional\r
-    public void deleteConfigModel(Long id) {\r
+    public void deleteConfigModel(@NotNull Long id) throws BluePrintException {\r
         Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);\r
         if (dbConfigModel.isPresent()) {\r
             configModelContentRepository.deleteByConfigModel(dbConfigModel.get());\r
             configModelRepository.delete(dbConfigModel.get());\r
+        } else {\r
+            throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));\r
         }\r
     }\r
 \r
index 62b6830..fc2956b 100644 (file)
@@ -46,81 +46,49 @@ public class ConfigModelRest {
     @GetMapping(path = "/initial/{name}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel getInitialConfigModel(@PathVariable(value = "name") String name) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.getInitialConfigModel(name);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2000, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.getInitialConfigModel(name);\r
     }\r
 \r
-    @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
+    @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel saveConfigModel(@RequestBody ConfigModel configModel) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.saveConfigModel(configModel);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2200, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.saveConfigModel(configModel);\r
     }\r
 \r
     @DeleteMapping(path = "/{id}")\r
     public void deleteConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {\r
-        try {\r
-            this.configModelService.deleteConfigModel(id);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2400, e.getMessage(), e);\r
-        }\r
+        this.configModelService.deleteConfigModel(id);\r
     }\r
 \r
     @GetMapping(path = "/publish/{id}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel publishConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.publishConfigModel(id);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2500, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.publishConfigModel(id);\r
     }\r
 \r
     @GetMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel getConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.getConfigModel(id);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2001, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.getConfigModel(id);\r
     }\r
 \r
     @GetMapping(path = "/by-name/{name}/version/{version}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel getConfigModelByNameAndVersion(@PathVariable(value = "name") String name,\r
                                                @PathVariable(value = "version") String version) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.getConfigModelByNameAndVersion(name, version);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2002, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.getConfigModelByNameAndVersion(name, version);\r
     }\r
 \r
     @GetMapping(path = "/search/{tags}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     List<ConfigModel> searchConfigModels(@PathVariable(value = "tags") String tags) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.searchConfigModels(tags);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2003, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.searchConfigModels(tags);\r
     }\r
 \r
     @GetMapping(path = "/clone/{id}", produces = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ConfigModel getCloneConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {\r
-        try {\r
-            return this.configModelService.getCloneConfigModel(id);\r
-        } catch (Exception e) {\r
-            throw new BluePrintException(2004, e.getMessage(), e);\r
-        }\r
+        return this.configModelService.getCloneConfigModel(id);\r
     }\r
 \r
 }\r
index 6bcbae9..082b150 100644 (file)
@@ -70,7 +70,7 @@ public class ModelTypeRest {
         }\r
     }\r
 \r
-    @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
+    @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ModelType saveModelType(@RequestBody ModelType modelType) throws BluePrintException {\r
         try {\r
index 795738c..a4aced6 100644 (file)
@@ -43,7 +43,7 @@ public class ResourceDictionaryRest {
         this.resourceDictionaryService = dataDictionaryService;\r
     }\r
 \r
-    @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
+    @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)\r
     public @ResponseBody\r
     ResourceDictionary saveResourceDictionary(@RequestBody ResourceDictionary dataDictionary)\r
             throws BluePrintException {\r
index 370533b..8b719f5 100644 (file)
@@ -34,6 +34,7 @@
         <eelf.version>1.0.0</eelf.version>
         <springfox.swagger2.version>2.9.2</springfox.swagger2.version>
         <h2database.version>1.4.197</h2database.version>
+        <onap.logger.slf4j>1.2.2-SNAPSHOT</onap.logger.slf4j>
     </properties>
     <dependencyManagement>
         <dependencies>
                 <artifactId>eelf-core</artifactId>
                 <version>${eelf.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.onap.logging-analytics</groupId>
+                <artifactId>logging-slf4j</artifactId>
+                <version>${onap.logger.slf4j}</version>
+            </dependency>
 
             <!--Swagger Dependencies -->
             <dependency>
             <groupId>com.att.eelf</groupId>
             <artifactId>eelf-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.onap.logging-analytics</groupId>
+            <artifactId>logging-slf4j</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>