diff options
Diffstat (limited to 'ms/controllerblueprints')
20 files changed, 409 insertions, 156 deletions
diff --git a/ms/controllerblueprints/README.md b/ms/controllerblueprints/README.md index 070a5416..4079daf6 100755 --- a/ms/controllerblueprints/README.md +++ b/ms/controllerblueprints/README.md @@ -1,5 +1,8 @@ Application VM Arguments :
+-DappName=ControllerBluePrints
+-Dms_name=org.onap.ccsdk.apps.controllerblueprints
+-DappVersion=1.0.0
-Dlogging.config=etc/logback.xml
-Dspring.config.location=opt/app/onap/config/
-Dspring.datasource.url=jdbc:mysql://127.0.0.1:3306/sdnctl
diff --git a/ms/controllerblueprints/application/etc/logback.xml b/ms/controllerblueprints/application/etc/logback.xml index 44e9a8a1..0a75e60f 100644 --- a/ms/controllerblueprints/application/etc/logback.xml +++ b/ms/controllerblueprints/application/etc/logback.xml @@ -15,11 +15,18 @@ -->
<configuration>
+
+ <property name="localPattern" value="%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n" />
+
+ <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" />
+
+ <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" />
+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
- <pattern>%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n</pattern>
+ <pattern>${defaultPattern}</pattern>
</encoder>
</appender>
diff --git a/ms/controllerblueprints/application/etc/run.source b/ms/controllerblueprints/application/etc/run.source index cba5e1dd..fc1b4e55 100644 --- a/ms/controllerblueprints/application/etc/run.source +++ b/ms/controllerblueprints/application/etc/run.source @@ -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} \ diff --git a/ms/controllerblueprints/application/opt/app/onap/config/application.properties b/ms/controllerblueprints/application/opt/app/onap/config/application.properties index f075b578..3b6033e7 100644 --- a/ms/controllerblueprints/application/opt/app/onap/config/application.properties +++ b/ms/controllerblueprints/application/opt/app/onap/config/application.properties @@ -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 diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java index 0a403b8c..6e9dcd7f 100644 --- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ApplicationExceptionHandler.java @@ -22,6 +22,9 @@ import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException; import org.onap.ccsdk.apps.controllerblueprints.service.common.ErrorMessage;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
@@ -32,17 +35,26 @@ import org.springframework.web.context.request.WebRequest; @SuppressWarnings("unused")
public class ApplicationExceptionHandler {
private static EELFLogger log = EELFManager.getInstance().getLogger(ApplicationExceptionHandler.class);
+
@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorMessage> handleAllExceptions(Exception ex, WebRequest request) {
log.error("Application Exception", ex);
- ErrorMessage exceptionResponse = new ErrorMessage( ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getLocalizedMessage());
+ ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), ex.getLocalizedMessage());
return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
+ @ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentNotValidException.class,
+ HttpRequestMethodNotSupportedException.class})
+ public final ResponseEntity<ErrorMessage> handleBadRequest(Exception ex, WebRequest request) {
+ log.error("Bad Request Exception", ex);
+ ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), HttpStatus.BAD_REQUEST.value(), ex.getLocalizedMessage());
+ return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);
+ }
+
@ExceptionHandler(BluePrintException.class)
public final ResponseEntity<ErrorMessage> handleBlueprintException(BluePrintException ex, WebRequest request) {
log.error("Application Blueprint Exception", ex);
- ErrorMessage exceptionResponse = new ErrorMessage( ex.getMessage(), ex.getCode(), ex.getLocalizedMessage());
+ ErrorMessage exceptionResponse = new ErrorMessage(ex.getMessage(), ex.getCode(), ex.getLocalizedMessage());
return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplication.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplication.java index 447e1966..6b0efd87 100644 --- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplication.java +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/ControllerBluprintsApplication.java @@ -35,7 +35,7 @@ public class ControllerBluprintsApplication { private static EELFLogger log = EELFManager.getInstance().getLogger(ControllerBluprintsApplication.class);
public static void main(String[] args) {
- log.info("****** Starting Controller Bluprints Application **************");
+ log.info("****** Starting Controlled Blueprints Application ******");
SpringApplication.run(ControllerBluprintsApplication.class, args);
}
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 index d00d2c84..00000000 --- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/CorsConfig.java +++ /dev/null @@ -1,55 +0,0 @@ -/*
- * Copyright © 2017-2018 AT&T Intellectual Property.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onap.ccsdk.apps.controllerblueprints;
-
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.reactive.CorsWebFilter;
-import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
-import java.util.Arrays;
-
-/**
- * CorsConfig.java Purpose: Provide Configuration Generator CorsConfig Information
- *
- * @author Brinda Santh
- * @version 1.0
- */
-@Configuration
-public class CorsConfig {
- /**
- * This is a CORS Implementation for different Orgin GUI to access.
- *
- * @return CorsFilter
- */
- @Bean
- CorsWebFilter corsWebFilter() {
- CorsConfiguration corsConfig = new CorsConfiguration();
- corsConfig.setAllowedOrigins(Arrays.asList("*"));
- corsConfig.setMaxAge(8000L);
- corsConfig.addAllowedMethod("*");
-
- UrlBasedCorsConfigurationSource source =
- new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", corsConfig);
-
- return new CorsWebFilter(source);
- }
-
-
-}
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/SwaggerConfig.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/SwaggerConfig.java index 67e3e5d0..cfcccf33 100644 --- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/SwaggerConfig.java +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/SwaggerConfig.java @@ -16,16 +16,30 @@ package org.onap.ccsdk.apps.controllerblueprints;
+import com.google.common.collect.Lists;
+import org.jetbrains.annotations.NotNull;
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.builders.ResponseMessageBuilder;
+import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
+import springfox.documentation.service.Header;
+import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* SwaggerConfig
@@ -36,10 +50,23 @@ import java.util.Collections; @EnableSwagger2
@SuppressWarnings("unused")
public class SwaggerConfig {
+ @Value("${appVersion}")
+ private String appVersion;
+ @Value("${swagger.contact.name}")
+ private String contactName;
+ @Value("${swagger.contact.url}")
+ private String contactUrl;
+ @Value("${swagger.contact.email}")
+ private String contactEmail;
+
@Bean
@SuppressWarnings("unused")
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
+ .globalResponseMessage(RequestMethod.GET, getDefaultGetResponseMessages())
+ .globalResponseMessage(RequestMethod.POST, getDefaultPostResponseMessages())
+ .globalResponseMessage(RequestMethod.PUT, getDefaultPutResponseMessages())
+ .globalResponseMessage(RequestMethod.DELETE, getDefaultDeleteResponseMessages())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
@@ -51,11 +78,77 @@ public class SwaggerConfig { return new ApiInfo(
"Controller Blueprints API",
"Controller blueprints API for VNF Self Service.",
- "1.0.0",
+ appVersion,
"Terms of service",
- new Contact("Brinda Santh", "www.onap.com", "brindasanth@onap.com"),
+ new Contact(contactName, contactUrl, contactEmail),
"Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", Collections.emptyList());
}
+ private List<ResponseMessage> getDefaultGetResponseMessages() {
+ List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();
+ Map<String, Header> defaultHeaders = getDefaultResponseHeaders();
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.NOT_FOUND, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));
+ return defaultResponseMessages;
+ }
+
+ private List<ResponseMessage> getDefaultPostResponseMessages() {
+ List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();
+ Map<String, Header> defaultHeaders = getDefaultResponseHeaders();
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.CREATED, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));
+ return defaultResponseMessages;
+ }
+
+ private List<ResponseMessage> getDefaultPutResponseMessages() {
+ List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();
+ Map<String, Header> defaultHeaders = getDefaultResponseHeaders();
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));
+ return defaultResponseMessages;
+ }
+
+ private List<ResponseMessage> getDefaultDeleteResponseMessages() {
+ List<ResponseMessage> defaultResponseMessages = Lists.newArrayList();
+ Map<String, Header> defaultHeaders = getDefaultResponseHeaders();
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.OK, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.BAD_REQUEST, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.UNAUTHORIZED, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.FORBIDDEN, defaultHeaders));
+ defaultResponseMessages.add(getResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, defaultHeaders));
+ return defaultResponseMessages;
+ }
+ private ResponseMessage getResponseBuilder(@NotNull HttpStatus httpStatus, Map<String, Header> defaultHeaders) {
+ ResponseMessageBuilder responseMessageBuilder = new ResponseMessageBuilder();
+ responseMessageBuilder.code(httpStatus.value())
+ .message(httpStatus.getReasonPhrase())
+ .headersWithDescription(defaultHeaders)
+ .build();
+ return responseMessageBuilder.build();
+ }
+
+ private Map<String, Header> getDefaultResponseHeaders() {
+ Map<String, Header> defaultHeaders = new HashMap<>();
+ defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID,
+ new Header(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID, "Transaction Id", new ModelRef("string")));
+ defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION,
+ new Header(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION, "API Latest Version", new ModelRef("string")));
+ defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION,
+ new Header(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION, "API Minor Version", new ModelRef("string")));
+ defaultHeaders.put(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION,
+ new Header(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION, "API Patch Version", new ModelRef("string")));
+ return defaultHeaders;
+ }
}
diff --git a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/WebConfig.java b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/WebConfig.java index 1eba97cd..c5cdee62 100644 --- a/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/WebConfig.java +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/WebConfig.java @@ -26,6 +26,7 @@ import org.springframework.web.reactive.config.WebFluxConfigurationSupport; * @author Brinda Santh 8/13/2018
*/
@Configuration
+@SuppressWarnings("unused")
public class WebConfig extends WebFluxConfigurationSupport {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
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 index 00000000..9a556e71 --- /dev/null +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/ApplicationLoggingFilter.java @@ -0,0 +1,81 @@ +/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.controllerblueprints.filters;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * ApplicationLoggingFilter
+ *
+ * @author Brinda Santh 8/14/2018
+ */
+@Component
+@WebFilter(asyncSupported = true, urlPatterns = {"/*"})
+@SuppressWarnings("unused")
+public class ApplicationLoggingFilter implements Filter {
+ private static Logger log = LoggerFactory.getLogger(ApplicationLoggingFilter.class);
+
+ @SuppressWarnings("unused")
+ @Value("${appVersion}")
+ private String appVersion;
+
+ public void doFilter(ServletRequest request,
+ ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ HttpServletRequest req = (HttpServletRequest) request;
+ HttpServletResponse res = (HttpServletResponse) response;
+
+ ONAPLogAdapter onapLogAdapter = new ONAPLogAdapter(log);
+ onapLogAdapter.entering(req);
+
+ String[] tokens = StringUtils.split(appVersion, '.');
+ Preconditions.checkNotNull(tokens, "failed to split application versions");
+ Preconditions.checkArgument(tokens.length == 3, "failed to tokenize application versions");
+ res.addHeader(BluePrintConstants.RESPONSE_HEADER_TRANSACTION_ID, MDC.get("RequestID"));
+ res.addHeader(BluePrintConstants.RESPONSE_HEADER_MINOR_VERSION, tokens[1]);
+ res.addHeader(BluePrintConstants.RESPONSE_HEADER_PATCH_VERSION, tokens[2]);
+ res.addHeader(BluePrintConstants.RESPONSE_HEADER_LATEST_VERSION, appVersion);
+ chain.doFilter(request, response);
+ // Clean the MDC info
+ onapLogAdapter.exiting();
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) {
+
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
\ 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 index 00000000..91cc731d --- /dev/null +++ b/ms/controllerblueprints/application/src/main/java/org/onap/ccsdk/apps/controllerblueprints/filters/CorsFilter.java @@ -0,0 +1,61 @@ +/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.controllerblueprints.filters;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.stereotype.Component;
+import javax.servlet.*;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+/**
+ * CorsFilter.java Purpose: Provide Configuration Generator CorsFilter Information
+ *
+ * @author Brinda Santh
+ */
+@Component
+@WebFilter(asyncSupported = true, urlPatterns = {"/*"})
+@SuppressWarnings("unused")
+public class CorsFilter implements Filter {
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
+ throws IOException, ServletException {
+
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Allow-Methods", "*");
+ response.addHeader("Access-Control-Allow-Headers",
+ "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range");
+
+ if (request.getMethod().equals(HttpMethod.OPTIONS.toString())) {
+ response.addHeader("Access-Control-Max-Age", "1728000");
+ response.setStatus(HttpServletResponse.SC_ACCEPTED);
+ return;
+ }
+ chain.doFilter(request, servletResponse);
+ }
+
+ public void init(FilterConfig fConfig) throws ServletException {
+ }
+
+}
\ 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 index 00000000..9445e1d3 --- /dev/null +++ b/ms/controllerblueprints/application/src/test/java/org/onap/ccsdk/apps/controllerblueprints/VersionSplitTest.java @@ -0,0 +1,36 @@ +/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.ccsdk.apps.controllerblueprints;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+/**
+ * VersionSplitTest
+ *
+ * @author Brinda Santh
+ */
+public class VersionSplitTest {
+
+ @Test
+ public void testVersionSplit() {
+ String version = "1.03.04";
+ String[] tokens = StringUtils.split(version, '.');
+ Assert.assertNotNull("failed to tokenize", tokens);
+ Assert.assertEquals("failed to three token ", 3, tokens.length );
+ }
+}
\ No newline at end of file diff --git a/ms/controllerblueprints/application/src/test/resources/application.properties b/ms/controllerblueprints/application/src/test/resources/application.properties index a147034f..a63ed5b7 100644 --- a/ms/controllerblueprints/application/src/test/resources/application.properties +++ b/ms/controllerblueprints/application/src/test/resources/application.properties @@ -13,7 +13,18 @@ # 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
+
+#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
+
#Load Blueprints
# blueprints.load.initial-data may be overridden by ENV variables
blueprints.load.initial-data=true
diff --git a/ms/controllerblueprints/distribution/src/main/dc/docker-compose.yaml b/ms/controllerblueprints/distribution/src/main/dc/docker-compose.yaml index 9450f306..493d4381 100644 --- a/ms/controllerblueprints/distribution/src/main/dc/docker-compose.yaml +++ b/ms/controllerblueprints/distribution/src/main/dc/docker-compose.yaml @@ -26,11 +26,12 @@ services: - ~/share/vm_ms/controllerblueprints/config:/opt/app/onap/config
- ~/share/vm_ms/controllerblueprints/logs:/logs
environment:
+ APPLICATIONNAME : ControllerBluePrints
+ BUNDLEVERSION: 1.0.0
+ APP_CONFIG_HOME: /opt/app/onap/config
DB_URL: jdbc:mysql://db:3306/sdnctl
DB_USER: sdnctl
DB_PASSWORD: sdnctl
INIT_DATA_LOAD: "true"
- APP_CONFIG_HOME: /opt/app/onap/config
- BUNDLEVERSION: 1.0.0
STICKYSELECTORKEY:
ENVCONTEXT: DEV
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintConstants.kt b/ms/controllerblueprints/modules/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintConstants.kt index 2e3edb65..4ae1f4d5 100644 --- a/ms/controllerblueprints/modules/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintConstants.kt +++ b/ms/controllerblueprints/modules/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/BluePrintConstants.kt @@ -17,12 +17,17 @@ package org.onap.ccsdk.apps.controllerblueprints.core
/**
- *
+ * BluePrintConstants
*
* @author Brinda Santh
*/
object BluePrintConstants {
+ const val RESPONSE_HEADER_TRANSACTION_ID: String = "X-ONAP-RequestID"
+ const val RESPONSE_HEADER_MINOR_VERSION: String = "X-MinorVersion"
+ const val RESPONSE_HEADER_PATCH_VERSION: String = "X-PatchVersion"
+ const val RESPONSE_HEADER_LATEST_VERSION: String = "X-LatestVersion"
+
const val TYPE_DEFAULT: String = "default"
const val DATA_TYPE_STRING: String = "string"
diff --git a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/ConfigModelService.java b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/ConfigModelService.java index 534394a3..a2f653c6 100644 --- a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/ConfigModelService.java +++ b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/ConfigModelService.java @@ -19,6 +19,7 @@ package org.onap.ccsdk.apps.controllerblueprints.service; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants;
import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException;
import org.onap.ccsdk.apps.controllerblueprints.core.ConfigModelConstant;
@@ -68,6 +69,7 @@ public class ConfigModelService { this.configModelRepository = configModelRepository;
this.configModelContentRepository = configModelContentRepository;
this.configModelCreateService = configModelCreateService;
+ log.info("Config Model Service Initiated...");
}
/**
@@ -143,8 +145,8 @@ public class ConfigModelService { * @param version version
* @return ConfigModel
*/
- public ConfigModel getConfigModelByNameAndVersion(String name, String version) {
- ConfigModel configModel = null;
+ public ConfigModel getConfigModelByNameAndVersion(@NotNull String name, String version) throws BluePrintException {
+ ConfigModel configModel;
Optional<ConfigModel> dbConfigModel;
if (StringUtils.isNotBlank(version)) {
dbConfigModel = configModelRepository.findByArtifactNameAndArtifactVersion(name, version);
@@ -153,6 +155,8 @@ public class ConfigModelService { }
if (dbConfigModel.isPresent()) {
configModel = dbConfigModel.get();
+ } else {
+ throw new BluePrintException(String.format("failed to get config model name(%s), version(%s) from repo", name, version));
}
return configModel;
}
@@ -162,15 +166,17 @@ public class ConfigModelService { *
* @param id id
* @return ConfigModel
+ * @throws BluePrintException BluePrintException
*/
- public ConfigModel getConfigModel(Long id) {
- ConfigModel configModel = null;
- if (id != null) {
- Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);
- if (dbConfigModel.isPresent()) {
- configModel = dbConfigModel.get();
- }
+ public ConfigModel getConfigModel(@NotNull Long id) throws BluePrintException {
+ ConfigModel configModel;
+ Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);
+ if (dbConfigModel.isPresent()) {
+ configModel = dbConfigModel.get();
+ } else {
+ throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));
}
+
return configModel;
}
@@ -179,54 +185,56 @@ public class ConfigModelService { *
* @param id id
* @return ConfigModel
+ * @throws BluePrintException BluePrintException
*/
- public ConfigModel getCloneConfigModel(Long id) {
+ public ConfigModel getCloneConfigModel(@NotNull Long id) throws BluePrintException {
ConfigModel configModel;
- ConfigModel cloneConfigModel = null;
- if (id != null) {
- Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);
- if (dbConfigModel.isPresent()) {
- configModel = dbConfigModel.get();
- cloneConfigModel = configModel;
- cloneConfigModel.setUpdatedBy("xxxxx@xxx.com");
- cloneConfigModel.setArtifactName("XXXX");
- cloneConfigModel.setPublished("XXXX");
- cloneConfigModel.setPublished("XXXX");
- cloneConfigModel.setUpdatedBy("XXXX");
- cloneConfigModel.setId(null);
- cloneConfigModel.setTags(null);
- cloneConfigModel.setCreatedDate(new Date());
- List<ConfigModelContent> configModelContents = cloneConfigModel.getConfigModelContents();
-
- if (CollectionUtils.isNotEmpty(configModelContents)) {
- for (ConfigModelContent configModelContent : configModelContents) {
- if (configModelContent != null && StringUtils.isNotBlank(configModelContent.getContentType())) {
- configModelContent.setId(null);
- configModelContent.setCreationDate(new Date());
-
- if (ConfigModelConstant.MODEL_CONTENT_TYPE_TOSCA_JSON
- .equalsIgnoreCase(configModelContent.getContentType())) {
- ServiceTemplate serviceTemplate = JacksonUtils
- .readValue(configModelContent.getContent(), ServiceTemplate.class);
- if (serviceTemplate != null && serviceTemplate.getMetadata() != null) {
- serviceTemplate.getMetadata()
- .put(BluePrintConstants.METADATA_TEMPLATE_AUTHOR, "XXXX");
- serviceTemplate.getMetadata()
- .put(BluePrintConstants.METADATA_TEMPLATE_VERSION, "1.0.0");
- serviceTemplate.getMetadata()
- .put(BluePrintConstants.METADATA_TEMPLATE_NAME, "XXXXXX");
-
- configModelContent.setContent(JacksonUtils.getJson(serviceTemplate));
- }
+ ConfigModel cloneConfigModel;
+ Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);
+ if (dbConfigModel.isPresent()) {
+ configModel = dbConfigModel.get();
+ cloneConfigModel = configModel;
+ cloneConfigModel.setUpdatedBy("xxxxx@xxx.com");
+ cloneConfigModel.setArtifactName("XXXX");
+ cloneConfigModel.setPublished("XXXX");
+ cloneConfigModel.setPublished("XXXX");
+ cloneConfigModel.setUpdatedBy("XXXX");
+ cloneConfigModel.setId(null);
+ cloneConfigModel.setTags(null);
+ cloneConfigModel.setCreatedDate(new Date());
+ List<ConfigModelContent> configModelContents = cloneConfigModel.getConfigModelContents();
+
+ if (CollectionUtils.isNotEmpty(configModelContents)) {
+ for (ConfigModelContent configModelContent : configModelContents) {
+ if (configModelContent != null && StringUtils.isNotBlank(configModelContent.getContentType())) {
+ configModelContent.setId(null);
+ configModelContent.setCreationDate(new Date());
+
+ if (ConfigModelConstant.MODEL_CONTENT_TYPE_TOSCA_JSON
+ .equalsIgnoreCase(configModelContent.getContentType())) {
+ ServiceTemplate serviceTemplate = JacksonUtils
+ .readValue(configModelContent.getContent(), ServiceTemplate.class);
+ if (serviceTemplate != null && serviceTemplate.getMetadata() != null) {
+ serviceTemplate.getMetadata()
+ .put(BluePrintConstants.METADATA_TEMPLATE_AUTHOR, "XXXX");
+ serviceTemplate.getMetadata()
+ .put(BluePrintConstants.METADATA_TEMPLATE_VERSION, "1.0.0");
+ serviceTemplate.getMetadata()
+ .put(BluePrintConstants.METADATA_TEMPLATE_NAME, "XXXXXX");
+
+ configModelContent.setContent(JacksonUtils.getJson(serviceTemplate));
}
}
-
}
+
}
}
+ } else {
+ throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));
}
+
return cloneConfigModel;
}
@@ -234,14 +242,17 @@ public class ConfigModelService { * This is a deleteConfigModel method
*
* @param id id
+ * @throws BluePrintException BluePrintException
*/
@Transactional
- public void deleteConfigModel(Long id) {
+ public void deleteConfigModel(@NotNull Long id) throws BluePrintException {
Optional<ConfigModel> dbConfigModel = configModelRepository.findById(id);
if (dbConfigModel.isPresent()) {
configModelContentRepository.deleteByConfigModel(dbConfigModel.get());
configModelRepository.delete(dbConfigModel.get());
+ } else {
+ throw new BluePrintException(String.format("failed to get config model id(%d) from repo", id));
}
}
diff --git a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ConfigModelRest.java b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ConfigModelRest.java index 62b68303..fc2956be 100644 --- a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ConfigModelRest.java +++ b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ConfigModelRest.java @@ -46,81 +46,49 @@ public class ConfigModelRest { @GetMapping(path = "/initial/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel getInitialConfigModel(@PathVariable(value = "name") String name) throws BluePrintException {
- try {
- return this.configModelService.getInitialConfigModel(name);
- } catch (Exception e) {
- throw new BluePrintException(2000, e.getMessage(), e);
- }
+ return this.configModelService.getInitialConfigModel(name);
}
- @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel saveConfigModel(@RequestBody ConfigModel configModel) throws BluePrintException {
- try {
- return this.configModelService.saveConfigModel(configModel);
- } catch (Exception e) {
- throw new BluePrintException(2200, e.getMessage(), e);
- }
+ return this.configModelService.saveConfigModel(configModel);
}
@DeleteMapping(path = "/{id}")
public void deleteConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {
- try {
- this.configModelService.deleteConfigModel(id);
- } catch (Exception e) {
- throw new BluePrintException(2400, e.getMessage(), e);
- }
+ this.configModelService.deleteConfigModel(id);
}
@GetMapping(path = "/publish/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel publishConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {
- try {
- return this.configModelService.publishConfigModel(id);
- } catch (Exception e) {
- throw new BluePrintException(2500, e.getMessage(), e);
- }
+ return this.configModelService.publishConfigModel(id);
}
@GetMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel getConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {
- try {
- return this.configModelService.getConfigModel(id);
- } catch (Exception e) {
- throw new BluePrintException(2001, e.getMessage(), e);
- }
+ return this.configModelService.getConfigModel(id);
}
@GetMapping(path = "/by-name/{name}/version/{version}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel getConfigModelByNameAndVersion(@PathVariable(value = "name") String name,
@PathVariable(value = "version") String version) throws BluePrintException {
- try {
- return this.configModelService.getConfigModelByNameAndVersion(name, version);
- } catch (Exception e) {
- throw new BluePrintException(2002, e.getMessage(), e);
- }
+ return this.configModelService.getConfigModelByNameAndVersion(name, version);
}
@GetMapping(path = "/search/{tags}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
List<ConfigModel> searchConfigModels(@PathVariable(value = "tags") String tags) throws BluePrintException {
- try {
- return this.configModelService.searchConfigModels(tags);
- } catch (Exception e) {
- throw new BluePrintException(2003, e.getMessage(), e);
- }
+ return this.configModelService.searchConfigModels(tags);
}
@GetMapping(path = "/clone/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ConfigModel getCloneConfigModel(@PathVariable(value = "id") Long id) throws BluePrintException {
- try {
- return this.configModelService.getCloneConfigModel(id);
- } catch (Exception e) {
- throw new BluePrintException(2004, e.getMessage(), e);
- }
+ return this.configModelService.getCloneConfigModel(id);
}
}
diff --git a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ModelTypeRest.java b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ModelTypeRest.java index 6bcbae96..082b1507 100644 --- a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ModelTypeRest.java +++ b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ModelTypeRest.java @@ -70,7 +70,7 @@ public class ModelTypeRest { }
}
- @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ModelType saveModelType(@RequestBody ModelType modelType) throws BluePrintException {
try {
diff --git a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ResourceDictionaryRest.java b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ResourceDictionaryRest.java index 795738cb..a4aced60 100644 --- a/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ResourceDictionaryRest.java +++ b/ms/controllerblueprints/modules/service/src/main/java/org/onap/ccsdk/apps/controllerblueprints/service/rs/ResourceDictionaryRest.java @@ -43,7 +43,7 @@ public class ResourceDictionaryRest { this.resourceDictionaryService = dataDictionaryService;
}
- @PostMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ResourceDictionary saveResourceDictionary(@RequestBody ResourceDictionary dataDictionary)
throws BluePrintException {
diff --git a/ms/controllerblueprints/parent/pom.xml b/ms/controllerblueprints/parent/pom.xml index 370533b7..8b719f57 100644 --- a/ms/controllerblueprints/parent/pom.xml +++ b/ms/controllerblueprints/parent/pom.xml @@ -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> @@ -51,6 +52,11 @@ <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> @@ -160,6 +166,10 @@ <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> </dependency> |