From 314bba3a72c1b1122668950005a2e754f8c5c5cc Mon Sep 17 00:00:00 2001 From: "waqas.ikram" Date: Fri, 22 Mar 2019 14:39:44 +0000 Subject: Created new BB for so-etsi Change-Id: I9bf6b4019c280b816925ee5e0d826bff69cb1583 Issue-ID: SO-1621 Signed-off-by: waqas.ikram --- .../org/onap/so/client/RestTemplateConfig.java | 34 ++- .../rest/BasicHttpHeadersProvider.java | 54 +++++ .../rest/HttpClientConnectionConfiguration.java | 87 +++++++ .../rest/HttpComponentsClientConfiguration.java | 73 ++++++ .../so/configuration/rest/HttpHeadersProvider.java | 35 +++ .../logging/jaxrs/filter/SpringClientFilter.java | 2 +- .../exceptions/InvalidRestRequestException.java | 37 +++ .../rest/exceptions/RestProcessingException.java | 37 +++ .../so/rest/service/HttpRestServiceProvider.java | 72 ++++++ .../rest/service/HttpRestServiceProviderImpl.java | 144 ++++++++++++ .../rest/BasicHttpHeadersProviderTest.java | 58 +++++ .../HttpComponentsClientConfigurationTest.java | 45 ++++ .../service/HttpRestServiceProviderImplTest.java | 252 +++++++++++++++++++++ 13 files changed, 922 insertions(+), 8 deletions(-) create mode 100644 common/src/main/java/org/onap/so/configuration/rest/BasicHttpHeadersProvider.java create mode 100644 common/src/main/java/org/onap/so/configuration/rest/HttpClientConnectionConfiguration.java create mode 100644 common/src/main/java/org/onap/so/configuration/rest/HttpComponentsClientConfiguration.java create mode 100644 common/src/main/java/org/onap/so/configuration/rest/HttpHeadersProvider.java create mode 100644 common/src/main/java/org/onap/so/rest/exceptions/InvalidRestRequestException.java create mode 100644 common/src/main/java/org/onap/so/rest/exceptions/RestProcessingException.java create mode 100644 common/src/main/java/org/onap/so/rest/service/HttpRestServiceProvider.java create mode 100644 common/src/main/java/org/onap/so/rest/service/HttpRestServiceProviderImpl.java create mode 100644 common/src/test/java/org/onap/so/configuration/rest/BasicHttpHeadersProviderTest.java create mode 100644 common/src/test/java/org/onap/so/configuration/rest/HttpComponentsClientConfigurationTest.java create mode 100644 common/src/test/java/org/onap/so/rest/service/HttpRestServiceProviderImplTest.java (limited to 'common') diff --git a/common/src/main/java/org/onap/so/client/RestTemplateConfig.java b/common/src/main/java/org/onap/so/client/RestTemplateConfig.java index 14556f1211..34ad6ef758 100644 --- a/common/src/main/java/org/onap/so/client/RestTemplateConfig.java +++ b/common/src/main/java/org/onap/so/client/RestTemplateConfig.java @@ -20,7 +20,10 @@ package org.onap.so.client; +import org.onap.so.configuration.rest.HttpComponentsClientConfiguration; import org.onap.so.logging.jaxrs.filter.SpringClientFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.BufferingClientHttpRequestFactory; @@ -30,11 +33,28 @@ import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { - @Bean - public RestTemplate restTemplate() { - RestTemplate restTemplate = new RestTemplate(); - restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory())); - restTemplate.getInterceptors().add(new SpringClientFilter()); - return restTemplate; - } + public static final String CONFIGURABLE_REST_TEMPLATE = "configurableRestTemplate"; + + @Autowired + private HttpComponentsClientConfiguration httpComponentsClientConfiguration; + + @Bean + public RestTemplate restTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate + .setRequestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory())); + restTemplate.getInterceptors().add(new SpringClientFilter()); + return restTemplate; + } + + @Bean + @Qualifier(CONFIGURABLE_REST_TEMPLATE) + public RestTemplate configurableRestTemplate() { + final HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = + httpComponentsClientConfiguration.httpComponentsClientHttpRequestFactory(); + final RestTemplate restTemplate = + new RestTemplate(new BufferingClientHttpRequestFactory(clientHttpRequestFactory)); + restTemplate.getInterceptors().add(new SpringClientFilter()); + return restTemplate; + } } diff --git a/common/src/main/java/org/onap/so/configuration/rest/BasicHttpHeadersProvider.java b/common/src/main/java/org/onap/so/configuration/rest/BasicHttpHeadersProvider.java new file mode 100644 index 0000000000..7606f3a8d3 --- /dev/null +++ b/common/src/main/java/org/onap/so/configuration/rest/BasicHttpHeadersProvider.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +/** + * @author waqas.ikram@est.tech + */ +public class BasicHttpHeadersProvider implements HttpHeadersProvider { + + public static final String AUTHORIZATION_HEADER = "Authorization"; + + private final HttpHeaders headers = new HttpHeaders(); + + public BasicHttpHeadersProvider(final String authorization) { + headers.add(AUTHORIZATION_HEADER, authorization); + headers.setContentType(MediaType.APPLICATION_JSON); + } + + public BasicHttpHeadersProvider() { + headers.setContentType(MediaType.APPLICATION_JSON); + } + + @Override + public HttpHeaders getHttpHeaders() { + return headers; + } + + @Override + public String toString() { + return "BasicHttpHeadersProvider [headers=" + headers + "]"; + } + +} diff --git a/common/src/main/java/org/onap/so/configuration/rest/HttpClientConnectionConfiguration.java b/common/src/main/java/org/onap/so/configuration/rest/HttpClientConnectionConfiguration.java new file mode 100644 index 0000000000..a5a4cb7d53 --- /dev/null +++ b/common/src/main/java/org/onap/so/configuration/rest/HttpClientConnectionConfiguration.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * This class is used configure the parameters needed for + * {@link org.apache.http.impl.client.CloseableHttpClient} + * + * @author waqas.ikram@est.tech + */ +@Service +public class HttpClientConnectionConfiguration { + + @Value(value = "${rest.http.client.configuration.connTimeOutInSec:10}") + private int connectionTimeOutInSeconds; + + @Value(value = "${rest.http.client.configuration.socketTimeOutInSec:180}") + private int socketTimeOutInSeconds; + + @Value(value = "${rest.http.client.configuration.socketTimeOutInSec:600}") + private int timeToLiveInSeconds; + + @Value(value = "${rest.http.client.configuration.maxConnections:10}") + private int maxConnections; + + @Value(value = "${rest.http.client.configuration.maxConnectionsPerRoute:2}") + private int maxConnectionsPerRoute; + + /** + * @return the socket connection time out in milliseconds + */ + public int getSocketTimeOutInMiliSeconds() { + return (int) TimeUnit.SECONDS.toMillis(socketTimeOutInSeconds); + } + + /** + * @return the maximum total connection value. + */ + public int getMaxConnections() { + return maxConnections; + } + + /** + * @return the maximum connection per route value. + */ + public int getMaxConnectionsPerRoute() { + return maxConnectionsPerRoute; + } + + /** + * @return the connect time out value in milliseconds. + */ + public int getConnectionTimeOutInMilliSeconds() { + return (int) TimeUnit.SECONDS.toMillis(connectionTimeOutInSeconds); + } + + /** + * @return the connection time to live value in mintues. + */ + public int getTimeToLiveInMins() { + return (int) TimeUnit.SECONDS.toMinutes(timeToLiveInSeconds); + } + +} diff --git a/common/src/main/java/org/onap/so/configuration/rest/HttpComponentsClientConfiguration.java b/common/src/main/java/org/onap/so/configuration/rest/HttpComponentsClientConfiguration.java new file mode 100644 index 0000000000..e943aef159 --- /dev/null +++ b/common/src/main/java/org/onap/so/configuration/rest/HttpComponentsClientConfiguration.java @@ -0,0 +1,73 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2018 Ericsson. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import java.util.concurrent.TimeUnit; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +/** + * Allow user to configure {@link org.apache.http.client.HttpClient} + * + * @author waqas.ikram@est.tech + */ +@Configuration +public class HttpComponentsClientConfiguration { + + private final HttpClientConnectionConfiguration clientConnectionConfiguration; + + @Autowired + public HttpComponentsClientConfiguration(final HttpClientConnectionConfiguration clientConnectionConfiguration) { + this.clientConnectionConfiguration = clientConnectionConfiguration; + } + + @Bean + public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() { + return new HttpComponentsClientHttpRequestFactory(httpClient()); + } + + @Bean + public CloseableHttpClient httpClient() { + return HttpClientBuilder.create().setConnectionManager(poolingHttpClientConnectionManager()) + .setMaxConnPerRoute(clientConnectionConfiguration.getMaxConnectionsPerRoute()) + .setMaxConnTotal(clientConnectionConfiguration.getMaxConnections()) + .setDefaultRequestConfig(requestConfig()).build(); + } + + @Bean + public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() { + return new PoolingHttpClientConnectionManager(clientConnectionConfiguration.getTimeToLiveInMins(), + TimeUnit.MINUTES); + } + + @Bean + public RequestConfig requestConfig() { + return RequestConfig.custom().setSocketTimeout(clientConnectionConfiguration.getSocketTimeOutInMiliSeconds()) + .setConnectTimeout(clientConnectionConfiguration.getConnectionTimeOutInMilliSeconds()).build(); + } +} diff --git a/common/src/main/java/org/onap/so/configuration/rest/HttpHeadersProvider.java b/common/src/main/java/org/onap/so/configuration/rest/HttpHeadersProvider.java new file mode 100644 index 0000000000..0cff7b4ba0 --- /dev/null +++ b/common/src/main/java/org/onap/so/configuration/rest/HttpHeadersProvider.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import org.springframework.http.HttpHeaders; + +/** + * Providers {@link org.springframework.http.HttpHeaders} for HTTP requests + * + * @author waqas.ikram@est.tech + * + */ +public interface HttpHeadersProvider { + + HttpHeaders getHttpHeaders(); + +} diff --git a/common/src/main/java/org/onap/so/logging/jaxrs/filter/SpringClientFilter.java b/common/src/main/java/org/onap/so/logging/jaxrs/filter/SpringClientFilter.java index cecef1945b..ed63a706a2 100644 --- a/common/src/main/java/org/onap/so/logging/jaxrs/filter/SpringClientFilter.java +++ b/common/src/main/java/org/onap/so/logging/jaxrs/filter/SpringClientFilter.java @@ -57,6 +57,7 @@ public class SpringClientFilter implements ClientHttpRequestInterceptor { } private void processRequest(HttpRequest request, byte[] body) throws IOException { + setInvocationId(); setupHeaders(request); setupMDC(request); if (log.isDebugEnabled()) { @@ -89,7 +90,6 @@ public class SpringClientFilter implements ClientHttpRequestInterceptor { MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, clientRequest.getURI().toString()); MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString()); - setInvocationId(); MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY,extractTargetEntity(clientRequest)); } diff --git a/common/src/main/java/org/onap/so/rest/exceptions/InvalidRestRequestException.java b/common/src/main/java/org/onap/so/rest/exceptions/InvalidRestRequestException.java new file mode 100644 index 0000000000..2a9799315e --- /dev/null +++ b/common/src/main/java/org/onap/so/rest/exceptions/InvalidRestRequestException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.rest.exceptions; + +/** + * @author waqas.ikram@est.tech + * + */ +public class InvalidRestRequestException extends RuntimeException { + private static final long serialVersionUID = -1158414939006977465L; + + public InvalidRestRequestException(final String message) { + super(message); + } + + public InvalidRestRequestException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/org/onap/so/rest/exceptions/RestProcessingException.java b/common/src/main/java/org/onap/so/rest/exceptions/RestProcessingException.java new file mode 100644 index 0000000000..e8ce00c7e5 --- /dev/null +++ b/common/src/main/java/org/onap/so/rest/exceptions/RestProcessingException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.rest.exceptions; + +/** + * @author waqas.ikram@est.tech + * + */ +public class RestProcessingException extends RuntimeException { + + private static final long serialVersionUID = 16862313537198441L; + + public RestProcessingException(final String message) { + super(message); + } + + public RestProcessingException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProvider.java b/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProvider.java new file mode 100644 index 0000000000..43b2fb4292 --- /dev/null +++ b/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProvider.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.rest.service; + +import org.springframework.http.ResponseEntity; + +import com.google.common.base.Optional; + +/** + * @author waqas.ikram@est.tech + */ +public interface HttpRestServiceProvider { + + /** + * Execute the HTTP GET to the given URI template + * + * @param url the URL + * @param clazz the type of the return value + * @return Returns the body of this entity. + */ + public Optional get(final String url, final Class clazz); + + /** + * Execute the HTTP GET to the given URI template + * + * @param url the URL + * @param clazz the type of the return value + * @return Returns the {@link ResponseEntity}. + */ + public ResponseEntity getHttpResponse(final String url, final Class clazz); + + + /** + * Execute the HTTP POST to the given URI template + * + * @param object the entity (i.e. body) to write to the request + * @param url the URL + * @param clazz the type of the return value + * @return Returns the body of this entity. + */ + public Optional post(final Object object, final String url, final Class clazz); + + /** + * Execute the HTTP POST to the given URI template + * + * @param object the entity (i.e. body) to write to the request + * @param url the URL + * @param clazz the type of the return value + * @return Returns the {@link ResponseEntity}. + */ + public ResponseEntity postHttpRequest(final Object object, final String url, final Class clazz); + + +} diff --git a/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProviderImpl.java b/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProviderImpl.java new file mode 100644 index 0000000000..032df84a98 --- /dev/null +++ b/common/src/main/java/org/onap/so/rest/service/HttpRestServiceProviderImpl.java @@ -0,0 +1,144 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.rest.service; + +import org.onap.so.configuration.rest.BasicHttpHeadersProvider; +import org.onap.so.configuration.rest.HttpHeadersProvider; +import org.onap.so.rest.exceptions.InvalidRestRequestException; +import org.onap.so.rest.exceptions.RestProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.google.common.base.Optional; + +/** + * A Service to perform HTTP requests + * + * @author waqas.ikram@est.tech + */ +public class HttpRestServiceProviderImpl implements HttpRestServiceProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpRestServiceProviderImpl.class); + private final RestTemplate restTemplate; + private final HttpHeadersProvider httpHeadersProvider; + + public HttpRestServiceProviderImpl(final RestTemplate restTemplate) { + this.restTemplate = restTemplate; + this.httpHeadersProvider = new BasicHttpHeadersProvider(); + } + + public HttpRestServiceProviderImpl(final RestTemplate restTemplate, final HttpHeadersProvider httpHeadersProvider) { + this.restTemplate = restTemplate; + this.httpHeadersProvider = httpHeadersProvider; + } + + @Override + public Optional get(final String url, final Class clazz) { + final ResponseEntity response = getHttpResponse(url, clazz); + if (!response.getStatusCode().equals(HttpStatus.OK)) { + final String message = + "Unable to invoke HTTP GET using URL: " + url + ", Response Code: " + response.getStatusCode(); + LOGGER.error(message); + return Optional.absent(); + } + + if (response.hasBody()) { + return Optional.of(response.getBody()); + } + return Optional.absent(); + } + + + @Override + public ResponseEntity getHttpResponse(final String url, final Class clazz) { + LOGGER.trace("Will invoke HTTP GET using URL: {}", url); + try { + final HttpEntity request = new HttpEntity<>(getHttpHeaders()); + return restTemplate.exchange(url, HttpMethod.GET, request, clazz); + + } catch (final HttpClientErrorException httpClientErrorException) { + final String message = "Unable to invoke HTTP GET using url: " + url + ", Response: " + + httpClientErrorException.getRawStatusCode(); + LOGGER.error(message, httpClientErrorException); + final int rawStatusCode = httpClientErrorException.getRawStatusCode(); + if (rawStatusCode == HttpStatus.BAD_REQUEST.value() || rawStatusCode == HttpStatus.NOT_FOUND.value()) { + throw new InvalidRestRequestException("No result found for given url: " + url); + } + throw new RestProcessingException("Unable to invoke HTTP GET using URL: " + url); + + } catch (final RestClientException restClientException) { + LOGGER.error("Unable to invoke HTTP GET using url: {}", url, restClientException); + throw new RestProcessingException("Unable to invoke HTTP GET using URL: " + url, restClientException); + } + } + + @Override + public Optional post(final Object object, final String url, final Class clazz) { + final ResponseEntity response = postHttpRequest(object, url, clazz); + if (!response.getStatusCode().equals(HttpStatus.OK)) { + final String message = + "Unable to invoke HTTP GET using URL: " + url + ", Response Code: " + response.getStatusCode(); + LOGGER.error(message); + return Optional.absent(); + } + + if (response.hasBody()) { + return Optional.of(response.getBody()); + } + + return Optional.absent(); + } + + + @Override + public ResponseEntity postHttpRequest(final Object object, final String url, final Class clazz) { + try { + final HttpEntity request = new HttpEntity<>(object, getHttpHeaders()); + return restTemplate.exchange(url, HttpMethod.POST, request, clazz); + + } catch (final HttpClientErrorException httpClientErrorException) { + final String message = "Unable to invoke HTTP POST using url: " + url + ", Response: " + + httpClientErrorException.getRawStatusCode(); + LOGGER.error(message, httpClientErrorException); + final int rawStatusCode = httpClientErrorException.getRawStatusCode(); + if (rawStatusCode == HttpStatus.BAD_REQUEST.value() || rawStatusCode == HttpStatus.NOT_FOUND.value()) { + throw new InvalidRestRequestException("No result found for given url: " + url); + } + throw new RestProcessingException("Unable to invoke HTTP GET using URL: " + url); + + } catch (final RestClientException restClientException) { + LOGGER.error("Unable to invoke HTTP POST using url: {}", url, restClientException); + throw new RestProcessingException("Unable to invoke HTTP GET using URL: " + url, restClientException); + } + } + + private HttpHeaders getHttpHeaders() { + return httpHeadersProvider.getHttpHeaders(); + } +} diff --git a/common/src/test/java/org/onap/so/configuration/rest/BasicHttpHeadersProviderTest.java b/common/src/test/java/org/onap/so/configuration/rest/BasicHttpHeadersProviderTest.java new file mode 100644 index 0000000000..3e762cfbe7 --- /dev/null +++ b/common/src/test/java/org/onap/so/configuration/rest/BasicHttpHeadersProviderTest.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.onap.so.configuration.rest.BasicHttpHeadersProvider.AUTHORIZATION_HEADER; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + + +/** + * @author waqas.ikram@est.tech + * + */ +public class BasicHttpHeadersProviderTest { + + private static final String BASIC_AUTH_VALUE = "Basic AuthValue"; + + @Test + public void test_getHttpHeaders_ContentTypeIsJson() { + final HttpHeadersProvider objUnderTest = new BasicHttpHeadersProvider(); + final HttpHeaders actualHttpHeaders = objUnderTest.getHttpHeaders(); + assertNull(actualHttpHeaders.get(AUTHORIZATION_HEADER)); + assertEquals(MediaType.APPLICATION_JSON, actualHttpHeaders.getContentType()); + } + + @Test + public void test_getHttpHeaders_ContainAuthorizationHeader() { + final HttpHeadersProvider objUnderTest = new BasicHttpHeadersProvider(BASIC_AUTH_VALUE); + final HttpHeaders actualHttpHeaders = objUnderTest.getHttpHeaders(); + assertEquals(Arrays.asList(BASIC_AUTH_VALUE), actualHttpHeaders.get(AUTHORIZATION_HEADER)); + assertEquals(MediaType.APPLICATION_JSON, actualHttpHeaders.getContentType()); + } + +} diff --git a/common/src/test/java/org/onap/so/configuration/rest/HttpComponentsClientConfigurationTest.java b/common/src/test/java/org/onap/so/configuration/rest/HttpComponentsClientConfigurationTest.java new file mode 100644 index 0000000000..5084acc934 --- /dev/null +++ b/common/src/test/java/org/onap/so/configuration/rest/HttpComponentsClientConfigurationTest.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.configuration.rest; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +/** + * @author waqas.ikram@est.tech + */ +public class HttpComponentsClientConfigurationTest { + + @Test + public void test_httpComponentsClientHttpRequestFactory_HttpComponentsClientHttpRequestFactoryNotNull() { + final HttpClientConnectionConfiguration clientConnectionConfiguration = new HttpClientConnectionConfiguration(); + final HttpComponentsClientConfiguration objUnderTest = + new HttpComponentsClientConfiguration(clientConnectionConfiguration); + + final HttpComponentsClientHttpRequestFactory factory = objUnderTest.httpComponentsClientHttpRequestFactory(); + assertNotNull(factory); + assertNotNull(factory.getHttpClient()); + + } + +} diff --git a/common/src/test/java/org/onap/so/rest/service/HttpRestServiceProviderImplTest.java b/common/src/test/java/org/onap/so/rest/service/HttpRestServiceProviderImplTest.java new file mode 100644 index 0000000000..a738afe565 --- /dev/null +++ b/common/src/test/java/org/onap/so/rest/service/HttpRestServiceProviderImplTest.java @@ -0,0 +1,252 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.rest.service; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.so.rest.exceptions.InvalidRestRequestException; +import org.onap.so.rest.exceptions.RestProcessingException; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.google.common.base.Optional; + + +/** + * @author waqas.ikram@est.tech + */ +@RunWith(MockitoJUnitRunner.class) +public class HttpRestServiceProviderImplTest { + + private static final String BODY = "{}"; + private static final String DUMMY_URL = "http://localhost:9000/dummy/url"; + + @Mock + private RestTemplate mockRestTemplate; + + @Mock + private ResponseEntity mockEntity; + + @Test + public void test_get_returnOptionalPresentIfResponseIsOKAndHasBody() { + + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.OK); + when(mockEntity.hasBody()).thenReturn(true); + when(mockEntity.getBody()).thenReturn(BODY); + + final Optional actual = objUnderTest.get(DUMMY_URL, String.class); + + assertTrue(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), + eq(String.class)); + } + + @Test + public void test_get_returnOptionalPresentIfResponseIsNotOK() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR); + + final Optional actual = objUnderTest.get(DUMMY_URL, String.class); + + assertFalse(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), + eq(String.class)); + } + + @Test + public void test_get_returnOptionalPresentIfResponseIsOKAndNoBody() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.OK); + when(mockEntity.hasBody()).thenReturn(false); + + final Optional actual = objUnderTest.get(DUMMY_URL, String.class); + + assertFalse(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), + eq(String.class)); + } + + @Test(expected = InvalidRestRequestException.class) + public void test_get_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionWithHttpStatusBadRequest() { + assertGetErrorScenario(HttpStatus.BAD_REQUEST); + + } + + @Test(expected = InvalidRestRequestException.class) + public void test_get_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionWithHttpStatusNotFoundHttpStatus() { + assertGetErrorScenario(HttpStatus.NOT_FOUND); + } + + @Test(expected = RestProcessingException.class) + public void test_get_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionOccured() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(HttpClientErrorException.class); + + objUnderTest.get(DUMMY_URL, String.class); + } + + @Test(expected = RestProcessingException.class) + public void test_get_ThrowsInvalidRestRequestExceptionifRestProcessingExceptionOccured() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(RestClientException.class); + + objUnderTest.get(DUMMY_URL, String.class); + } + + @Test + public void test_post_returnOptionalPresentIfResponseIsOKAndHasBody() { + + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.OK); + when(mockEntity.hasBody()).thenReturn(true); + when(mockEntity.getBody()).thenReturn(BODY); + + final Optional actual = objUnderTest.post(BODY, DUMMY_URL, String.class); + + assertTrue(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), + eq(String.class)); + } + + @Test + public void test_post_returnOptionalPresentIfResponseIsOKAndHasNoBody() { + + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.OK); + when(mockEntity.hasBody()).thenReturn(false); + + final Optional actual = objUnderTest.post(BODY, DUMMY_URL, String.class); + + assertFalse(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), + eq(String.class)); + } + + + @Test + public void test_post_returnOptionalPresentIfResponseIsNotOKAndHasBody() { + + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenReturn(mockEntity); + + when(mockEntity.getStatusCode()).thenReturn(HttpStatus.PARTIAL_CONTENT); + + final Optional actual = objUnderTest.post(BODY, DUMMY_URL, String.class); + + assertFalse(actual.isPresent()); + verify(mockRestTemplate, atLeastOnce()).exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), + eq(String.class)); + } + + @Test(expected = InvalidRestRequestException.class) + public void test_post_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionWithHttpStatusBadRequest() { + assertPostErrorScenario(HttpStatus.BAD_REQUEST); + + } + + @Test(expected = InvalidRestRequestException.class) + public void test_post_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionWithHttpStatusNotFoundHttpStatus() { + assertPostErrorScenario(HttpStatus.NOT_FOUND); + } + + @Test(expected = RestProcessingException.class) + public void test_post_ThrowsInvalidRestRequestExceptionifHttpClientErrorExceptionOccured() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenThrow(HttpClientErrorException.class); + + objUnderTest.post(BODY, DUMMY_URL, String.class); + } + + @Test(expected = RestProcessingException.class) + public void test_post_ThrowsInvalidRestRequestExceptionifRestProcessingExceptionOccured() { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenThrow(RestClientException.class); + + objUnderTest.post(BODY, DUMMY_URL, String.class); + } + + private void assertPostErrorScenario(final HttpStatus status) { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + final HttpClientErrorException errorException = new HttpClientErrorException(status); + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.POST), any(HttpEntity.class), eq(String.class))) + .thenThrow(errorException); + + objUnderTest.post(BODY, DUMMY_URL, String.class); + } + + private void assertGetErrorScenario(final HttpStatus status) { + final HttpRestServiceProvider objUnderTest = new HttpRestServiceProviderImpl(mockRestTemplate); + + final HttpClientErrorException errorException = new HttpClientErrorException(status); + when(mockRestTemplate.exchange(eq(DUMMY_URL), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class))) + .thenThrow(errorException); + + objUnderTest.get(DUMMY_URL, String.class); + } + +} -- cgit 1.2.3-korg