I'd like to use Publish/Subscribe in our XPages application, in Java, e.g. with Jedis. The application runs in a multi-user setting, and when one user makes some changes to a document we'd like to see those changes reflected on other users' screens. In theory that could be done using PubSub: when the change is applied, a "document modified" message is published and sent to the party or parties that subscribed to this message. The subscriber part I'd like to put in a Thread, so that the object that subscribed can react immediately when the message is received.
The scope for most objects that use subscribe is viewscope, they should be destroyed when viewscope is destroyed. But what happens when the object is abandoned and the subscriber thread is still there? For instance, how can I tell the JVM that the Thread can safely be stopped and scrapped by the garbage collector?
I have yet to try this, so I have no code that I can show, but here's the questions I have:
am I right, will the Thread continue to run even when viewscope is destroyed?
is there a way to create a garbage-collectable Thread?
or maybe: is there some API that does PubSub in the multi-threaded XPages environment?
I did something like this years ago. You can find a Pub/Sub example with Guava here: http://hasselba.ch/blog/?p=2158
I am not sure what you are planning with the subscriber thread
respectively what the benefit is for your idea.
But to answer your questions:
Yes, a thread continues to run until you stop it. You should use an ExecutorService because it helps you with management a lot. If you want to have it "automatically" removed, you just have to do a "shutdown", which then processes all jobs left and stops the ThreadPool.
If you need a server-wide Pub/Sub system, think about an OSGi Plugin which starts / stops automatically with the Domino HTTP task. All objects of this plugin can be used by any application.
Related
I'm trying to figure out a design pattern for scheduling events in a stateless Node back-end with multiple instances running simultaneously.
Use case example:
Create an message object with a publish date/time and save it to a database
Optionally update the publishing time or delete the object
When the publish time is reached, the message content is sent to a 3rd party API endpoint
Right now my best idea is to use bee-queue or bull to queue delayed jobs. It should be able to store the state and ensure that the job is executed only once. However, I feel like it might introduce a single point of failure, especially when maintaining state on Redis for months and then hoping that the future version of the queue library is still working.
Another option is a service worker that polls the database for upcoming events every n minutes, but this seems like a potential scaling issue down the line for multi-tenant SaaS.
Are there more robust design patterns for solving this?
Don't worry about redis breaking. It's pretty stable, and eventually you can decide to freeze the version.
If there are jobs that will be executed in the future I would suggest a database, like Mongo or Redis, with a disk-store. So you will survive a reboot, you don't have to reinvent the wheel, and already have a nice set of tools for scalability.
Developing with RAD Studio (Delphi) v10.2.1 (Tokyo release 1)
on Windows 10 "Creators Update" 64bit, but 32bit development.
The application is VCL with multiple background threads, each using Indy TidHTTP to fetch network resources. Synchronisation between the main thread and the background threads is implemented using message queues (PostThreadMessage calls). This is complicated enough that offering direct code here would be difficult and messy, so I'm starting with a verbal description.
What is supposed to happen: Open a file with links to external resources, this generates the HTTP requests and hands them out to background processing, then waits for incoming messages on the application message queue to say the resources have been downloaded. The application messages are matched in event code assigned to TApplication.OnMessage (which, I suspect, is where my problem lies).
It works. Everything goes smoothly most of the time. But if I open a TSaveDialog - even if I cancel the dialog rather than actually doing anything - then messages go missing off the application message queue.
Through a process of writing log messages (it's impossible to debug directly because that upsets the timing required to cause the problem) I've worked out that the background threads are indeed posting the messages (and getting a positive response from PostThreadMessage), but they never appear on my TApplication.OnMessage event code.
I've seen that some sneaky code in various libraries will set up their own PeekMessage/TranslateMessage/DispatchMessage loops, but not all of them remember to check if there is a TApplication.OnMessage event. But I've just searched through the VCL code and the dozen or so third party libraries I'm using and have not found any instances of this that would be getting hit in this case (as far as I can tell).
Note: I am using madExcept, Indy, FastReport, AddictSpell, SynEdit, VclStyleUtils (amongst a few other less known libraries)
Note 2: I am wondering if it might be related to with Delphi 10.2.1 or Windows 10 Creator's update, since I am also seeing some other odd behaviour (long delays with the first exception or first TOpenDialog - but only on some applications) that definitely didn't happen with 10.1 (I didn't use 10.2.0). ... But this may be (probably is) something different.
So my question is: What can I do about this?
Any suggestions on how to find/verify that there is some other code stealing the application messages? Anything else I should search for other than PeekMessage?
Is there another way to intercept the application message queue messages that might let me avoid the problem?
If no better options show themselves I may have to abandon using application thread messages and implement my own messaging/synchronisation system, which I'd rather not do after getting this other working very well the rest of the time.
You mention PostThreadMessage. Look no further. You can't use this unless you control all message loops that might pull off thread messages, and you don't. The modal file dialog message loop is out of your control. It will pull off thread messages intended for a different message loop, and not know what to do with them.
The solution is simple enough. Post messages to a window rather than a thread. That way all sane message loops (the modal file dialog's message loop is sane) will dispatch the messages to the intended recipient window.
In Delphi terms this would involve using AllocateHWnd or similar to create a hidden window to receive the messages.
Raymond Chen has covered this topic here: Why do messages posted by PostThreadMessage disappear?
Maybe it's a simple question, but I don't get it. When should I use concureency in my javafx project? Is it right that I should use for every task, which do some action in the background, the Concurrency API? So every action in my controller class, which has nothing to do with the UI should be executed in a single task?
I really don't get it how to use this right....
Whenever you have a task that may take sometime to get executed or there is a possibility of delayed response, you do not want your JavaFX Application thread to wait for it, because, as long as the JavaFX Application thread waits for the response, the UI becomes unresponsive.
A few examples where you may want to use a background thread is :
An I/O operation
A web service call
From the JavaFX documentation :
Implementing long-running tasks on the JavaFX Application thread inevitably makes an application UI unresponsive.
On the other hand, if you have minor calculations or some task which can be completed in a jiffy (I am not sure if this is the correct word, but I hope you can relate to what I want to say) and will not put the JavaFX Application thread on wait, you can execute them on the same thread.
So I have some Java code that takes some time to complete (about 2 minutes). Nothing I can do about that.
But I am wondering how best to approach this in the XPages UI so that the user may still have to wait but has more control/interaction while it is running (not just a spinning wheel).
So from what I can see I can do the following.
Java class called in XPage wrapped in a thread.
Java Agent called from XPage in a thread.
Java Agent called from an XPage, but waits for a document to be updated.
Eclipse plugin (For in the client) is activated. Not sure how it would talk back to XPage though (via document?).
Any other methods?
If you created the thread in the XPage, is that going to cause any problems at the server end? Will I have to avoid using Notes objects in the Java class?
I would suggest using the OSGi Tasklet service, a.k.a. DOTS. This approach allows Java tasks to be scheduled or bound to events, just like agents, but perform significantly more efficiently than agents. Perhaps most pertinent to your need is the additional ability to trigger DOTS tasks via the console, which would allow your XPages code to start the Java code merely by issuing a remote console command via the session object.
In addition, check out the technique used in the XSP Starter Kit to provide a serverScope variable. If your code is running in a DOTS task (or even an agent), it's running in a different Java application, so it can't talk directly to the standard scope variables. The serverScope approach would theoretically allow you to store objects that can be accessed from both the XPage and the triggered task. This could aid in using Mark's technique, as mentioned above by Per, to convey progress to the user while the task is running: you'd just be storing the progress information in serverScope instead of sessionScope.
A solution would be to have an agent react on saving new documents in the database instead of kicking of the agent in your application and use threads ( because threads can be very dangerous and could easily kill your http task )
Another thing you could look into is why the code that you want to execute is taking 2 minutes to complete. What is the code for? Doing things in other databases or connect to other non notes resources?
I am trying to determine the "approved" or best practices approach while in a Java EE environment for doing the following: A client is on a web page and clicks a button. This starts a thread for monitoring a process, i.e. database activity, network, etc. This process will continue to run until the user clicks a button that tells the process to end. Other clients, and/or the same client then clicks a button to listen to the status being sent from that process which will continue to listen until the user clicks a button to stop listening.
I have already done the above by using a WebSocket to communicate with a servlet which gets an injected a singleton EJB that extends WebSocketApplication. But, this EJB is spawning the process thread to do the monitoring. Although it works and should continue to work since it is a singleton, it is not the "approved" way of doing it.
Some suggestions I have reviewed discuss using JMS to spawn the thread, but, unless I am misunderstanding something, this doesn't solve anything since a Message Driven Bean isn't supposed to spawn a thread either. So, what is the approved/best practices method of doing this? How does one start and stop a background process in a Java EE environment? Again, the requirements are, only one process can be spawned, it must communicate to all WebSockets that register with the servlet, it must be able to die when told to (although that doesn't mean the server closes the sockets, since it could be started back up and would still communicate to all the previously registered clients).
Thanks.
this EJB is spawning the process thread
EJBs are not permitted to start threads. Quoth the standard:
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt
to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enter-
prise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads
would decrease the container’s ability to properly manage the runtime environment.
This is by design; the specification states the following
The Enterprise JavaBeans architecture will make it easy to write applications: application
developers will not have to understand low-level transaction and state management details,
multi-threading, connection pooling, or other complex low-level APIs.
Have you considered using a stateful session bean? Clicking on the button causes the bean to enter the "started" state. Click on the second button causes the bean to enter the "stopped" state.
To create threads in an enterprise environment, you should use either ManagedThreadFactory or ManagedExecutorService.
Please see here
The answer is an asynchronous EJB 3.1 bean. Thanks for the reply.
As of Java EE 7 you can use the ManagedExecutorService to give your EJBs access to a managed thread pool.