Task execution library derived from JXP's execution framework.
This library provides task execution and synchronisation applying certain reusable task execution modes. For example, one could create a mode that manages a transaction when executing a task.
repositories {
maven { url "https://jitpack.io" }
}
dependencies {
implementation "com.github.robinfriedli:exec:1.4"
}
<dependency>
<groupId>com.github.robinfriedli</groupId>
<artifactId>exec</artifactId>
<version>1.4</version>
<type>pom</type>
</dependency>
<repository>
<name>jitpack.io</name>
<url>https://jitpack.io</url>
</repository>
Also, make sure you are using the Kotlin JVM plugin and Kotlin is set up. Refer to the guide for Gradle and Maven.
Java example:
publicvoidtestInvokeCallable() throwsException {
Invokerinvoker = Invoker.newInstance();
Modemode = Mode.create()
.with(newAbstractNestedModeWrapper() {
@SuppressWarnings("unchecked")
@Overridepublic <T> Callable<T> wrap(Callable<T> callable) {
return () -> {
inti = (Integer) callable.call();
return (T) (Object) (i + 5);
};
}
})
.with(newAbstractNestedModeWrapper() {
@SuppressWarnings("unchecked")
@Overridepublic <T> Callable<T> wrap(Callable<T> callable) {
return () -> {
inti = (Integer) callable.call();
return (T) (Object) (i * 2);
};
}
});
inti = invoker.invoke(mode, () -> 3);
assertEquals(i, 11);
}Equivalent Kotlin example
funtestInvokeCallable() {
val invoker = newInstance()
val mode = create()
.with(object:AbstractNestedModeWrapper() {
overridefun <T> wrap(callable:Callable<T>): Callable<T> {
returnCallable {
val i = callable.call() asInt
(i +5) asT
}
}
})
.with(object:AbstractNestedModeWrapper() {
overridefun <T> wrap(callable:Callable<T>): Callable<T> {
returnCallable {
val i = callable.call() asInt
(i *2) asT
}
}
})
val i = invoker.invoke<Int>(mode) { 3 }
assertEquals(i, 11)
}Or check out JXP for examples in production. E.g.:
From AbstractContext:
@Overridepublic <E> Einvoke(booleancommit, booleaninstantApply, Callable<E> task) {
Modemode = Mode.create()
.with(newMutexSyncMode<>(getMutexKey(), GLOBAL_CONTEXT_SYNC))
.with(getTransactionMode(instantApply, false).shouldCommit(commit));
returninvoke(mode, task);
}
@Overridepublic <E> Einvoke(Modemode, Callable<E> task) {
Invokerinvoker = Invoker.newInstance();
returninvoker.invoke(mode, task, e -> newPersistException("Exception in task", e));
}From AbstractTransactionalMode:
@NotNull@Overridepublic <E> Callable<E> wrap(@NotNullCallable<E> callable) {
return () -> {
activeTransaction = context.getTransaction();
newTransaction = getTransaction();
oldTransaction = null;
if (activeTransaction != null) {
switchTx();
} else {
openTx();
}
EreturnValue;
try {
returnValue = callable.call();
activeTransaction.internal().apply();
if (!activeTransaction.isApplyOnly()) {
if (shouldCommit) {
activeTransaction.internal().commit(writeToFile);
} else {
context.getUncommittedTransactions().add(activeTransaction);
}
}
} catch (Exceptione) {
try {
activeTransaction.internal().assertRollback();
} catch (Exceptione1) {
Loggerlogger = context.getBackend().getLogger();
logger.error("Exception while rolling back changes", e1);
}
thrownewPersistException(e.getClass().getSimpleName() + " thrown while running task. Closing transaction.", e);
} finally {
List<QueuedTask<?>> queuedTasks = activeTransaction.getQueuedTasks();
booleanfailed = activeTransaction.failed();
closeTx();
queuedTasks.forEach(t -> {
if (failed && t.isCancelOnFailure()) {
t.cancel(false);
} else {
t.runLoggingErrors();
}
});
}
returnreturnValue;
};
}This is an example of how Modes can be used to manage a Transaction when executing a task.