Skip to content

Commit

Permalink
fixed ClassNotFoundException errors in ParaClient when a WebApplicati…
Browse files Browse the repository at this point in the history
…onException is thrown
  • Loading branch information
albogdano committed Oct 5, 2021
1 parent 9f65c4e commit 1e5b638
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 180 deletions.
27 changes: 0 additions & 27 deletions .travis.yml

This file was deleted.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

## A scalable, multitenant backend for the cloud.

[![Build Status](https://travis-ci.org/Erudika/para.svg?branch=master)](https://travis-ci.org/Erudika/para)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=com.erudika%3Apara-parent&metric=alert_status)](https://sonarcloud.io/dashboard?id=com.erudika%3Apara-parent)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.erudika/para-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.erudika/para-core)
[![Join the chat at https://gitter.im/Erudika/para](https://badges.gitter.im/Erudika/para.svg)](https://gitter.im/Erudika/para?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Expand Down
36 changes: 21 additions & 15 deletions para-client/src/main/java/com/erudika/para/client/ParaClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

import com.erudika.para.Para;
import com.erudika.para.core.App;
import static com.erudika.para.core.App.AllowedMethods.DELETE;
import static com.erudika.para.core.App.AllowedMethods.GET;
import static com.erudika.para.core.App.AllowedMethods.PATCH;
import static com.erudika.para.core.App.AllowedMethods.POST;
import static com.erudika.para.core.App.AllowedMethods.PUT;
import com.erudika.para.core.ParaObject;
import com.erudika.para.core.Tag;
import com.erudika.para.core.utils.ParaObjectUtils;
Expand Down Expand Up @@ -48,12 +53,12 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static javax.ws.rs.HttpMethod.DELETE;
import static javax.ws.rs.HttpMethod.GET;
import static javax.ws.rs.HttpMethod.POST;
import static javax.ws.rs.HttpMethod.PUT;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
//import static javax.ws.rs.HttpMethod.DELETE;
//import static javax.ws.rs.HttpMethod.GET;
//import static javax.ws.rs.HttpMethod.POST;
//import static javax.ws.rs.HttpMethod.PUT;
//import javax.ws.rs.WebApplicationException;
//import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import nl.altindag.ssl.SSLFactory;
Expand All @@ -74,6 +79,7 @@
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
Expand Down Expand Up @@ -326,15 +332,15 @@ private <T> T readEntity(HttpEntity respEntity, Class<?> returnType, int statusC
Map<String, Object> error = readEntity(respEntity, Map.class);
if (error != null && error.containsKey("code")) {
String msg = error.containsKey("message") ? (String) error.get("message") : "error";
WebApplicationException e = new WebApplicationException(msg, (Integer) error.get("code"));
RuntimeException e = new RuntimeException((Integer) error.get("code") + " - " + msg);
logger.error("{} - {}", error.get("code"), e.getMessage());
if (throwExceptionOnHTTPError) {
throw e;
}
} else {
logger.error("{} - {}", statusCode, reason);
if (throwExceptionOnHTTPError) {
throw new WebApplicationException(reason, statusCode);
throw new RuntimeException(statusCode + " - " + reason);
}
}
}
Expand Down Expand Up @@ -393,7 +399,7 @@ protected String getFullPath(String resourcePath) {
*/
public <T> T invokeGet(String resourcePath, MultivaluedMap<String, String> params, Class<?> returnType) {
logger.debug("GET {}, params: {}", getFullPath(resourcePath), params);
return invokeSignedRequest(accessKey, key(!JWT_PATH.equals(resourcePath)), GET,
return invokeSignedRequest(accessKey, key(!JWT_PATH.equals(resourcePath)), GET.toString(),
getEndpoint(), getFullPath(resourcePath), null, params, null, returnType);
}

Expand All @@ -407,7 +413,7 @@ public <T> T invokeGet(String resourcePath, MultivaluedMap<String, String> param
*/
public <T> T invokePost(String resourcePath, Object entity, Class<?> returnType) {
logger.debug("POST {}, entity: {}", getFullPath(resourcePath), entity, returnType);
return invokeSignedRequest(accessKey, key(true), POST,
return invokeSignedRequest(accessKey, key(true), POST.toString(),
getEndpoint(), getFullPath(resourcePath), null, null, entity, returnType);
}

Expand All @@ -421,7 +427,7 @@ public <T> T invokePost(String resourcePath, Object entity, Class<?> returnType)
*/
public <T> T invokePut(String resourcePath, Object entity, Class<?> returnType) {
logger.debug("PUT {}, entity: {}", getFullPath(resourcePath), entity);
return invokeSignedRequest(accessKey, key(true), PUT,
return invokeSignedRequest(accessKey, key(true), PUT.toString(),
getEndpoint(), getFullPath(resourcePath), null, null, entity, returnType);
}

Expand All @@ -435,7 +441,7 @@ public <T> T invokePut(String resourcePath, Object entity, Class<?> returnType)
*/
public <T> T invokePatch(String resourcePath, Object entity, Class<?> returnType) {
logger.debug("PATCH {}, entity: {}", getFullPath(resourcePath), entity);
return invokeSignedRequest(accessKey, key(true), "PATCH",
return invokeSignedRequest(accessKey, key(true), PATCH.toString(),
getEndpoint(), getFullPath(resourcePath), null, null, entity, returnType);
}

Expand All @@ -449,7 +455,7 @@ public <T> T invokePatch(String resourcePath, Object entity, Class<?> returnType
*/
public <T> T invokeDelete(String resourcePath, MultivaluedMap<String, String> params, Class<?> returnType) {
logger.debug("DELETE {}, params: {}", getFullPath(resourcePath), params);
return invokeSignedRequest(accessKey, key(true), DELETE,
return invokeSignedRequest(accessKey, key(true), DELETE.toString(),
getEndpoint(), getFullPath(resourcePath), null, params, null, returnType);
}

Expand Down Expand Up @@ -1484,7 +1490,7 @@ public <P extends ParaObject> P me() {
public <P extends ParaObject> P me(String accessToken) {
if (!StringUtils.isBlank(accessToken)) {
String auth = accessToken.startsWith("Bearer") ? accessToken : "Bearer " + accessToken;
Map<String, Object> data = invokeSignedRequest(accessKey, auth, GET,
Map<String, Object> data = invokeSignedRequest(accessKey, auth, GET.toString(),
getEndpoint(), getFullPath("_me"), null, null, null, Map.class);
return ParaObjectUtils.setAnnotatedFields(data);
}
Expand Down Expand Up @@ -1571,7 +1577,7 @@ public Map<String, Object> rebuildIndex() {
public Map<String, Object> rebuildIndex(String destinationIndex) {
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
params.putSingle("destinationIndex", destinationIndex);
return invokeSignedRequest(accessKey, key(true), POST,
return invokeSignedRequest(accessKey, key(true), POST.toString(),
getEndpoint(), getFullPath("_reindex"), null, params, null, Map.class);
}

Expand Down
138 changes: 2 additions & 136 deletions para-core/src/main/java/com/erudika/para/rest/Signer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@
*/
package com.erudika.para.rest;

import com.erudika.para.Para;
import com.erudika.para.core.utils.ParaObjectUtils;
import com.erudika.para.utils.Config;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.Clock;
import java.time.Instant;
Expand All @@ -36,16 +32,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -183,114 +170,6 @@ public static Instant parseAWSInstant(String date) {
return LocalDateTime.from(TIME_FORMATTER.parse(date)).toInstant(ZoneOffset.UTC);
}

/**
* Builds, signs and executes a request to an API endpoint using the provided credentials.
* Signs the request using the Amazon Signature 4 algorithm and returns the response.
* @param apiClient Jersey Client object
* @param accessKey access key
* @param secretKey secret key
* @param httpMethod the method (GET, POST...)
* @param endpointURL protocol://host:port
* @param reqPath the API resource path relative to the endpointURL
* @param headers headers map
* @param params parameters map
* @param entity an entity containing any Java object (payload), could be null
* @return a response object
*/
public Response invokeSignedRequest(Client apiClient, String accessKey, String secretKey,
String httpMethod, String endpointURL, String reqPath, Map<String, String> headers,
MultivaluedMap<String, String> params, Entity<?> entity) {
byte[] jsonEntity = null;
if (entity != null) {
try {
jsonEntity = ParaObjectUtils.getJsonWriterNoIdent().writeValueAsBytes(entity.getEntity());
} catch (JsonProcessingException ex) {
jsonEntity = null;
logger.error(null, ex);
}
}
return invokeSignedRequest(apiClient, accessKey, secretKey, httpMethod,
endpointURL, reqPath, headers, params, jsonEntity);
}

/**
* Builds, signs and executes a request to an API endpoint using the provided credentials.
* Signs the request using the Amazon Signature 4 algorithm and returns the response.
* @param apiClient Jersey Client object
* @param accessKey access key
* @param secretKey secret key
* @param httpMethod the method (GET, POST...)
* @param endpointURL protocol://host:port
* @param reqPath the API resource path relative to the endpointURL
* @param headers headers map
* @param params parameters map
* @param jsonEntity an object serialized to JSON byte array (payload), could be null
* @return a response object
*/
public Response invokeSignedRequest(Client apiClient, String accessKey, String secretKey,
String httpMethod, String endpointURL, String reqPath,
Map<String, String> headers, MultivaluedMap<String, String> params, byte[] jsonEntity) {

boolean isJWT = StringUtils.startsWithIgnoreCase(secretKey, "Bearer");

// strip URI template param brackets - https://stackoverflow.com/questions/57011188
reqPath = reqPath.replaceAll("[{}]", "");
cleanUpParams(params);

WebTarget target = apiClient.target(endpointURL).path(reqPath);
Map<String, String> signedHeaders = new HashMap<>();
if (!isJWT) {
signedHeaders = signRequest(accessKey, secretKey, httpMethod, endpointURL, reqPath,
headers, params, jsonEntity);
}

if (params != null) {
for (Map.Entry<String, List<String>> param : params.entrySet()) {
String key = param.getKey();
List<String> value = param.getValue();
if (value != null && !value.isEmpty() && value.get(0) != null) {
target = target.queryParam(key, value.toArray());
}
}
}

Invocation.Builder builder = target.request(MediaType.APPLICATION_JSON);

if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
builder.header(header.getKey(), header.getValue());
}
}

Entity<?> jsonPayload = null;
if (jsonEntity != null && jsonEntity.length > 0) {
try {
jsonPayload = Entity.json(new String(jsonEntity, Config.DEFAULT_ENCODING));
} catch (IOException ex) {
logger.error(null, ex);
}
}

if (isJWT) {
builder.header(HttpHeaders.AUTHORIZATION, secretKey);
} else {
builder.header(HttpHeaders.AUTHORIZATION, signedHeaders.get(HttpHeaders.AUTHORIZATION)).
header("X-Amz-Date", signedHeaders.get("X-Amz-Date"));
}

if (Config.getConfigBoolean("user_agent_id_enabled", true)) {
String userAgent = new StringBuilder("Para client ").append(Para.getVersion()).append(" ").append(accessKey).
append(" (Java ").append(System.getProperty("java.runtime.version")).append(")").toString();
builder.header(HttpHeaders.USER_AGENT, userAgent);
}

if (jsonPayload != null) {
return builder.method(httpMethod, jsonPayload);
} else {
return builder.method(httpMethod);
}
}

/**
* Builds and signs a request to an API endpoint using the provided credentials.
* @param accessKey access key
Expand All @@ -316,12 +195,12 @@ public Map<String, String> signRequest(String accessKey, String secretKey,

if (StringUtils.isBlank(secretKey)) {
logger.debug("Anonymous request: {} {}", httpMethod, reqPath);
headers.put(HttpHeaders.AUTHORIZATION, "Anonymous " + accessKey);
headers.put("Authorization", "Anonymous " + accessKey);
return headers;
}

if (httpMethod == null) {
httpMethod = HttpMethod.GET;
httpMethod = "GET";
}

InputStream in = null;
Expand All @@ -343,17 +222,4 @@ public Map<String, String> signRequest(String accessKey, String secretKey,

return sign(httpMethod, endpointURL, reqPath, headers, sigParams, in, accessKey, secretKey);
}

private void cleanUpParams(MultivaluedMap<String, String> params) {
if (params != null) {
for (Map.Entry<String, List<String>> param : params.entrySet()) {
String key = param.getKey();
List<String> value = param.getValue();
if (value != null && !value.isEmpty()) {
params.put(key, value.stream().filter(v -> !StringUtils.isBlank(v)).
map(v -> v.replaceAll("[{}]", "")).collect(Collectors.toList()));
}
}
}
}
}
2 changes: 1 addition & 1 deletion para-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
<dependency>
<groupId>com.onelogin</groupId>
<artifactId>java-saml</artifactId>
<version>2.7.0</version>
<version>2.8.0</version>
</dependency>

<!-- CAFFEINE -->
Expand Down

0 comments on commit 1e5b638

Please sign in to comment.