Task chaining in JavaFX8: Start next Task after onSucceeded finished on previous task - concurrency

I'm rather new to JavaFX8 and facing the following problem. In my current App, which is for document processing/editing, I have two rather expensive tasks. Opening a document and saving a document.
My app has the buttons "import next", "export current" and "export current and import next". For Import and Export, I have two Task of the following structure:
private class Export extends Task<Void> {
public Export() {
this.setOnRunning(event -> {
// do stuff (change cursor etc)
});
this.setOnFailed(event -> {
// do stuff, eg. show error box
});
this.setOnSucceeded(event -> {
// do stuff
});
}
#Override
protected Void call() throws Exception {
// do expensive stuff
return null;
}
}
I submit the task using the Executors.newSingleThreadExecutor();.
For the functionality "export current and import next", my goal is to submit the Export and Import tasks to the executor, but my Import tasks should only run if the export-task was sucessful and the EventHandler given in setOnSucceedded (whichs runs on the GUI thread) finished. If the export fails, it does not make any sense to load the next document because user interaction is needed. How can this be achieved?
First I tired to but the entire logic/error handling in the call method, but this does not work as I cannot change the GUI from this method (i.e. to show an error-box).
As workaround, I'm manually submitting the import-task on the last line of my setOnSucceeded in the export-task, but this is not very flexible, because I want to be sure this task exports only (without subsequent import)...

Don't call the handler property methods setOnXXX in your Task subclass constructor. These actually set a property on the task, so if you also call those methods from elsewhere you will replace the functionality you're implementing in the class itself, rather than add to it.
Instead, override the protected convenience methods:
public class Export extends Task<Void> {
#Override
protected void succeeded() {
super.succeeded();
// do stuff...
}
#Override
protected void running() {
super.running();
// do stuff...
}
#Override
protected void failed() {
super.failed();
// do stuff...
}
#Override
protected Void call() {
// do expensive stuff....
return null ;
}
}
Now you can safely use setOnXXX(...) externally to the Export class without breaking its functionality:
Export export = new Export();
export.setOnSucceeded(e -> {
Import import = new Import();
executor.submit(import);
});
executor.submit(export);
This puts the logic for chaining the tasks at the point where you actually create them, which would seem to be the correct place to do it.
Note that another way to provide multiple handlers for the change of state is to register listeners with the stateProperty():
Export export = new Export();
export.stateProperty().addListener((obs, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
// ...
}
});
From testing, it appears the order of execution of these different mechanisms is:
state listeners
the onSucceeded handler
the Task.succeeded method
All are executed on the FX Application Thread.
So if you want the code in the Task subclass to be executed before the handler added externally, do
public class Export extends Task<Void> {
public Export() {
stateProperty().addListener((obs, oldState, newState) -> {
if (newState == Worker.State.RUNNING) {
// do stuff
} else if (newState == Worker.State.SUCCEEDED) {
// do stuff
} else if (newState == Worker.State.FAILED) {
// do stuff
}
});
}
#Override
public Void call() {
// ...
}
}
Finally, you could implement the entire logic in your call method: if you need to interact with the UI you can wrap those calls in a Platform.runLater(() -> {});. However, separating the functionality into different tasks as you have done is probably cleaner anyway.

Related

Unknown thread spawns which ignores the filter chain and fails on async decorator

