Commit d04266c9 authored by ethiraj krishnamanaidu's avatar ethiraj krishnamanaidu
Browse files

Merge branch 'refactor_http_body_parsing' into 'master'

Refactor http body parsing

See merge request !29
parents d4e42813 f63dcc66
Pipeline #12904 passed with stages
in 5 minutes and 35 seconds
......@@ -84,6 +84,7 @@ The following software have components provided under the terms of this license:
- Spring Context (from https://github.com/spring-projects/spring-framework)
- Spring Core (from https://github.com/spring-projects/spring-framework)
- Spring Expression Language (SpEL) (from https://github.com/spring-projects/spring-framework)
- Spring TestContext Framework (from https://github.com/spring-projects/spring-framework)
- Spring Web (from https://github.com/spring-projects/spring-framework)
- Spring Web MVC (from https://github.com/spring-projects/spring-framework)
- T-Digest (from https://github.com/tdunning/t-digest)
......
......@@ -6,7 +6,7 @@
<groupId>org.opengroup.osdu</groupId>
<artifactId>os-core-common</artifactId>
<version>0.3.16</version>
<version>0.3.17</version>
<packaging>jar</packaging>
<properties>
......@@ -68,6 +68,12 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
......@@ -99,7 +105,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
......
......@@ -14,6 +14,7 @@
package org.opengroup.osdu.core.common.crs;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.stereotype.Component;
......@@ -22,15 +23,21 @@ import org.springframework.stereotype.Component;
public class CrsConverterClientFactory extends AbstractFactoryBean<ICrsConverterFactory> {
//TODO: make it private once endpoint is up for all clouds
@Value("${CRS_API:}")
public String CRS_API;
public final String crsApi;
private final HttpResponseBodyMapper mapper;
public CrsConverterClientFactory(@Value("${CRS_API:}") String crsApi, HttpResponseBodyMapper mapper) {
this.crsApi = crsApi;
this.mapper = mapper;
}
@Override
protected ICrsConverterFactory createInstance() throws Exception {
return new CrsConverterFactory(CrsConverterAPIConfig
.builder()
.rootUrl(CRS_API)
.build());
.rootUrl(crsApi)
.build(), mapper);
}
@Override
......
......@@ -14,18 +14,21 @@
package org.opengroup.osdu.core.common.crs;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.http.HttpClient;
public class CrsConverterFactory implements ICrsConverterFactory {
private final CrsConverterAPIConfig config;
private final HttpResponseBodyMapper mapper;
public CrsConverterFactory(CrsConverterAPIConfig config) {
public CrsConverterFactory(CrsConverterAPIConfig config, HttpResponseBodyMapper mapper) {
if (config == null) {
throw new IllegalArgumentException("CrsConverterAPIConfig cannot be empty");
}
this.config = config;
this.mapper = mapper;
}
@Override
......@@ -33,6 +36,6 @@ public class CrsConverterFactory implements ICrsConverterFactory {
if (headers == null) {
throw new NullPointerException("headers cannot be null");
}
return new CrsConverterService(this.config, new HttpClient(), headers);
return new CrsConverterService(this.config, new HttpClient(), headers, mapper);
}
}
\ No newline at end of file
......@@ -14,8 +14,9 @@
package org.opengroup.osdu.core.common.crs;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyParsingException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.crs.*;
import org.opengroup.osdu.core.common.http.HttpRequest;
......@@ -26,13 +27,16 @@ public class CrsConverterService implements ICrsConverterService {
private final String rootUrl;
private final IHttpClient httpClient;
private final DpsHeaders headers;
private final HttpResponseBodyMapper responseBodyMapper;
CrsConverterService(CrsConverterAPIConfig config,
IHttpClient httpClient,
DpsHeaders headers) {
DpsHeaders headers,
HttpResponseBodyMapper mapper) {
this.rootUrl = config.getRootUrl();
this.httpClient = httpClient;
this.headers = headers;
this.responseBodyMapper = mapper;
if (config.apiKey != null) {
headers.put("AppKey", config.apiKey);
}
......@@ -64,8 +68,8 @@ public class CrsConverterService implements ICrsConverterService {
private <T> T getResult(HttpResponse result, Class<T> type) throws CrsConverterException {
if (result.isSuccessCode()) {
try {
return result.parseBody(type);
} catch (JsonSyntaxException e) {
return responseBodyMapper.parseBody(result, type);
} catch (HttpResponseBodyParsingException e) {
throw new CrsConverterException("Error parsing response. Check the inner HttpResponse for more info.",
result);
}
......
......@@ -14,18 +14,21 @@
package org.opengroup.osdu.core.common.entitlements;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.http.HttpClient;
public class EntitlementsFactory implements IEntitlementsFactory {
private final EntitlementsAPIConfig config;
private final HttpResponseBodyMapper mapper;
public EntitlementsFactory(EntitlementsAPIConfig config) {
public EntitlementsFactory(EntitlementsAPIConfig config, HttpResponseBodyMapper mapper) {
if (config == null) {
throw new IllegalArgumentException("EntitlementsAPIConfig cannot be empty");
}
this.config = config;
this.mapper = mapper;
}
@Override
......@@ -35,6 +38,6 @@ public class EntitlementsFactory implements IEntitlementsFactory {
}
return new EntitlementsService(this.config,
new HttpClient(),
headers);
headers, mapper);
}
}
\ No newline at end of file
......@@ -14,8 +14,9 @@
package org.opengroup.osdu.core.common.entitlements;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyParsingException;
import org.opengroup.osdu.core.common.model.entitlements.EntitlementsException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.entitlements.CreateGroup;
......@@ -33,13 +34,16 @@ public class EntitlementsService implements IEntitlementsService {
private final String rootUrl;
private final IHttpClient httpClient;
private final DpsHeaders headers;
private final HttpResponseBodyMapper responseBodyMapper;
EntitlementsService(EntitlementsAPIConfig config,
IHttpClient httpClient,
DpsHeaders headers) {
DpsHeaders headers,
HttpResponseBodyMapper mapper) {
this.rootUrl = config.getRootUrl();
this.httpClient = httpClient;
this.headers = headers;
this.responseBodyMapper = mapper;
if (config.apiKey != null) {
headers.put("AppKey", config.apiKey);
}
......@@ -126,8 +130,8 @@ public class EntitlementsService implements IEntitlementsService {
private <T> T getResult(HttpResponse result, Class<T> type) throws EntitlementsException {
if (result.isSuccessCode()) {
try {
return result.parseBody(type);
} catch (JsonSyntaxException e) {
return responseBodyMapper.parseBody(result, type);
} catch (HttpResponseBodyParsingException e) {
throw new EntitlementsException("Error parsing response. Check the inner HttpResponse for more info.",
result);
}
......
package org.opengroup.osdu.core.common.http;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpConfiguration {
@Bean
public ObjectMapper jsonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return objectMapper;
}
}
......@@ -14,23 +14,18 @@
package org.opengroup.osdu.core.common.http;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class HttpResponse {
static final Gson gson = new Gson();
static final JsonParser parser = new JsonParser();
Map<String, List<String>> headers;
private String body = "";
private String contentType = "";
......@@ -39,45 +34,32 @@ public class HttpResponse {
private HttpRequest request;
private long latency = 0;
public Boolean isSuccessCode() {
public boolean isSuccessCode() {
return responseCode >= 200 && responseCode <= 299;
}
public Boolean isServerErrorCode() {
public boolean isServerErrorCode() {
return responseCode >= 500;
}
public Boolean IsNotFoundCode() {
public boolean IsNotFoundCode() {
return responseCode == 404;
}
public Boolean IsUnauthorizedCode() {
public boolean IsUnauthorizedCode() {
return responseCode == 401;
}
public Boolean IsForbiddenCode() {
public boolean IsForbiddenCode() {
return responseCode == 403;
}
public Boolean IsBadRequestCode() {
public boolean IsBadRequestCode() {
return responseCode == 400;
}
public Boolean hasException() {
public boolean hasException() {
return exception != null;
}
public JsonObject getAsJsonObject() {
if (StringUtils.isBlank(body))
return null;
return parser.parse(body).getAsJsonObject();
}
public <T> T parseBody(Class<T> type) {
if (StringUtils.isBlank(body))
return null;
return gson.fromJson(body, type);
}
}
\ No newline at end of file
package org.opengroup.osdu.core.common.http.json;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.http.HttpResponse;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class HttpResponseBodyMapper {
private final ObjectMapper mapper;
public <T> T parseBody(HttpResponse response, Class<T> type) throws HttpResponseBodyParsingException {
String body = response.getBody();
if (StringUtils.isBlank(body)) {
return null;
}
try {
return mapper.readValue(body, type);
} catch (JsonProcessingException e) {
throw new HttpResponseBodyParsingException(e);
}
}
public JsonNode parseBody(HttpResponse response) throws HttpResponseBodyParsingException {
String body = response.getBody();
if (StringUtils.isBlank(body)) {
return null;
}
try {
return mapper.readTree(body);
} catch (JsonProcessingException e) {
throw new HttpResponseBodyParsingException(e);
}
}
}
package org.opengroup.osdu.core.common.http.json;
public class HttpResponseBodyParsingException extends Exception {
public HttpResponseBodyParsingException(Exception e) {
super(e);
}
}
......@@ -14,18 +14,18 @@
package org.opengroup.osdu.core.common.legal;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.http.HttpClient;
public class LegalFactory implements ILegalFactory {
private final LegalAPIConfig config;
private final HttpResponseBodyMapper mapper;
public LegalFactory(LegalAPIConfig config) {
if (config == null) {
throw new IllegalArgumentException("LegalAPIConfig cannot be empty");
}
public LegalFactory(LegalAPIConfig config, HttpResponseBodyMapper mapper) {
this.config = config;
this.mapper = mapper;
}
@Override
......@@ -33,6 +33,6 @@ public class LegalFactory implements ILegalFactory {
if (headers == null) {
throw new NullPointerException("headers cannot be null");
}
return new LegalService(this.config, new HttpClient(), headers);
return new LegalService(this.config, new HttpClient(), headers, mapper);
}
}
\ No newline at end of file
......@@ -14,8 +14,9 @@
package org.opengroup.osdu.core.common.legal;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang3.StringUtils;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyParsingException;
import org.opengroup.osdu.core.common.model.legal.*;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.http.HttpRequest;
......@@ -26,13 +27,16 @@ public class LegalService implements ILegalProvider {
private final String rootUrl;
private final IHttpClient httpClient;
private final DpsHeaders headers;
private final HttpResponseBodyMapper responseBodyMapper;
LegalService(LegalAPIConfig config,
IHttpClient httpClient,
DpsHeaders headers) {
DpsHeaders headers,
HttpResponseBodyMapper mapper) {
this.rootUrl = config.getRootUrl();
this.httpClient = httpClient;
this.headers = headers;
this.responseBodyMapper = mapper;
if (config.apiKey != null) {
headers.put("AppKey", config.apiKey);
}
......@@ -92,8 +96,8 @@ public class LegalService implements ILegalProvider {
private <T> T getResult(HttpResponse result, Class<T> type) throws LegalException {
if (result.isSuccessCode()) {
try {
return result.parseBody(type);
} catch (JsonSyntaxException e) {
return responseBodyMapper.parseBody(result, type);
} catch (HttpResponseBodyParsingException e) {
throw new LegalException("Error parsing response. Check the inner HttpResponse for more info.", result);
}
} else {
......
......@@ -24,6 +24,9 @@ import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.opengroup.osdu.core.common.util.SerializationUtils.DEFAULT_EXPIRATION_DATE;
import static org.opengroup.osdu.core.common.util.SerializationUtils.EXPIRATION_DATE_FORMAT;
/**
* If any class variable changed here,
* need to update the corresponding doc model class in SwaggerHelper.java
......@@ -33,7 +36,7 @@ import java.util.stream.Collectors;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Properties {
public static final Date DEFAULT_EXPIRATIONDATE = Date.valueOf("9999-12-31");
public static final Date DEFAULT_EXPIRATIONDATE = DEFAULT_EXPIRATION_DATE;
public final static String UNKNOWN_CONTRACT_ID = "Unknown";
public final static String NO_CONTRACT_ID = "No Contract Related";
......@@ -43,7 +46,7 @@ public class Properties {
private String contractId;
@JsonDeserialize(using = ExpirationDateDeserializer.class)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = EXPIRATION_DATE_FORMAT)
private Date expirationDate;
@Getter(AccessLevel.NONE)
......
package org.opengroup.osdu.core.common.search;
import org.opengroup.osdu.core.common.http.HttpClient;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
public class SearchFactory implements ISearchFactory {
private final SearchAPIConfig config;
private final HttpResponseBodyMapper bodyMapper;
public SearchFactory(SearchAPIConfig config) {
public SearchFactory(SearchAPIConfig config, HttpResponseBodyMapper bodyMapper) {
if (config == null) {
throw new IllegalArgumentException("SearchAPIConfig cannot be empty");
}
this.config = config;
this.bodyMapper = bodyMapper;
}
@Override
......@@ -19,6 +22,6 @@ public class SearchFactory implements ISearchFactory {
if (headers == null) {
throw new NullPointerException("headers cannot be null");
}
return new SearchService(this.config, new HttpClient(), headers);
return new SearchService(this.config, new HttpClient(), headers, bodyMapper);
}
}
......@@ -2,7 +2,8 @@ package org.opengroup.osdu.core.common.search;
import org.apache.commons.lang3.StringUtils;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyParsingException;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.model.search.*;
import org.opengroup.osdu.core.common.http.HttpRequest;
......@@ -12,10 +13,12 @@ import org.opengroup.osdu.core.common.http.IHttpClient;
public class SearchService implements ISearchService {
SearchService(SearchAPIConfig config,
IHttpClient httpClient,
DpsHeaders headers) {
DpsHeaders headers,
HttpResponseBodyMapper bodyMapper) {
this.rootUrl = config.getRootUrl();
this.httpClient = httpClient;
this.headers = headers;
this.bodyMapper = bodyMapper;
if (config.apiKey != null) {
headers.put("AppKey", config.getApiKey());
}
......@@ -24,6 +27,7 @@ public class SearchService implements ISearchService {
private final String rootUrl;
private final IHttpClient httpClient;
private final DpsHeaders headers;
private final HttpResponseBodyMapper bodyMapper;
@Override
public CursorQueryResponse getAllKindEntries(String kind) throws SearchException {
......@@ -84,8 +88,8 @@ public class SearchService implements ISearchService {
private <T> T getResult(HttpResponse result, Class<T> type) throws SearchException {
if (result.isSuccessCode()) {
try {
return result.parseBody(type);
} catch (JsonSyntaxException e) {
return bodyMapper.parseBody(result, type);
} catch (HttpResponseBodyParsingException e) {
throw new SearchException("Error parsing response. Check the inner HttpResponse for more info.",
result);
}
......
package org.opengroup.osdu.core.common.storage;
import org.opengroup.osdu.core.common.http.HttpClient;
import org.opengroup.osdu.core.common.http.json.HttpResponseBodyMapper;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
public class StorageFactory implements IStorageFactory {
public StorageFactory(StorageAPIConfig config) {
public StorageFactory(StorageAPIConfig config, HttpResponseBodyMapper bodyMapper) {
if (config == null) {
throw new IllegalArgumentException("StorageAPIConfig cannot be empty");
}
this.config = config;
this.bodyMapper = bodyMapper;
}
private final StorageAPIConfig config;
private final HttpResponseBodyMapper bodyMapper;
@Override
public IStorageService create(DpsHeaders headers) {
if (headers == null) {
throw new NullPointerException("headers cannot be null");
}
return new StorageService(this.config, new HttpClient(), headers);
return new StorageService(this.config, new HttpClient(), headers, bodyMapper);
}
}