ph.com.nightowlstudios.resource.Resource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of edge Show documentation
Show all versions of edge Show documentation
A simple library for building REST API using Vertx.
package ph.com.nightowlstudios.resource;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ph.com.nightowlstudios.auth.BasicAuthentication;
import ph.com.nightowlstudios.auth.UserRole;
import ph.com.nightowlstudios.dto.DTO;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
/**
* @author Joseph Harvey Angeles - @yev
* @since 9/12/20
*/
public abstract class Resource {
private final Logger logger;
private final Router router;
public Resource(Router router) {
this.router = router;
this.logger = LoggerFactory.getLogger(this.getClass());
logger().info("Loading {}...", this.getClass().getCanonicalName());
init();
setUp();
routes();
}
/**
* For Resource
subclasses. Use when initializing
* and setting up new Resource variants.
*/
void init() {
}
/**
* Executed before routes declaration. Setup services and any resource needed by
* route handlers inside this hook.
*/
protected void setUp() {
}
/**
* Define routes and their route handlers.
*/
protected abstract void routes();
protected Logger logger() {
return this.logger;
}
protected Router router() {
return this.router;
}
protected String getPathParam(RoutingContext ctx, String param) {
return getPathParam(ctx, param, StringUtils.EMPTY);
}
protected String getPathParam(RoutingContext ctx, String param, String def) {
return Optional.ofNullable(ctx.pathParam(param)).orElse(def);
}
protected String getRequestParam(RoutingContext ctx, String param) {
return getRequestParam(ctx, param, StringUtils.EMPTY);
}
protected String getRequestParam(RoutingContext ctx, String param, String def) {
return Optional.ofNullable(ctx.request().getParam(param)).orElse(def);
}
protected T getAuthClaim(RoutingContext ctx, String key) {
return ctx.user().get(key);
}
protected T getAuthClaim(RoutingContext ctx, String key, T def) {
return Optional.ofNullable(ctx.user().get(key)).orElse(def);
}
protected Route route(HttpMethod method, String path) {
return router().route(method, path);
}
protected Route protectedRoute(HttpMethod method, String path) {
return route(method, path).handler(BasicAuthentication.getInstance().createAuthNHandler());
}
protected Route protectedRoute(HttpMethod method, String path, UserRole role) {
return router.route(method, path)
.handler(BasicAuthentication.getInstance().createAuthNHandler())
.handler(BasicAuthentication.getInstance().createAuthZHandler(role));
}
protected Route get(String path) {
return protectedRoute(HttpMethod.GET, path);
}
protected Route get(String path, UserRole role) {
return protectedRoute(HttpMethod.GET, path, role);
}
protected Route put(String path) {
return protectedRoute(HttpMethod.PUT, path);
}
protected Route put(String path, UserRole role) {
return protectedRoute(HttpMethod.PUT, path, role);
}
protected Route post(String path) {
return protectedRoute(HttpMethod.POST, path);
}
protected Route post(String path, UserRole role) {
return protectedRoute(HttpMethod.POST, path, role);
}
protected Route delete(String path) {
return protectedRoute(HttpMethod.DELETE, path);
}
protected Route delete(String path, UserRole role) {
return protectedRoute(HttpMethod.DELETE, path, role);
}
protected void endContext(RoutingContext ctx, HttpResponseStatus status, String message) {
ctx.response().setStatusCode(status.code()).end(message);
}
protected void endContext(RoutingContext ctx, HttpResponseStatus status) {
ctx.response().setStatusCode(status.code()).end(status.reasonPhrase());
}
protected void endContext(RoutingContext ctx, Object body) {
ctx.response().setStatusCode(HttpResponseStatus.OK.code()).end(JsonObject.mapFrom(body).encode());
}
protected void endContext(RoutingContext ctx, JsonObject body) {
ctx.response().setStatusCode(HttpResponseStatus.OK.code()).end(body.encode());
}
protected void endContext(RoutingContext ctx, JsonArray body) {
ctx.response().setStatusCode(HttpResponseStatus.OK.code()).end(body.encode());
}
protected void endContext(RoutingContext ctx, List list) {
JsonArray body = new JsonArray();
list.forEach(dto -> body.add(dto.toJson()));
endContext(ctx, body);
}
protected void on(RoutingContext ctx, Future action, Handler onSuccess) {
action.onSuccess(onSuccess).onFailure(error -> this.failureHandler(ctx, error));
}
protected Future on(RoutingContext ctx, Future action) {
return action.onFailure(error -> this.failureHandler(ctx, error));
}
protected void failureHandler(RoutingContext ctx, Throwable cause) {
if (cause instanceof IllegalArgumentException) {
ctx.fail(HttpResponseStatus.BAD_REQUEST.code(), cause);
return;
}
if (cause instanceof NullPointerException) {
ctx.fail(HttpResponseStatus.NOT_FOUND.code(), cause);
return;
}
if (cause instanceof IllegalAccessException ||
cause instanceof IllegalAccessError ||
cause instanceof SecurityException) {
ctx.fail(HttpResponseStatus.FORBIDDEN.code(), cause);
return;
}
ctx.fail(cause.getCause());
}
/**
* Applies a Future execute
function on each element of list
.
* The Future
completes until all of the functions are executed.
*
* @param list the list to apply an execute
function from.
* @param execute the function to apply on each element
* @param the type of elements that list
holds
* @param the resulting type after execute
has been applied
* @return the same list
for fluent use.
*/
protected Future> onEach(List list, Function> execute) {
List futures = new ArrayList<>();
list.forEach(item -> futures.add(execute.apply(item)));
Promise> promise = Promise.promise();
CompositeFuture
.all(futures)
.onSuccess(ignore -> promise.complete(list))
.onFailure(promise::fail);
return promise.future();
}
}