I am currently facing a strange issue I am not able to reproduce locally, but happens in AWS ECS regularly, letting the application crash or run slow.
We have a spring boot application which extracts the tenant from the incoming GraphQL request and sets the tenant to a ThreadLocal instance.
To support DataLoader from GraphQL Java kickstart we populate the tenant to each child thread which will be used by the graphql dataloader. The tenant is mandatory to specify the database schema.
The executor
#Bean
#Override
public Executor getAsyncExecutor() {
log.info("Configuring async executor for multi tenancy...");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(15);
executor.setThreadNamePrefix("tenant-child-executor-");
// Important part: Set the MultiTenancyTaskDecorator to populate current tenant to child thread
executor.setTaskDecorator(new MultiTenancyAsyncTaskDecorator());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
log.info("Executor configured successfully!");
executor.initialize();
return executor;
}
Task Decorator
#NonNull
#Override
public Runnable decorate(#NonNull Runnable runnable) {
if (Objects.isNull(CurrentTenantContext.getTenant())) {
log.warn("Current tenant is null while decorating a new thread!");
}
final TenantIdentifier parentThreadTenantIdentifier = Objects.isNull(CurrentTenantContext.getTenant()) ? TenantIdentifier.asSystem() : CurrentTenantContext.getTenant();
// Also need to get the MDC context map as it is bound to the current local thread
final Map<String, String> parentContextMap = MDC.getCopyOfContextMap();
final var requestAttributes = RequestContextHolder.getRequestAttributes();
return () -> {
try {
CurrentTenantContext.setTenant(TenantIdentifier.of(parentThreadTenantIdentifier.getTenantName()));
if (Objects.isNull(requestAttributes)) {
log.warn("RequestAttributes are not available!");
log.warn("Running on tenant: {}", parentThreadTenantIdentifier.getTenantName());
} else {
RequestContextHolder.setRequestAttributes(requestAttributes, true);
}
if (Objects.isNull(parentContextMap)) {
log.warn("Parent context map not available!");
log.warn("Running on tenant: {}", parentThreadTenantIdentifier.getTenantName());
} else {
MDC.setContextMap(parentContextMap);
}
runnable.run();
} finally {
// Will be executed after thread finished or on exception
RequestContextHolder.resetRequestAttributes();
CurrentTenantContext.clear();
MDC.clear();
}
};
}
Tenant Context
public class CurrentTenantContext {
private static final ThreadLocal<TenantIdentifier> currentTenant = new ThreadLocal<>();
private CurrentTenantContext() {
// Hide constructor to only provide static functionality
}
public static TenantIdentifier getTenant() {
return currentTenant.get();
}
public static String getTenantName() {
return getTenant().getTenantName();
}
public static void setTenant(TenantIdentifier tenant) {
currentTenant.set(tenant);
}
public static void clear() {
currentTenant.remove();
}
public static boolean isTenantSet() {
return Objects.nonNull(currentTenant.get());
}
}
Locally, this works like a charm. Even in a docker compose environment with limited resources (CPU and Mem) like in AWS. Even 100.000 requests (JMETER) everything works like expected.
On AWS we can easily let the application crash.
After one or two requests, containing some child objects to resolve by GraphQL, we see a thread spawning which seems to ignore or not go through the chain
Thread-110 | [sys ] | WARN | MultiTenancyAsyncTaskDecorator | Current tenant is null while decorating a new thread!
An interesting thing in this line is the name of the thread.
Each incoming request has the pattern http-nio-9100-exec-[N] and each child thread the pattern tenant-child-executor-[I] but this one has the pattern Thread-[Y].
Now I am wondering where this thread is coming from and why is it not reproducible locally.
I was able to find the solution to the problem.
I needed to change
private static final ThreadLocal<TenantIdentifier> currentTenant = new ThreadLocal<>();
to
private static final InheritableThreadLocal<TenantIdentifier> currentTenant = new InheritableThreadLocal<>();
But I don't know why it works with InheritableThreadLocal but not with ThreadLocal within the AWS environment.
Further, I wonder why this change was not necessary for local testing which works with both ways.
Maybe somebody can provide some ideas.

Akka: Can an actor of some class become an actor of a diferent class?

