Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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. */ package org.apache.eagle.common.rest; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.eagle.common.function.ThrowableConsumer; import org.apache.eagle.common.function.ThrowableSupplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.function.Supplier; @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public class RESTResponse<T> { private static final Logger LOGGER = LoggerFactory.getLogger(RESTResponse.class); @JsonProperty private boolean success = false; @JsonProperty private String message; @JsonProperty private String exception; @JsonProperty private T data; public RESTResponse() { } public RESTResponse(Throwable throwable) { if (throwable.getMessage() == null || throwable.getMessage().isEmpty()) { this.setMessage(throwable.getMessage()); } else { this.setMessage(ExceptionUtils.getMessage(throwable)); } this.setException(ExceptionUtils.getStackTrace(throwable)); } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public static <E> RestResponseBuilder<E> builder() { return new RestResponseBuilder<>(); } public static <E> RestResponseBuilder<E> of(E data) { return RESTResponse.<E>builder().data(data); } public static <E> RestResponseBuilder<E> of(Consumer<RestResponseBuilder<E>> func) { return RESTResponse.<E>builder().of(func); } public static <E> RestResponseBuilder<E> of(Supplier<E> func) { return RESTResponse.<E>builder().of(func); } public static <E> RestResponseBuilder<E> async(ThrowableSupplier<E, Exception> func) { return RESTResponse.<E>builder().async(func); } public static <E> RestResponseBuilder<E> async(ThrowableConsumer<RestResponseBuilder<E>, Exception> func) { return RESTResponse.<E>builder().async(func); } public String getException() { return exception; } public void setThrowable(Throwable exception) { this.setException(ExceptionUtils.getStackTrace(exception)); } public void setException(String exception) { this.exception = exception; } public static class RestResponseBuilder<E> { private RESTResponse current = new RESTResponse(); private Response.Status status = Response.Status.OK; private CompletableFuture future = null; public RestResponseBuilder<E> success(boolean success) { this.current.setSuccess(success); return this; } public RestResponseBuilder<E> status(Response.Status status) { this.status = status; return this; } public RestResponseBuilder<E> status(boolean success, Response.Status status) { this.success(success); this.status(status); return this; } public RestResponseBuilder<E> message(String message) { this.current.setMessage(message); return this; } public RestResponseBuilder<E> data(E data) { this.current.setData(data); return this; } public RestResponseBuilder<E> exception(Throwable exception) { this.current.setThrowable(exception); if (this.current.getMessage() == null) { if (exception.getMessage() == null || exception.getMessage().isEmpty()) { this.current.setMessage(ExceptionUtils.getMessage(exception)); } else { this.current.setMessage(exception.getMessage()); } } return this; } public RestResponseBuilder<E> of(Consumer<RestResponseBuilder<E>> func) { try { this.success(true).status(Response.Status.OK); func.accept(this); } catch (Exception ex) { LOGGER.error("Exception: " + ex.getMessage(), ex); this.success(false).data(null).status(Response.Status.BAD_REQUEST).exception(ex); raiseWebAppException(ex); } return this; } public RestResponseBuilder<E> of(Supplier<E> func) { try { this.success(true).status(Response.Status.OK).data(func.get()); } catch (Throwable ex) { LOGGER.error("Exception: " + ex.getMessage(), ex); this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); raiseWebAppException(ex); } return this; } public RestResponseBuilder<E> async(ThrowableSupplier<E, Exception> func) { CompletableFuture future = CompletableFuture.runAsync(() -> { try { this.status(Response.Status.OK).success(true).data(func.get()); } catch (Throwable e) { LOGGER.error("Exception: " + e.getMessage(), e); this.success(false).status(Response.Status.BAD_REQUEST).exception(e); raiseWebAppException(e); } }); runAsync(future); return this; } public RestResponseBuilder<E> async(ThrowableConsumer<RestResponseBuilder<E>, Exception> func) { CompletableFuture future = CompletableFuture.runAsync(() -> { try { func.accept(this); this.success(true); } catch (Throwable ex) { LOGGER.error("Exception: " + ex.getMessage(), ex); this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); raiseWebAppException(ex); } }); runAsync(future); return this; } private void runAsync(Future future) { try { future.get(); } catch (InterruptedException ex) { LOGGER.error("InterruptedException: " + ex.getMessage(), ex); Thread.currentThread().interrupt(); future.cancel(true); this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); raiseWebAppException(ex); } catch (ExecutionException ex) { LOGGER.error("ExecutionException: " + ex.getMessage(), ex); this.success(false).status(Response.Status.BAD_REQUEST).exception(ex.getCause()); raiseWebAppException(ex); } } private void raiseWebAppException(Throwable ex) { throw new WebApplicationException(ex, Response.status(this.status).entity(this.current).build()); } public RestResponseBuilder<E> then(ThrowableConsumer<RestResponseBuilder<E>, Exception> func) { try { func.accept(this); } catch (Throwable ex) { LOGGER.error("Exception: " + ex.getMessage(), ex); this.success(false).status(Response.Status.BAD_REQUEST).exception(ex); raiseWebAppException(ex); } return this; } public RESTResponse<E> get() { return current; } public Response build() { return Response.status(status).entity(current).type(MediaType.APPLICATION_JSON).build(); } } }