This question already has answers here:
REST-Endpoint: Async execution without return value
(2 answers)
Closed 2 years ago.
In one class I want to call a method, but not have to wait until the method finishes. Normally in a spring application I would use #Async, but what is the way to go about in a Quarkus application?
Beneath is a simple example to get started. In the 'StartWork' class the 'Work' gets started. (I left out the Work-interface, but you can see one of its implementations: WorkA). After calling 'work.do()' the startWork() method should proceed without waiting for the work.do() to finish.
#ApplicationScoped
public class WorkA implements Work {
public void do() {
System.out.println("Starting work A.");
try {
Thread.sleep(1000l);
System.out.println("Finished work A.");
} catch(InterruptedException ex) {
System.out.println("My work got interrupted.");
}
}
}
#ApplicationScoped
public class StartWork {
#Inject
Work work;
public void startWork() {
work.do();
System.out.println("I dont' care when and if the work finished, but it has started.");
}
}
Here is the same example, but now I've tried to use Mutiny:
#ApplicationScoped
public class WorkA implements Work {
public void do() {
Uni.createFrom().voidItem().invoke(Runnable -> {
System.out.println("Starting work A.");
try {
Thread.sleep(1000l);
System.out.println("Finished work A.");
} catch(InterruptedException ex) {
System.out.println("My work got interrupted.");
}
}
});
}
#ApplicationScoped
public class StartWork {
#Inject
Work work;
public void startWork() {
work.do();
System.out.println("I dont' care when and if the work finished, but it has started.");
}
}
When running this example I do not see the lines being printed. So I guess the anonymous runnable is not invoked?
Minimal reproducible product: https://gitlab.com/rmvanderspek/quarkus-multithreading
Kudo's to Turing85 for finding the answer.
As it turns out Quarkus works with an EventBus for asynchronous actions. A producer is created, but works lazily and thus won't be invoked until a consumer is subscribed to this producer.
A working example: https://gitlab.com/rmvanderspek/quarkus-multithreading
In short:
#ApplicationScoped
public class WorkA implements Work {
#Override
public void doWork() {
log.info("Do work");
Uni.createFrom()
.item(UUID::randomUUID)
.emitOn(Infrastructure.getDefaultWorkerPool())
.subscribe()
.with(this::worker, Throwable::printStackTrace);
}
private Uni<Void> worker(UUID uuid) {
log.info("Starting work: " + uuid);
try {
Thread.sleep((long) Math.random() * 1000);
} catch (InterruptedException ex) {
log.info("Could not finish work: " + uuid);
throw new RuntimeException(ex);
}
log.info("Finish work: {}.", uuid);
return Uni.createFrom().voidItem();
}
}
#ApplicationScoped
public class StartWork {
#Inject
Work work;
public void startWork() {
work.do();
System.out.println("I dont' care when and if the work finished, but it has started.");
}
}
Related
I have a use case where I have a set of items, DiagnosticRuns, that are submitted to my cluster. I want to process them serially (to avoid conflicts). I am trying to use a Hazelcast Queue protected by a Lock to make sure the items are processed one at a time. Hazelcast is running in embedded mode in my cluster. If I register an ItemListener with the Queue, is it safe to call take() on the Queue from within the itemAdded() method? For example:
#Component
public class DistributedQueueListener
{
public static final String DIAGNOSTICS_RUN_QUEUE_NAME = "diagnosticRun";
#Autowired
private HazelcastInstance hazelcast;
#Autowired
private ProductVersioningService productVersioningService;
private IQueue<DiagnosticRun> diagnosticRunQueue;
private ILock diagnosticRunLock;
private String diagnosticRunListenerId;
#PostConstruct
public void init()
{
diagnosticRunQueue = hazelcast.getQueue(DIAGNOSTICS_RUN_QUEUE_NAME);
diagnosticRunLock = hazelcast.getLock("diagnosticRunLock");
diagnosticRunListenerId = diagnosticRunQueue.addItemListener(new DiagnosticRunListener(), false);
}
#PreDestroy
public void stop()
{
diagnosticRunQueue.removeItemListener(diagnosticRunListenerId);
}
public class DiagnosticRunListener implements ItemListener<DiagnosticRun>
{
#Override
public void itemAdded(ItemEvent<diagnosticRun> item)
{
diagnosticRunLock.lock(5, TimeUnit.SECONDS);
try
{
DiagnosticRun diagnosticRun = diagnosticRunQueue.poll();
if(diagnosticRun != null)
{
productVersioningService.updateProductDeviceTable(diagnosticRun);
}
}
finally
{
diagnosticRunLock.unlock();
}
}
#Override
public void itemRemoved(ItemEvent<diagnosticRun> item)
{
}
}
}
I'm not sure whether it's threadsafe to call take() on the Queue from that location and thread.
If that is not allowed, I'll have to set up my own long-running loop to poll() the Queue. I'm not sure what's the best way to set up a long-running thread in a Spring Boot application. Assuming the method above does not work, would the below code be threadsafe? Or is there a better way to do this?
#Component
public class DistributedQueueListener
{
public static final String DIAGNOSTIC_RUN_QUEUE_NAME = "diagnosticRun";
#Autowired
private HazelcastInstance hazelcast;
#Autowired
private ProductVersioningService productVersioningService;
private IQueue<diagnosticRun> diagnosticRunQueue;
private ILock diagnosticRunLock;
private ExecutorService executorService;
#PostConstruct
public void init()
{
diagnosticRunQueue = hazelcast.getQueue(DIAGNOSTIC_RUN_QUEUE_NAME);
diagnosticRunLock = hazelcast.getLock("diagnosticRunLock");
executorService = Executors.newFixedThreadPool(1);
executorService.submit(() -> listenToDiagnosticRuns());
}
#PreDestroy
public void stop()
{
executorService.shutdown();
}
private void listenToDiagnosticRuns()
{
while(!executorService.isShutdown())
{
diagnosticRunLock.lock(5, TimeUnit.SECONDS);
try
{
DiagnosticRun diagnosticRun = diagnosticRunQueue.poll(1L, TimeUnit.SECONDS);
productVersioningService.updateProductDeviceTable(diagnosticRun);
}
catch(InterruptedException e)
{
logger.error("Interrupted polling diagnosticRun queue", e);
}
finally
{
diagnosticRunLock.unlock();
}
}
}
}
First I'll qualify that I'm not exactly an expert on which threads these are executed on and when so some may disagree but here're my thoughts on this so anyone please chime in as this looks to be an interesting case. Your first solution mixes the Hazelcast event threading with it's operation threading. In fact you're triggering three operations to be invoked as a result of the single event. If you put some arbitrary latency in your call to updateProcductDeviceTable, you'll see that eventually, it will slow down but resume up again after some time. This will cause your local event queue to pile up while operations are invoked. You could put everything you're doing in a separate thread which you can "wake" up on #itemAdded or if you can afford to have a bit of latency, do what you're doing on your second solution. I would, however, make a couple changes in
listenToDiagnosticsRuns() method:
private void listenToDiagnosticRuns()
{
while(!executorService.isShutdown())
{
if(diagnosticRunQueue.peek() != null)
{
diagnosticRunLock.lock(5, TimeUnit.SECONDS);
try
{
DiagnosticRun diagnosticRun = diagnosticRunQueue.poll(1L, TimeUnit.SECONDS);
if(diagnosticRun != null)
{
productVersioningService.updateProductDeviceTable(diagnosticRun);
}
}
catch(InterruptedException e)
{
logger.error("Interrupted polling diagnosticRun queue", e);
}
finally
{
diagnosticRunLock.unlock();
}
} // peek != null
else
{
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
//do nothing
}
}
}
}
The question of the day is: how to call controllers function from another thread. My application looks like this:
public class Server {
//(...)
public String setMsg(String string) {
msg.set(string+"\n");
mainScreenController.updateLog();
}
//(...)
while (true){
doThings();
}
}
public class MainScreenController {
//(...)
public void startServer(){
new Thread(server::start).start();
}
public void updateLog(){
Platform.runLater(()->{ testAreaLog.setText(testAreaLog.getText() + server.getMsg()); });
}
//(...)
}
I want to call updateLog() in the finally block, so every time server updates msg GUI adds this message to log window. My msg is
private volatile AtomicReference<String> msg = new AtomicReference<String>();
it works when i call updateLog(); in startServer(), it displays the first message Starting server as you may guessed, but calling another updateLog(); there returns null so I wanted to call it directly after getMsg() is used.
It's not really clear why you can't just do
public class MainScreenController {
//(...)
public void startServer(){
new Thread(server::start).start();
}
public void updateLog(String message){
Platform.runLater(()-> testAreaLog.appendText(message + "\n"));
}
//(...)
}
and
public class Server {
public void start() {
while (true){
doThings();
String newMessage = ... ;
mainScreenController.updateLog(newMessage);
doMoreThings();
}
}
}
This assumes something in your while loop is a blocking (or time-consuming) call, so that you are not flooding the UI thread with too many Platform.runLater() calls.
I am trying to implement a program where I want different Components to blink at different speeds. I am using threads. But its not working.
How can I implement this.
This is the void run function in the class that implements runnable
public void run()
{
try
{
while(true)
{
Thread.sleep(1000);
if(isVisible()==true)
{
setVisible(false);
}
else
{
setVisible(true);
}
repaint();
}
}
catch(InterruptedException e)
{
}
}
}
and this is the class (its in a paint component of the main JPanel)where I call the threads-
{
cars[i]=new Car(color, xLocation, yLocation, speed, type, i, widthController, heightController);
cars[i].setBounds(widthController+(xLocation*50)+10, heightController+(yLocation*50)+10, 30, 30);
add(cars[i]);
threads[i]=new Thread(cars[i]);
threads[i].start();
}
cars is an array of JComponents of which void run is part of.
Thanks
With Swing, all operations that affect visible components should be run on the AWT-EventQueue. This is a dedicated thread for Input/Output operations as well as drawing and component operations. My recommendation is to use a swing timer for your run operation. The repaint call you made will call the paintCompnent method on the AWT-EventQueue. However you're changing the state of visibility on a seperate thread. This means that by the time the repaint call is made, it's possible the state has already changed to the previous value.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
//Rest of code above...
//This will execute the timer every 500 milliseconds
Timer aTimer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent pE) {
aComponent.setVisible(!aComponent.isVisible());
}
});
aTimer.start();
Another option is that on each thread add this call:
//This should be added inside of your thread
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
aComponent.setVisible(!aComponent.isVisible());
}
});
Here's the answer I was alluding to in my comments:
public void run()
{
try
{
while(true)
{
Thread.sleep(1000);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setVisible(!isVisible());
}
}
});
}
catch(InterruptedException e)
{
}
interface IExecutor
{
void Execute();
}
class Executor2<T> where T : IExecutor
{
public void Execute()
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
}
It was a question at an interview. They told me that sometimes this code falls (causes exceptions) and there are at least 3 reasons that could cause the problems. It's unknown what exceptions were there. But the method Execute was created good, its implementation has no fault.
Does anybody have a suggestion about that?
Edit: There are at least 3 reasons that could cause the problems. What are these reasons?
On the face of it I can see a few issues.
The code doesn't compile, but I can ignore that and make it compile.
The code doesn't do what you think it does.
To explain 2: you specify a type T at the class definition with a constraint on IExecutor, but you then define another type T at the method level without a constraint. This doesn't compile.
If I fix this and remove the <T> definition from the method I can see a number of reasons for it failing without much warning:
ex is null.
Type T doesn't have a public parameterless constructor defined.
Perhaps it cannot load the DLL containing T.
As spotted by Jakub:
T could be an interface (no constructor).
T could be an abstract class, these don't allow instances to be created directly.
The first can be guarded against using a null check if (ex != null) and the second can be guarded against using another generic constraint new():
class Executor2<T> where T : IExecutor, new()
{
}
Obviously you could also amend your code to including exception logging. This might be useful in figuring out what the actual problems are instead of just stabbing in the dark:
public void Execute<T>()
{
try
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
catch (Exception ex)
{
Log(ex); // Mystical logging framework.
throw;
}
}
This is the only answer I can cobble together considering I didn't understand the question.
If I were asked this in an interview I'd likely say I couldn't name all 3, but I'd know how to change the code to be more maintainable and tell me what was wrong. Then I'd likely walk for asking pointless interview questions.
T may be an interface or abstract class - and you cannot create instances of them, or T doesn't have a parameterless constructor.
Also, var ex = (T)Activator.CreateInstance(typeof(T)); could be rewritten as var ex = Activator.CreateInstance<T>();
Is it assumed that there is no fault in T's design? By which I mean, if T defines a static constructor which does Bad Stuff, type initialisation for T will fail giving a different exception to that which would occur if it did not have a parameterless constructor.
For that matter, if T defines a parameterless constructor which will fail then it's also broken.
Also, if the type has a private constructor you will get an error. Or if the type inherits from a type which will cause a TypeInitialisationException
[Edit]
Try this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try {
new Executor2<IExecutor>().Execute();
}
catch { Console.WriteLine("Failed IExecutor"); }
try { new Executor2<AbstractExecutorWithImpl>().Execute(); }
catch { Console.WriteLine("Failed AbstractExecutorWithImpl"); }
try { new Executor2<AbstractExecutorWithNoImpl>().Execute(); }
catch { Console.WriteLine("Failed AbstractExecutorWithNoImpl"); }
try { new Executor2<ConcreteExecutor>().Execute(); }
catch { Console.WriteLine("Failed ConcreteExecutor"); }
try { new Executor2<DerivedExecutor>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutor"); }
try { new Executor2<DerivedExecutorWithBadConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithBadConstr"); }
try { new Executor2<DerivedExecutorWithPrivateConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithPrivateConstr"); }
try { new Executor2<DerivedExecutorWithPublicBadConstr>().Execute(); }
catch { Console.WriteLine("Failed DerivedExecutorWithPublicBadConstr"); }
Console.ReadLine();
}
}
interface IExecutor
{
void Execute();
}
abstract class AbstractExecutorWithImpl : IExecutor
{
public void Execute()
{
Console.Write("Executing AbstractExecutorWithImpl ");
}
}
abstract class AbstractExecutorWithNoImpl : IExecutor
{
public abstract void Execute();
}
class ConcreteExecutor : IExecutor
{
public void Execute()
{
Console.WriteLine("Executing ConcreteExecutor");
}
}
class DerivedExecutor : AbstractExecutorWithNoImpl
{
public override void Execute()
{
Console.WriteLine("Executing DerivedExecutor");
}
}
class DerivedExecutorWithBadConstr : IExecutor
{
static DerivedExecutorWithBadConstr() { throw new Exception("Static initialisation Exception"); }
public void Execute()
{
Console.WriteLine("Executing DerivedExecutorWithBadConstr");
}
}
class DerivedExecutorWithPrivateConstr : DerivedExecutor
{
private DerivedExecutorWithPrivateConstr() { }
}
class DerivedExecutorWithPublicBadConstr : DerivedExecutorWithBadConstr
{
public DerivedExecutorWithPublicBadConstr() : base() { }
}
class Executor2<T> where T : IExecutor
{
public void Execute()
{
var ex = (T)Activator.CreateInstance(typeof(T));
ex.Execute();
}
}
}
I'm trying to intercept the method persist and update of javax.persistence.EntityManager in a Seam 3 project.
In a previous version (Seam 2) of the micro-framework I'm trying to make, I did this using an implementation of org.hibernate.Interceptor and declaring it in the persistence.xml.
But I want something more "CDI-like" now we are in a JEE6 environment.
I want that just before entering in a EntityManager.persist call, an event #BeforeTrackablePersist is thrown. The same way, I want an event #BeforeTrackableUpdate to be thrown before entering in a EntityManager.merge call. Trackable is an interface which some of my Entitys could implement in order to be intercepted before persist or merge.
I'm using Seam 3 (3.1.0.Beta3) Extended Persistence Manager :
public class EntityManagerHandler {
#SuppressWarnings("unused")
#ExtensionManaged
#Produces
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
}
So I've made a javax.enterprise.inject.spi.Extension, and tryied many ways to do that :
public class TrackableExtension implements Extension {
#Inject #BeforeTrackablePersisted
private Event<Trackable> beforeTrackablePersistedEvent;
#Inject #BeforeTrackableMerged
private Event<Trackable> beforeTrackableMergedEvent;
#SuppressWarnings("unchecked")
public void processEntityManagerTarget(#Observes final ProcessInjectionTarget<EntityManager> event) {
final InjectionTarget<EntityManager> injectionTarget = event.getInjectionTarget();
final InjectionTarget<EntityManager> injectionTargetProxy = (InjectionTarget<EntityManager>) Proxy.newProxyInstance(event.getClass().getClassLoader(), new Class[] {InjectionTarget.class}, new InvocationHandler() {
#Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if ("produce".equals(method.getName())) {
final CreationalContext<EntityManager> ctx = (CreationalContext<EntityManager>) args[0];
final EntityManager entityManager = decorateEntityManager(injectionTarget, ctx);
return entityManager;
} else {
return method.invoke(injectionTarget, args);
}
}
});
event.setInjectionTarget(injectionTargetProxy);
}
public void processEntityManagerType(#Observes final ProcessAnnotatedType<EntityManager> event) {
final AnnotatedType<EntityManager> type = event.getAnnotatedType();
final AnnotatedTypeBuilder<EntityManager> builder = new AnnotatedTypeBuilder<EntityManager>().readFromType(type);
for (final AnnotatedMethod<? super EntityManager> method : type.getMethods()) {
final String name = method.getJavaMember().getName();
if (StringUtils.equals(name, "persist") || StringUtils.equals(name, "merge")) {
builder.addToMethod(method, TrackableInterceptorBindingLiteral.INSTANCE);
}
}
event.setAnnotatedType(builder.create());
}
public void processEntityManagerBean(#Observes final ProcessBean<EntityManager> event) {
final AnnotatedType<EntityManager> annotatedType = (AnnotatedType<EntityManager>)event.getAnnotated();
// not even called
}
public void processEntityManager(#Observes final ProcessProducer<?, EntityManager> processProducer) {
processProducer.setProducer(decorate(processProducer.getProducer()));
}
private Producer<EntityManager> decorate(final Producer<EntityManager> producer) {
return new Producer<EntityManager>() {
#Override
public EntityManager produce(final CreationalContext<EntityManager> ctx) {
return decorateEntityManager(producer, ctx);
}
#Override
public Set<InjectionPoint> getInjectionPoints() {
return producer.getInjectionPoints();
}
#Override
public void dispose(final EntityManager instance) {
producer.dispose(instance);
}
};
}
private EntityManager decorateEntityManager(final Producer<EntityManager> producer, final CreationalContext<EntityManager> ctx) {
final EntityManager entityManager = producer.produce(ctx);
return (EntityManager) Proxy.newProxyInstance(entityManager.getClass().getClassLoader(), new Class[] {EntityManager.class}, new InvocationHandler() {
#Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
final String methodName = method.getName();
if (StringUtils.equals(methodName, "persist")) {
fireEventIfTrackable(beforeTrackablePersistedEvent, args[0]);
} else if (StringUtils.equals(methodName, "merge")) {
fireEventIfTrackable(beforeTrackableMergedEvent, args[0]);
}
return method.invoke(entityManager, args);
}
private void fireEventIfTrackable(final Event<Trackable> event, final Object entity) {
if (entity instanceof Trackable) {
event.fire(Reflections.<Trackable>cast(entity));
}
}
});
}
}
In all those observer methods, only the second one (processEntityManagerType(#Observes ProcessAnnotatedType<EntityManager>)) is called ! And even with that binding addition to methods persist and merge, my Interceptor is never called (I've of course enabled it with the correct lines in beans.xml, and enabled my extension with the services/javax.enterprise.inject.spi.Extension file).
Something I've thought simple with CDI seems to be actually really hard at last... or perhaps Seam 3 does something which prevent this code from executing correctly...
Does someone know how to handle that ?
I think you're making this a little harder than what it needs to be. Firstly though, JPA and CDI integration isn't very good in Java EE 6, we're very much hoping that changes in Java EE 7 and JPA 2.1.
What you'll want to do is create your own producer for the EntityManager that will delegate to an actual instance of an EntityManager, but also fire your own events when you call the methods you're interested in. Take a look at the Seam Persistence source to see one way this can be done.
As finally my little patch for Seam Persistence was applied in SEAMPERSIST-75, it will be possible in theory to do that by extending org.jboss.seam.persistence.HibernatePersistenceProvider and override the method proxyEntityManager(EntityManager).