As a course project, I am trying to implement a (simulation) of the Raft protocol.
In this post, I will not use Raft terminology at all; instead, I will use a simplified one.
The protocol is run by a number of servers (for example, 5) which can be in three different states (A, B, C).
The servers inherit some state variables and behavior from a "base" kind, but they all also have many unique state variables and methods, and respond to different messages.
At some point of the protocol, a server in some state (for example, A) is required to become the other state (for example, B).
In other words, the server should:
Lose the state variables and methods of state A, acquire those of state B, but maintain the variables of the "base" kind.
Stop responding to messages destined for state A, start responding to messages destined for state B.
In Akka, Point 1 can be implemented using Receives and become().
Point 2 is needed because, for example, an actor of class B should not have access to state variables and methods of an actor of class A. This aims at separating concerns, and achieving a better code organization.
The issues I am facing in implementing these Point 2 are the following:
Right now, my implementation has only one actor, which contains both A and B state variables and methods.
The protocol I am trying to implement requires each server has to keep a reference to the others (i.e., the ActorRef of the others).
I can't simply spawn an actor in state B, transfer the values of the state variables of the "base" kind to it, and stop the old actor, because the newly spawned actor has a new ActorRef, and the other servers are in the dark about it, and they will continue sending messages using the old ActorRef (therefore, the new actor would not receive anything, and both parties time out).
A way to circumvent the issue is that the newly spawned actor "advertises" itself by sending a message to the other actors, including its old ActorRef.
However, again due to the protocol, the other servers may be temporarily not available (i.e., they are crashed), thus they might not receive and process the advertisement.
In the project, I must use extensions of AbstractActor, and not FSM (final state machines), and have to use Java.
Is there any Akka pattern or functionality that solves this use case? Thank you for any insight. Below is a simplified example.
public abstract class BaseActor extends AbstractActor {
protected int x = 0;
// some state variables and methods that make sense for both A and B
#Override
public Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("x", msg -> {
System.out.println(x);
x++;
})
.build();
}
}
public class A extends BaseActor {
protected int a = 10;
// many other state variables and methods that are own of A and do NOT make sense to B
#Override
public Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("a", msg -> {
System.out.println(a);
})
.matchEquals("change", msg -> {
// here I want A to become B, but maintain value of x
})
.build()
.orElse(super.createReceive());
}
}
public class B extends BaseActor {
protected int b = 20;
// many other state variables and methods that are own of B and do NOT make sense to A
#Override
public AbstractActor.Receive createReceive() {
return new ReceiveBuilder()
.matchEquals("b", msg -> {
System.out.println(b);
})
.matchEquals("change", msg -> {
// here I want B to become A, but maintain value of x
})
.build()
.orElse(super.createReceive());
}
}
public class Example {
public static void main(String[] args) {
var system = ActorSystem.create("example");
// actor has class A
var actor = system.actorOf(Props.create(A.class));
actor.tell("x", ActorRef.noSender()); // prints "0"
actor.tell("a", ActorRef.noSender()); // prints "10"
// here, the actor should become of class B,
// preserving the value of x, a variable of the "base" kind
actor.tell("change", ActorRef.noSender());
// actor has class B
actor.tell("x", ActorRef.noSender()); // should print "1"
actor.tell("b", ActorRef.noSender()); // should print "20"
}
}
This is a sketch implementation of how this could look like.
You model each of the states a separate class:
public class BaseState {
//base state fields/getters/setters
}
public class StateA {
BaseState baseState;
//state A fields/getters/setters
..
//factory methods
public static StateA fromBase(BaseState baseState) {...}
//if you need to go from StateB to StateA:
public static StateA fromStateB(StateB stateB) {...}
}
public class StateB {
BaseState baseState;
//state B fields/getters/setters
//factory methods
public static StateB fromBase(BaseState baseState) {...}
//if you need to go from StateA to StateB:
public static StateB fromStateA(StateA stateA) {...}
}
Then in your Actor you can have receive functions defined for both A and B and initialize it to A or B depending which one is the initial one
private static class MyActor extends AbstractActor
{
private AbstractActor.Receive receive4StateA(StateA stateA)
{
return new ReceiveBuilder()
.matchEquals("a", msg -> stateA.setSomeProperty(msg))
.matchEquals("changeToB", msg -> getContext().become(
receive4StateB(StateB.fromStateA(stateA))))
.build();
}
private AbstractActor.Receive receive4StateB(StateB stateB)
{
return new ReceiveBuilder()
.matchEquals("b", msg -> stateB.setSomeProperty(msg))
.matchEquals("changeToA", msg -> getContext().become(
receive4StateA(StateA.fromStateB(stateB))))
.build();
}
//assuming stateA is the initial state
#Override
public AbstractActor.Receive createReceive()
{
return receive4StateA(StateA.fromBase(new BaseState()));
}
}
Admittedly, my Java is rusty, but for example, this actor (or something very much like it...) will take strings until it receives a Lock message, after which it can be queried for how many distinct strings it received before being locked. So in the first Receive it gets, it tracks a Set of the strings received in order to dedupe. On a Lock it transitions to a second Receive which does not contain the Set (just an Integer field) and ignores String and Lock messages.
import akka.japi.JavaPartialFunction;
import java.util.HashSet;
import scala.runtime.BoxedUnit;
public class StringCounter extends AbstractActor {
public StringCounter() {}
public static class Lock {
private Lock() {}
public static final Lock INSTANCE = new Lock();
}
public static class Query {
private Query() {}
public static final Query INSTANCE = new Query();
}
/** The taking in Strings state */
public class AcceptingStrings extends JavaPartialFunction<Object, BoxedUnit> {
private HashSet<String> strings;
public AcceptingStrings() {
strings = new HashSet<String>();
}
public BoxedUnit apply(Object msg, boolean isCheck) {
if (msg instanceof String) {
if (!isCheck) {
strings.add(msg);
}
} else if (msg instanceof Lock) {
if (!isCheck) {
context().become(new Queryable(strings.size()), true);
}
} else {
// not handling any other message
throw noMatch();
}
return BoxedUnit.UNIT;
}
}
/** The responding to queries state */
public class Queryable extends JavaPartialFunction<Object, BoxedUnit> {
private Integer ans;
public Queryable(int answer) {
ans = Integer.valueOf(answer);
}
public BoxedUnit apply(Object msg, boolean isCheck) {
if (msg instanceof Query) {
if (!isCheck) {
getSender().tell(ans, getSelf());
}
} else {
// not handling any other message
throw noMatch();
}
return BoxedUnit.UNIT;
}
}
#Override
public Receive createReceive() {
return new Receive(new AcceptingStrings());
}
}
Note that in Queryable the set is long gone. One thing to be careful of is that the JavaPartialFunction will typically have apply called once with isCheck set to true and if that call doesn't throw the exception returned by noMatch(), it will be called again "for real" with isCheck set to false. You therefore need to be careful to not do anything but throw noMatch() or return in the case that isCheck is true.
This pattern is exceptionally similar to what happens in Akka Typed (especially in the functional API) under the hood.
Hopefully this illuminates this approach. There's a chance, of course, that your instructors will not accept this, though in that case it might be worth pushing back with the argument that:
in the actor model state and behavior are effectively the same thing
all the functionality is contained within an AbstractActor
I'd also not necessarily recommend using this approach normally in Java Akka code (the AbstractActor with state in its fields feels a lot more Java-y).

