Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions src/main/java/fr/wseduc/webutils/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import fr.wseduc.webutils.http.HttpMethod;
import fr.wseduc.webutils.http.Renders;
import fr.wseduc.webutils.http.TraceIdContextHandler;
import fr.wseduc.webutils.request.AccessLogger;
import fr.wseduc.webutils.request.AccessLoggerFactory;
import fr.wseduc.webutils.request.IAccessLogger;
import fr.wseduc.webutils.request.filter.SecurityHandler;
Expand All @@ -33,6 +32,7 @@
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.apache.commons.lang3.time.StopWatch;
import org.vertx.java.core.http.RouteMatcher;
Expand All @@ -44,8 +44,10 @@
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public abstract class Controller extends Renders {

Expand Down Expand Up @@ -78,7 +80,7 @@ public Controller(Vertx vertx, JsonObject config, RouteMatcher rm,
}

protected void init(Vertx vertx, JsonObject config, RouteMatcher rm,
Map<String, SecuredAction> securedActions)
Map<String, SecuredAction> securedActions)
{
super.init(vertx, config);
this.rm = rm;
Expand Down Expand Up @@ -452,6 +454,22 @@ private String addPathPrefix(String pattern) {
return pathPrefix + pattern.trim();
}

/**
* Take a json array of jsonObject, appy the mapper to enforce contract, then serialize the result back to jsonObject
* to be send on the event bus
* @param arr List of JsonObject from database
* @param mapper Mapper to convert / filter JsonObject to a specific T class
* @return JsonArray of serialized T on JsonObject
* @param <T>
*/
public static <T> JsonArray serializeForBus(JsonArray arr, Function<JsonObject, T> mapper) {
return new JsonArray(arr.stream()
.map(JsonObject.class::cast)
.map(mapper)
.map(JsonObject::mapFrom)
.collect(Collectors.toList()));
}

public void setAccessLogger(IAccessLogger accessLogger) {
this.accessLogger = accessLogger;
}
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/fr/wseduc/webutils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import fr.wseduc.webutils.eventbus.ResultMessage;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.Message;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
Expand All @@ -28,6 +30,7 @@
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.function.Consumer;

public class Utils {

Expand Down Expand Up @@ -199,4 +202,35 @@ public static Handler<AsyncResult<Message<JsonObject>>> handlerToAsyncHandler(Ha
};
}

/**
* Bridges a legacy callback-based service method (using {@link Either}) into a Vert.x {@link Future}.
* <p>
* Many service methods in this codebase accept a {@code Handler<Either<String, T>>} as their last
* argument, where a {@link Either.Left} signals failure (with an error message) and a
* {@link Either.Right} signals success (with the result value). This utility wraps such a call
* into a {@link Future} so it can be composed with other async operations.
*
* <pre>{@code
* // Given a service method:
* // void findUser(String id, Handler<Either<String, JsonObject>> handler)
*
* Utils.eitherToFuture(handler -> userService.findUser(userId, handler))
* .compose(user -> Utils.eitherToFuture(handler -> roleService.getRoles(user.getString("id"), handler)))
* .onSuccess(roles -> renderJson(request, roles))
* .onFailure(err -> renderError(request, err));
* }</pre>
*
* @param call a consumer that invokes the legacy service method, passing along the provided handler
* @param <T> the type of the success value
* @return a {@link Future} that completes with the right value on success, or fails with the left message on error
*/
public static <T> Future<T> eitherToFuture(Consumer<Handler<Either<String, T>>> call) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Est-ce que tu pourrais ajouter de la javadoc et peut-être aussi dedans un example de code ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Promise<T> promise = Promise.promise();
call.accept(res -> {
if (res.isRight()) promise.complete(res.right().getValue());
else promise.fail(res.left().getValue());
});
return promise.future();
}

}
3 changes: 1 addition & 2 deletions src/main/java/fr/wseduc/webutils/http/BaseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package fr.wseduc.webutils.http;

import fr.wseduc.webutils.Controller;
import fr.wseduc.webutils.Server;
import fr.wseduc.webutils.security.SecuredAction;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
Expand All @@ -37,7 +36,7 @@ public BaseController() {
this(null, null, null, null);
}

public void init(Vertx vertx, JsonObject config, RouteMatcher rm,
public void init(Vertx vertx, JsonObject config, RouteMatcher rm,
Map<String, SecuredAction> securedActions) {
super.init(vertx, config, rm, securedActions);
}
Expand Down