T
- The generic response type for this RestActionApplicationAction
, AuditableRestAction
, GuildAction
, MemberAction
, MessageAction
, MessageHistory.MessageRetrieveAction
, OrderAction
, PaginationAction
, RestAction.EmptyRestAction
public abstract class RestAction<T>
extends java.lang.Object
Methods that return an instance of RestAction require an additional step to complete the execution. Thus the user needs to append a follow-up method.
A default RestAction is issued with the following operations:
queue()
, queue(Consumer)
, queue(Consumer, Consumer)
submit()
, submit(boolean)
complete()
, complete(boolean)
submit()
.
queue()
operations.
queue()
and complete()
versions that
will be executed by a ScheduledExecutorService
after a
specified delay:
queueAfter(long, TimeUnit)
queue()
with default callback Consumers
to be executed after the specified delay
.
TimeUnit
is used to convert the provided long into a delay time.
queueAfter(1, TimeUnit.SECONDS);
queue()
1 second later.submitAfter(long, TimeUnit)
ScheduledFuture
which
can be joined into the current Thread using Future.get()
submitAfter(delay, unit).get()
will return
the value processed by a call to complete()
completeAfter(long, TimeUnit)
complete()
once finished sleeping.All of those operations provide overloads for optional parameters such as a custom
ScheduledExecutorService
instead of using the default
global JDA executor. Specifically queueAfter(long, TimeUnit)
has overloads
to provide a success and/or failure callback due to the returned ScheduledFuture
not being able to provide the response values of the queue()
callbacks.
queue()
operation which will
be executed on a rate limit worker thread in the background, without blocking your current thread:
MessageChannel
channel = event.getChannel();
RestAction<Message> action = channel.sendMessage("Hello World");
action.queue()
; // Execute the rest action asynchronously
Sometimes it is important to access the response value, possibly to modify it later.
Now we have two options to actually access the response value, either using an asynchronous
callback Consumer
or the (not recommended) complete()
which will block
the current thread until the response has been processed and joins with the current thread.
MessageChannel
channel = event.getChannel();
final long time = System.currentTimeMillis();
RestAction<Message> action = channel.sendMessage("Calculating Response Time...");
Consumer
<Message> callback = (message) -> {
Message m = message; // ^This is a lambda parameter!^
m.editMessage("Response Time: " + (System.currentTimeMillis() - time) + "ms").queue();
// End with queue() to not block the callback thread!
};
// You can also inline this with the queue parameter: action.queue(m -> m.editMessage(...).queue());
action.queue(callback)
;
MessageChannel
channel = event.getChannel();
final long time = System.currentTimeMillis();
RestAction<Message> action = channel.sendMessage("Calculating Response Time...");
Message message = action.complete()
;
message.editMessage("Response Time: " + (System.currentTimeMillis() - time) + "ms").queue();
// End with queue()
to not block the callback thread!
MessageChannel
channel = event.getChannel();
RestAction<Message> action = channel.sendMessage("This message will destroy itself in 5 seconds!");
action.queue((message) -> message.delete().queueAfter(5, TimeUnit.SECONDS)
);
Developer Note: It is generally a good practice to use asynchronous logic because blocking threads requires resources
which can be avoided by using callbacks over blocking operations:
queue(Consumer)
> complete()
There is a dedicated wiki page for RestActions that can be useful for learning.
Modifier and Type | Class | Description |
---|---|---|
static class |
RestAction.EmptyRestAction<T> |
Specialized form of
RestAction that is used to provide information that
has already been retrieved or generated so that another request does not need to be made to Discord. |
Modifier and Type | Field | Description |
---|---|---|
static java.util.function.Consumer<java.lang.Throwable> |
DEFAULT_FAILURE |
|
static java.util.function.Consumer |
DEFAULT_SUCCESS |
|
static org.slf4j.Logger |
LOG |
Constructor | Description |
---|---|
RestAction(JDA api,
net.dv8tion.jda.core.requests.Route.CompiledRoute route) |
Creates a new RestAction instance
|
RestAction(JDA api,
net.dv8tion.jda.core.requests.Route.CompiledRoute route,
okhttp3.RequestBody data) |
Creates a new RestAction instance
|
RestAction(JDA api,
net.dv8tion.jda.core.requests.Route.CompiledRoute route,
org.json.JSONObject data) |
Creates a new RestAction instance
|
Modifier and Type | Method | Description |
---|---|---|
T |
complete() |
Blocks the current Thread and awaits the completion
of an
submit() request. |
T |
complete(boolean shouldQueue) |
Blocks the current Thread and awaits the completion
of an
submit() request. |
T |
completeAfter(long delay,
java.util.concurrent.TimeUnit unit) |
Blocks the current Thread for the specified delay and calls
complete()
when delay has been reached. |
JDA |
getJDA() |
The current JDA instance
|
static boolean |
isPassContext() |
Whether RestActions will use
ContextException
automatically to keep track of the caller context. |
void |
queue() |
Submits a Request for execution.
|
void |
queue(java.util.function.Consumer<? super T> success) |
Submits a Request for execution.
|
void |
queue(java.util.function.Consumer<? super T> success,
java.util.function.Consumer<? super java.lang.Throwable> failure) |
Submits a Request for execution.
|
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit) |
Schedules a call to
queue() to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.concurrent.ScheduledExecutorService executor) |
Schedules a call to
queue() to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.function.Consumer<? super T> success) |
Schedules a call to
queue(java.util.function.Consumer) to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.function.Consumer<? super T> success,
java.util.concurrent.ScheduledExecutorService executor) |
Schedules a call to
queue(java.util.function.Consumer) to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.function.Consumer<? super T> success,
java.util.function.Consumer<? super java.lang.Throwable> failure) |
Schedules a call to
queue(java.util.function.Consumer, java.util.function.Consumer)
to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<?> |
queueAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.function.Consumer<? super T> success,
java.util.function.Consumer<? super java.lang.Throwable> failure,
java.util.concurrent.ScheduledExecutorService executor) |
Schedules a call to
queue(java.util.function.Consumer, java.util.function.Consumer)
to be executed after the specified delay . |
RestAction<T> |
setCheck(java.util.function.BooleanSupplier checks) |
Sets the last-second checks before finally executing the http request in the queue.
|
static void |
setPassContext(boolean enable) |
If enabled this will pass a
ContextException
as root-cause to all failure consumers. |
RequestFuture<T> |
submit() |
Submits a Request for execution and provides a
RequestFuture
representing its completion task. |
RequestFuture<T> |
submit(boolean shouldQueue) |
Submits a Request for execution and provides a
RequestFuture
representing its completion task. |
java.util.concurrent.ScheduledFuture<T> |
submitAfter(long delay,
java.util.concurrent.TimeUnit unit) |
Schedules a call to
complete() to be executed after the specified delay . |
java.util.concurrent.ScheduledFuture<T> |
submitAfter(long delay,
java.util.concurrent.TimeUnit unit,
java.util.concurrent.ScheduledExecutorService executor) |
Schedules a call to
complete() to be executed after the specified delay . |
public static final org.slf4j.Logger LOG
public static java.util.function.Consumer DEFAULT_SUCCESS
public static java.util.function.Consumer<java.lang.Throwable> DEFAULT_FAILURE
public RestAction(JDA api, net.dv8tion.jda.core.requests.Route.CompiledRoute route)
api
- The current JDA instanceroute
- The Route.CompiledRoute
to be used for rate limit handlingpublic RestAction(JDA api, net.dv8tion.jda.core.requests.Route.CompiledRoute route, okhttp3.RequestBody data)
api
- The current JDA instanceroute
- The Route.CompiledRoute
to be used for rate limit handlingdata
- The data that should be sent to the specified route. (can be null)public RestAction(JDA api, net.dv8tion.jda.core.requests.Route.CompiledRoute route, org.json.JSONObject data)
api
- The current JDA instanceroute
- The Route.CompiledRoute
to be used for rate limit handlingdata
- The data that should be sent to the specified route. (can be null)public static void setPassContext(boolean enable)
ContextException
as root-cause to all failure consumers.
Note that the DEFAULT_FAILURE
does not print a stack-trace at all unless specified!
It is recommended to pass a context consumer as failure manually using queue(success, ContextException.here(failure))
enable
- True, if context should be passed to all failure consumerspublic static boolean isPassContext()
ContextException
automatically to keep track of the caller context.
true
this can cause performance drops due to the creation of stack-traces on execution.setPassContext(boolean)
public JDA getJDA()
public RestAction<T> setCheck(java.util.function.BooleanSupplier checks)
false
or throws an exception this will not be finished.
When an exception is thrown from the supplier it will be provided to the failure callback.checks
- The checks to run before executing the request, or null
to run no checkspublic void queue()
DEFAULT_SUCCESS
and
DEFAULT_FAILURE
This method is asynchronous
public void queue(java.util.function.Consumer<? super T> success)
This method is asynchronous
success
- The success callback that will be called at a convenient time
for the API. (can be null)public void queue(java.util.function.Consumer<? super T> success, java.util.function.Consumer<? super java.lang.Throwable> failure)
This method is asynchronous
success
- The success callback that will be called at a convenient time
for the API. (can be null)failure
- The failure callback that will be called if the Request
encounters an exception at its execution point.public RequestFuture<T> submit()
RequestFuture
representing its completion task.
Note: The usage of CompletionStage.toCompletableFuture()
is not supported.
RequestFuture
representing the completion promisepublic RequestFuture<T> submit(boolean shouldQueue)
RequestFuture
representing its completion task.
Note: The usage of CompletionStage.toCompletableFuture()
is not supported.
shouldQueue
- Whether the Request should automatically handle rate limitations. (default true)RequestFuture
task representing the completion promisepublic T complete()
submit()
request.
This might throw RuntimeExceptions
java.lang.IllegalStateException
- If used within a queue(...)
callbackpublic T complete(boolean shouldQueue) throws RateLimitedException
submit()
request.
shouldQueue
- Whether this should automatically handle rate limitations (default true)java.lang.IllegalStateException
- If used within a queue(...)
callbackRateLimitedException
- If we were rate limited and the shouldQueue
is false.
Use complete()
to avoid this Exception.public java.util.concurrent.ScheduledFuture<T> submitAfter(long delay, java.util.concurrent.TimeUnit unit)
complete()
to be executed after the specified delay
.
ScheduledFuture
representing the task.
The returned Future will provide the return type of a complete()
operation when
received through the blocking call to Future.get()
!
The global JDA ScheduledExecutorService
is used for this operation.
You can change the core pool size for this Executor through JDABuilder.setCorePoolSize(int)
or you can provide your own Executor using submitAfter(long, java.util.concurrent.TimeUnit, java.util.concurrent.ScheduledExecutorService)
!
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
ScheduledFuture
representing the
delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit is null
public java.util.concurrent.ScheduledFuture<T> submitAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.concurrent.ScheduledExecutorService executor)
complete()
to be executed after the specified delay
.
ScheduledFuture
representing the task.
The returned Future will provide the return type of a complete()
operation when
received through the blocking call to Future.get()
!
The specified ScheduledExecutorService
is used for this operation.
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
executor
- The Non-null ScheduledExecutorService
that should be used
to schedule this operationScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit or ScheduledExecutorService is null
public T completeAfter(long delay, java.util.concurrent.TimeUnit unit)
complete()
when delay has been reached.
TimeUnit.sleep(long)
)delay
- The delay after which to execute a call to complete()
unit
- The TimeUnit
which should be used
(this will use unit.sleep(delay)
)java.lang.IllegalArgumentException
- If the specified TimeUnit
is null
java.lang.RuntimeException
- If the sleep operation is interruptedpublic java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit)
queue()
to be executed after the specified delay
.
ScheduledFuture
representing the task.
This operation gives no access to the response value.
Use queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer)
to access
the success consumer for queue(java.util.function.Consumer)
!
The global JDA ScheduledExecutorService
is used for this operation.
You can change the core pool size for this Executor through JDABuilder.setCorePoolSize(int)
or provide your own Executor with queueAfter(long, java.util.concurrent.TimeUnit, java.util.concurrent.ScheduledExecutorService)
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
ScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit is null
public java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.function.Consumer<? super T> success)
queue(java.util.function.Consumer)
to be executed after the specified delay
.
ScheduledFuture
representing the task.
This operation gives no access to the failure callback.
Use queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer, java.util.function.Consumer)
to access
the failure consumer for queue(java.util.function.Consumer, java.util.function.Consumer)
!
The global JDA ScheduledExecutorService
is used for this operation.
You can change the core pool size for this Executor through JDABuilder.setCorePoolSize(int)
or provide your own Executor with queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer, java.util.concurrent.ScheduledExecutorService)
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
success
- The success Consumer
that should be called
once the queue(java.util.function.Consumer)
operation completes successfully.ScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit is null
public java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.function.Consumer<? super T> success, java.util.function.Consumer<? super java.lang.Throwable> failure)
queue(java.util.function.Consumer, java.util.function.Consumer)
to be executed after the specified delay
.
ScheduledFuture
representing the task.
The global JDA ScheduledExecutorService
is used for this operation.
You can change the core pool size for this Executor through JDABuilder.setCorePoolSize(int)
or provide your own Executor with
queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer, java.util.function.Consumer, java.util.concurrent.ScheduledExecutorService)
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
success
- The success Consumer
that should be called
once the queue(java.util.function.Consumer, java.util.function.Consumer)
operation completes successfully.failure
- The failure Consumer
that should be called
in case of an error of the queue(java.util.function.Consumer, java.util.function.Consumer)
operation.ScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit is null
public java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.concurrent.ScheduledExecutorService executor)
queue()
to be executed after the specified delay
.
ScheduledFuture
representing the task.
This operation gives no access to the response value.
Use queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer)
to access
the success consumer for queue(java.util.function.Consumer)
!
The specified ScheduledExecutorService
is used for this operation.
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
executor
- The Non-null ScheduledExecutorService
that should be used
to schedule this operationScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit or ScheduledExecutorService is null
public java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.function.Consumer<? super T> success, java.util.concurrent.ScheduledExecutorService executor)
queue(java.util.function.Consumer)
to be executed after the specified delay
.
ScheduledFuture
representing the task.
This operation gives no access to the failure callback.
Use queueAfter(long, java.util.concurrent.TimeUnit, java.util.function.Consumer, java.util.function.Consumer)
to access
the failure consumer for queue(java.util.function.Consumer, java.util.function.Consumer)
!
The specified ScheduledExecutorService
is used for this operation.
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
success
- The success Consumer
that should be called
once the queue(java.util.function.Consumer)
operation completes successfully.executor
- The Non-null ScheduledExecutorService
that should be used
to schedule this operationScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit or ScheduledExecutorService is null
public java.util.concurrent.ScheduledFuture<?> queueAfter(long delay, java.util.concurrent.TimeUnit unit, java.util.function.Consumer<? super T> success, java.util.function.Consumer<? super java.lang.Throwable> failure, java.util.concurrent.ScheduledExecutorService executor)
queue(java.util.function.Consumer, java.util.function.Consumer)
to be executed after the specified delay
.
ScheduledFuture
representing the task.
The specified ScheduledExecutorService
is used for this operation.
delay
- The delay after which this computation should be executed, negative to execute immediatelyunit
- The TimeUnit
to convert the specified delay
success
- The success Consumer
that should be called
once the queue(java.util.function.Consumer, java.util.function.Consumer)
operation completes successfully.failure
- The failure Consumer
that should be called
in case of an error of the queue(java.util.function.Consumer, java.util.function.Consumer)
operation.executor
- The Non-null ScheduledExecutorService
that should be used
to schedule this operationScheduledFuture
representing the delayed operationjava.lang.IllegalArgumentException
- If the provided TimeUnit or ScheduledExecutorService is null