Fake internal calls of a SUT with FakeItEasy

I have a small C# class that handles printing.
I want to create (n)unit tests for this class, using
fakeItEasy. How can I fake the internal calls of this
class without faking the whole SUT ?
For example:
public class MyPrintHandler: IMyPrintHandler
{
public MyPrintHandler(ILogger<MyPrintHandler> logger)
{
}
// function I want to (unit test
public async Task<bool> PrintAsync(string ipaddress)
{
try
{
if (!string.IsNullOrWhiteSpace(ipaddress) )
{
return await StartPrint(ipaddress); // This cannot be called in a unit test, because it really start printing on a printer.
}
}
catch (Exception e)
{
}
return false;
}
private async Task<bool> StartPrint(string ipaddress)
{
// prints on the printer
}
[TestFixture]
public class MyPrintHandlerTests
{
[Test]
public void Succes_PrintAsync()
{
using (var fake = new AutoFake())
{
// Arrange - configure the fake
var sut = fake.Resolve<MyPrintHandler>();
// Act
await sut.PrintAsync("0.0.0.0"); // I want to prevent StartPrint() from being called..
}
}
}
How can I achieve this, or is this not possible at all?
Thanks in advance!
I would typically say that faking the SUT is an anti-pattern, to be avoided whenever possible, as it causes confusion. If you can refactor to introduce a collaborator that handles the StartPrinting method, I would strongly consider doing so. If this is not possible, you can try this, however
any method that you want to fake must be virtual or abstract, otherwise FakeItEasy cannot intercept it
any method that you want to fake must be public (or internal, if you can grant dynamic proxy access to production code's internals)
you would then fake the SUT, specifying that it should call the original (base) methods, and finally
explicitly override the behaviour for the method that you want to intercept

Spring Boot #Async not working

I expect that uploadImage method finishes once the file is uploaded to AWS, while scanFile method is still running asynchronously in the background;
#RestController
public class EmailController {
#PostMapping("/upload")
#ResponseStatus(HttpStatus.OK)
public void uploadImage(#RequestParam MultipartFile photos) {
awsAPIService.uploadImage(photos);
}
}
...
#Service
public class AwsAPIService {
public void uploadImage(MultipartFile file) {
try {
File fileToUpload = this.convertMultiPartToFile(file);
String fileName = this.generateFileName(file);
s3client.putObject(new PutObjectRequest(AWS_S3_QUARANTINE_BUCKET_NAME,fileName, fileToUpload));
fileToUpload.delete();
// start scan file
scanFile();
} ...
}
#Async
public void scanFile() {
log.info("Start scanning");
String queueUrl = sqs.getQueueUrl("bucket-antivirus").getQueueUrl();
List<Message> messages = sqs.receiveMessage(new ReceiveMessageRequest().withQueueUrl(queueUrl)
.withWaitTimeSeconds(20)).getMessages();
for (Message message : messages) {
// delete message
...
}
}
}
...
#EnableAsync
public class AppConfig {
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(200);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}
But this seems still running synchronously. What is the problem here?
By default #Async and other Spring method-level annotations like #Transactional work only on the external, bean-to-bean method call. An internal method call from uploadImage() to scanFile() in the same bean won't trigger the proxy implementing the Spring behaviour. As per Spring docs:
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct.
You could configure AspectJ to enable annotations on internal method calls, but it's usually easier to refactor the code.

Use Mockito to unit test a function which calls async function

I have a method which calls async function:
public class MyService {
...
public void uploadData() {
MyPool.getInstance().getThreadPool().execute(new Runnable() {
#Override
public void run() {
boolean suc = upload();
}
});
}
}
I want to unit test this function with Mockito, I tried:
MyPool mockMyPool = Mockito.mock(MyPool.class);
ThreadPool mockThreadPool = Mockito.mock(ThreadPool.class);
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
when(mockMyPool.getThreadPool()).thenReturn(mockThreadPool);
MyService service = new MyService();
// run the method under test
service.uploadData();
// set the runnableCaptor to hold your callback
verify(mockThreadPool).execute(runnableCaptor.capture());
But I got error:
org.mockito.exceptions.verification.WantedButNotInvoked:
Wanted but not invoked:
threadPool.execute(
<Capturing argument>
);
Why I got this error, how to unit test uploadData() function with Mockito?
OK, I figured out a way by myself, since MyPool is an singleton. I added one public function setInstance(mockedInstance) to pass the mocked instance to MyPool. Then, it works. I know it is a bit "dirty", but if you have better solution, please let me know. Thanks!
Aside from the DI approach you found of keeping a MyPool or ThreadPool field, you can also refactor a little bit to allow for dependency injection in your method:
public class MyService {
...
public void uploadData() {
uploadData(MyPool.getInstance().getThreadPool());
}
/** Receives an Executor for execution. Package-private for testing. */
void uploadData(Executor executor) {
executor.execute(new Runnable() {
#Override public void run() {
boolean suc = upload();
}
});
}
}
This might be even cleaner, because it reduces your ThreadPool to the level of abstraction you need (Executor), which means you're only mocking a one-method interface rather than your ThreadPool (which I assume is related to ThreadPoolService; otherwise, you can just accept a ThreadPool, too). Officially your uploadData() would be untested, but you could easily and thoroughly test uploadData(Executor) or uploadData(ThreadPool), which are the moving parts most likely to break.
The package-private trick does rely on your code and tests to be in the same package, though they could be in different source folders; alternatively, you could just make the ThreadPool-receiving call a part of your public API, which would allow for more flexibility later.