Losing ApplicationContext when executing new runnables - java

I know I'm new to this spring stuff but I've been stuck on this all day. I don't much like asking questions but maybe I'll get an idea.
So here's my problem:
I'm trying to create a Queue for processing stuff on the back end. I did this by creating a static executorservice in a component class with helper methods to run them. it seems to work like i want, and when i wire in classes i can get into those classes, but it seems like when those are running they lose application context (or something this is just my guess).
I'm sure There are better ways to do this, but in the custom framework I am working in there are a number of features that will not work for me. I have no spring-config.xml, cannot use #Configuration
executor service component
#Component
public class FifoComponent {
public static ExecutorService executors = Executors.newSingleThreadExecutor();
private static Lock lock = new ReentrantLock(true);
public static void executeNewTestJob(int i) {
lock.lock();
OrderAllocationTestJob job = new OrderAllocationTestJob(i);
executors.execute(job);
lock.unlock();
}
}
Runnable component - note appdateutils has a method that calls a component that and works fine in my typical tomcat environment
#Component
public class OrderAllocationTestJob implements Runnable {
int i;
public OrderAllocationTestJob(int i) {
this.i = i;
}
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Asynchronous task " + i);
System.out.println(AppDateUtils.getCurrentTimeStamp());
}
}
call from a struts 2 action (test) i know I can call the appdateutils.gettime method from
for (int i = 0; i < 50; i++) {
FifoComponent.executeNewTestJob(i);
}
here's the exception i end up with for what it's worth
"Scope 'request' is not active for the current thread"
Exception in thread "pool-15-thread-50" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dateTimestampDao': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

"I'm sure There are better ways to do this"
Based on this, you'll need to create/lookup all request and session scoped components before call another thread. Actually, request injection is thread local and can't works in your scenario.

i think if u remove
Thread.sleep(100);
in OrderAllocationTestJob to
job.sleep(100);
in FifoComponent will fix your problem

I solved this solution by extending ConcurrentLinkedQueue for my runnables and keeping them in a manager I instantiated in the initialize method of a ServletContextListener. By overriding the offer() method of the ConcurrentLinkedQueue to continually poll until the queue was empty I was able synchronously process runnables.
Unfortunately this locks down the request thread until the runnable is done and I will have to have my users keep an eye on it and let me know if the pages end up running long, but at least in my test environment the process seems sub-second even when i hit it with 20 at a time so I'm OK for now.
I would still prefer an ExecutorService executed from my Tomcat container but outside the scope of the requests but unless someone can answer the question I'm just going to have to leave it for now

Are you looking something like that?
#Component
public class AsynchronousThread extends Thread {
public static final Logger LOGGER = LoggerFactory
.getLogger(AsynchronousThread.class);
#Autowired
private Writer writer;
private BlockingQueue<IndexContextDTO> blockingQueue = new LinkedBlockingQueue<IndexContextDTO>(
500);
/**
*
*/
public AsynchronousThread() {
super("AsynchronousThread");
}
#PostConstruct
public void init() {
Integer internalQueueSize = 100;
this.blockingQueue = new LinkedBlockingQueue<>(internalQueueSize);
this.start();
}
#Override
public void run() {
while (true) {
// Do stuff
}
}
public void putInQueue(IndexContextDTO message) {
try {
this.blockingQueue.put(message);
} catch (InterruptedException interruptedException) {
// This exception will be thrown in very rare case.
LOGGER.error("An error while putting message in the queue. "
+ message, interruptedException);
}
}
}

Related

How to throw an exception on another Thread in Java?

So I'm using ListenableFuture as a return type for certain operations. I expect the users to add callback to the future and then handle the success and exception cases. Now if the user cannot handle the exception, I want to have the ability to throw that exception onto the main Thread. Here's some code example:
public class SomeProcessor {
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
public ListenableFuture<String> doStringProcessing() {
return executor.submit(() -> doWork());
}
private String doWork() {
return "stuff";
}
}
Then in a client class:
public class SomeConsumer {
public SomeConsumer (SomeProcessor processor) {
Futures.addCallback(processor.doStringProcessing(), new FutureCallback<String>() {
#Override
public void onSuccess(String result) {
// do something with result
}
#Override
public void onFailure(Throwable t) {
if (t instanceof ExceptionICanHandle) {
// great, deal with it
} else {
// HERE I want to throw on the Main thread, not on the executor's thread
// Assume somehow I can get a hold of the main thread object
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, t);
// This above code seems wrong???
throw new RuntimeException("Won't work as this is not on the mainthread");
}
}
}, MoreExecutors.directionExecutor());
}
}
There is no direct way to do this.1
Hence, this question boils down to a combination of 2 simple things:
How do I communicate some data from a submitted task back to the code that is managing the pool itself? Which boils down to: How do I send data from one thread to another, and...
How do I throw an exception - which is trivial - throw x;.
In other words, you make the exception in your task, and do not throw it, instead, you store the object in a place the main thread can see it, and notify the main thread they need to go fetch it and throw it. Your main thread waits for this notification and upon receiving it, fetches it, and throws it.
A submitted task cannot simply 'ask' for its pool or the thread that manages it. However, that is easy enough to solve: Simply pass either the 'main thread' itself, or more likely some third object that serves as common communication line between them, to the task itself, so that task knows where to go.
Here is one simplistic approach based on the raw synchronization primitives baked into java itself:
public static void main(String[] args) {
// I am the main thread
// Fire up the executorservice here and submit tasks to it.
// then ordinarily you would let this thread end or sleep.
// instead...
ExecutorService service = ...;
AtomicReference<Throwable> err = new AtomicReference<>();
Runnable task = () -> doWork(err);
service.submit(task);
while (true) {
synchronized (err) {
Throwable t = err.get();
if (t != null) throw t;
err.wait();
}
}
}
public void doWork(AtomicReference<Throwable> envelope) {
try {
doActualWork();
catch (Throwable t) {
synchronized (envelope) {
envelope.set(t);
envelope.notifyAll();
}
}
}
There are many, many ways to send messages from one thread to another and the above is a rather finicky, primitive form. It'll do fine if you don't currently have any comms channels already available to you. But, if you already have e.g. a message queue service or the like you should probably use that instead here.
[1] Thread.stop(someThrowable) literally does this as per its own documentation. However, it doesn't work - it's not just deprecated, it has been axed entirely; calling it throws an UnsupportedOperationException on modern VMs (I think at this point 10 years worth of releases at least), and is marked deprecated with the rather ominous warning of This method is inherently unsafe. and a lot more to boot, it's not the right answer.

What's the best way to release resources after java.util.Timer?

I have an AutoCloseable whose close() method is being called prematurely. The AutoCloseable is ProcessQueues below. I don't want the close() method to be called when it is currently being called. I'm considering the removal of "implements AutoCloseable" to accomplish that. But then how do I know when to call ProcessQueues.close()?
public class ProcessQueues implements AutoCloseable {
private ArrayList<MessageQueue> queueObjects = new ArrayList<MessageQueue>();
public ProcessQueues() {
queueObjects.add(new FFE_DPVALID_TO_SSP_EXCEPTION());
queueObjects.add(new FFE_DPVALID_TO_SSP_ESBEXCEPTION());
...
}
private void scheduleProcessRuns() {
try {
for (MessageQueue obj : queueObjects) {
monitorTimer.schedule(obj, new Date(), 1); // NOT THE ACTUAL ARGUMENTS
}
}
catch (Exception ex) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
#Override
public void close() throws Exception {
for (MessageQueue queue : queueObjects) {
queue.close();
}
}
}
I want ProcessQueues.close() to be called, but not until the task execution threads of all Timer objects terminate. As written, ProcessQueues.close() will be called as soon as the tasks are scheduled. I can easily solve that by removing "implements AutoCloseable" from the ProcessQueues class (and removing the #Override annotation). But then I have to call ProcessQueues.close() myself. How do I know when the task execution threads of all Timer objects have terminated? That's when I want to call ProcessQueues.close().
Note that MessageQueue isn't instantiated in the resource specification header of a try-with-resources block, so although MessageQueue also implements AutoCloseable, the feature isn't utilized here. I'm explicitly calling MessageQueue.close(). It is in MessageQueue.close() that I release resources. Releasing those resources prematurely causes the task execution threads to fail to complete their tasks.
I'm considering an explicit call to ProcessQueues.close() after rewriting the code to prevent automatic resource deallocation, but again I don't know how to discover the right time for that explicit call.
I considered overriding ProcessQueues.finalize(), but "Java: How to Program", Eleventh Edition advises against that. "You should never use method finalize, because it can cause many problems and there's uncertainty as to whether it will ever get called before a program terminates... Now it's considered better practice for any class that uses system resources... to provide a method that programmers can call to release resources when they're no longer needed in a program." I have such a method. It's ProcessQueues.close(). But when should I call it?
You have conflicting lifecycle issues here.
You have Timer whose lifecycle is 100% in your control. You start it, you stop it, and that's it. But you have no direct introspection in to the status of the threads being managed by the Timer. So, you can't ask it if it has anything currently running, for example.
Then you have your MessageQueue, which is invoked by the Timer. This is the lifecycle you're interested in. You want to wait for all of the MessageQueues to be "done", for assorted values of done. But, since the queue are constantly being rescheduled (given the Timer.schedule method that you're using), they're NEVER "done". They process their contents and go off and run again.
So, how is anyone to know when "done" means "done"?
Is it up to the MessageQueue? Or is it up to the ProcessQueues? Who's in command here?
Notice, nothing ever cancels the Timer. It's just runs on and on and on.
So, how can one know when MessageQueue can be closed?
If MessageQueue is the real driver here, then you should add lifecycle methods to the MessageQueue that ProcessQueues can monitor to know when to shut things down. For example, you could create a CountDownLatch set for however many MessageQueues are in your list, and then subscribe to a new lifecycle method on the MessageQueue that it calls when it's finished. The callback method can then decrement the CountDownLatch, and the ProcessQueues.close method simply waits on the latch to countdown before closing everything.
public class ProcessQueues implements AutoCloseable, MessageQueueListener {
private ArrayList<MessageQueue> queueObjects = new ArrayList<MessageQueue>();
CountDownLatch latch;
public ProcessQueues() {
queueObjects.add(new FFE_DPVALID_TO_SSP_EXCEPTION());
queueObjects.add(new FFE_DPVALID_TO_SSP_ESBEXCEPTION());
...
queueObjects.forEach((mq) -> {
mq.setListener(this);
});
latch = new CountDownLatch(queueObjects.size());
}
private void scheduleProcessRuns() {
try {
for (MessageQueue obj : queueObjects) {
monitorTimer.schedule(obj, new Date(), 1); // NOT THE ACTUAL ARGUMENTS
}
} catch (Exception ex) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
#Override
public void close() throws Exception {
latch.await();
for (MessageQueue queue : queueObjects) {
queue.close();
}
monitorTimer.cancel();
}
#Override
public void messageQueueDone() {
latch.countDown();
}
}
public interface MessageQueueListener {
public void messageQueueDone();
}
public class MessageQueue extends TimerTask {
MessageQueueListener listener;
public void setListener(MessageQueueListener listener) {
this.listener = listener;
}
private boolean isMessageQueueReallyDone {
...
}
public void run() {
...
if (isMessageQueueReallyDone() && listener != null) {
listener.messageQueueDone();
}
}
}
Mind, this means that your try-with-resource block will block waiting on all of the MessageQueues, if that's what you want, then you're good to go.
It also crassly assumes that your MessageQueue.run() knows when to shut down, which goes back to that "who's in control here" thing.
I could terminate the Timer, but having it run perpetually is intentional. The question is in consideration of what happens when something else terminates the Timer and the MessageQueue objects are no longer needed. It is at that point that I would like to call ProcessQueues.close().
If I were to use the Executor framework, rather than Timer, then I could use ExecutorService.awaitTermination(long timeout, TimeUnit unit)
TimerTask is a Runnable, and MessageQueue is already a TimerTask, so MessageQueue need not change.
'ExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)' would effectively wait forever for termination.
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
// Don't take this literally.
ExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
Of course, awaitTermination isn't a static method, so I'll have to have an ExecutorService, but you get the idea.
After termination, the AutoCloseable feature is leveraged and ProcessQueues.close() is implicitly called.
All that remains is to start the threads for perpetually repeated calls to each TimerTask, using the Executor framework. The answer to that question is ScheduledExecutorService.
I think this will work.

Spring - how to kill endless cycle

In my Spring application, there is a scheduler for executing some task. Scheduled annotation is not used there because the schedule is quite complicated - it is dynamic and it used some data from the database. So simple endless cycle with thread sleeping is used. And sleeping interval is changed according to some rules. Maybe all this can be done with Scheduled annotation, but the question is not about that.
Below is simple example:
#Service
public class SomeService {
#PostConstruct
void init() {
new Thread(() -> {
while (true) {
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println("end");
return;
}
}
}).start();
}
}
The code works fine but there is some trouble with killing that new thread. When I stop the application from Tomcat this new thread is continuing to run. So on Tomcat manage page I see that application is stopped, but in Tomcat log files I still see the output from the thread.
So what the problem? How I should change the code so the thread would be killed when the application is stopped?
Have you tried to implement a #PreDestroy method which will be invoked before WebApplicationContext is closed to change a boolean flag used in your loop? Though it seems strange that your objects are not discarded even when application is stopped...
class Scheduler {
private AtomicBoolean booleanFlag = new AtomicBoolean(true);
#PostConstruct
private void init() {
new Thread(() -> {
while (booleanFlag.get()) {
// do whatever you want
}
}).start();
}
#PreDestroy
private void destroy() {
booleanFlag.set(false);
}
}

Initializing time intensive subsystem in Websocket application

I am creating a websocket application, and I want to perform a one-time time intensive task at program initialization. In creating this application, the recommended practice (https://netbeans.org/kb/docs/javaee/maven-websocketapi.html) is to override the following functions:
#ServerEndpoint(value = "/testendpoint", encoders = {TestEncoder.class}, decoders = {TestDecoder.class})
public class WSEndpoint
{
#OnMessage
public void onMessage(Session wsSession, CommandIn command) throws IOException, EncodeException
{
...
}
#OnOpen
public void onOpen(Session wsSession)
{
...
}
#OnClose
public void onClose(Session wsSession)
{
...
}
#OnError
public void onError(Throwable t)
{
}
}
So when a new connection/session is created, "onOpen" would be called and when a new message is received, "onMessage" is called.
What I want to do is, before letting the user create sessions and send commands (via browser front end), to initialize the subsystem that takes about 20 seconds to initialize. If it's initialized only at "first requested use", as I am doing now, then the user experience gets interrupted. Clearly, there is no "main" function visible here (presumably, called by the websocket framework at a deeper level).
What do you guys recommend I do to achieve what I want to do? Currently, I have the initialization code in a static block in an internal class - which only gets executed once - but gets executed when the class is first "called/used", interrupting the user experience.
Any suggestions?
Thanks.
The best place for initialization code in a web application is inside a ServletContextListener's contextInitialized method.
This way you do your initialization when the application starts.

Glassfish 4 - Using Concurrency API to create Managed Threads

I'm trying to use the new Concurrency API to inject a ManagedThreadFactory and use it per the Oracle tutorial.
Here is an example of what I'm talking about:
#Singleton
#Startup
public class Demo {
#Resource(name="concurrent/__DefaultManagedThreadFactory") ManagedThreadFactory threadFactory;
#PostConstruct
public void startup() {
threadFactory.newThread(
new Runnable() {
#Override
public void run() {
System.out.println("Do something.");
}
}
).start();
}
}
I'm developing in Eclipse using the Glassfish plugin. When I republish after making a change, I always get this line in the server log. It appears once for every call to start() we make:
SEVERE: java.lang.IllegalStateException: Module (my application) is disabled
It's not actually throwing an IllegalStateException, just reporting that one has been thrown (and caught) inside Glassfish. The application deploys normally, but none of the threads start. If I subsequently republish and second time, the "error" goes away and the threads start as expected.
When I try to deploy the application to a "real" Glassfish setup (without Eclipse), it always reports successful deployment, and the logs do not contain the "error". But it still does not start the threads (even with repeated deployments).
Am I using the Concurrency API correctly? Could it be a configuration problem? For the record, I get the same behavior if I use a ManagedExcecutorService instead.
For the record, this question was asked a few months ago here: Can I start a ManagedThread in a Singleton Enterprise Java Bean?, but it was not really answered and I don't have the reputation yet to do anything but ask it again. Sorry!
UPDATE: This answer by Per-Axel Felth works. Thank you! I did some refactoring of that solution to attempt to isolate the workaround code from my original application logic:
#Singleton
#Startup
public class Demo {
#Resource(name="java:comp/DefaultManagedThreadFactory") ManagedThreadFactory threadFactory;
#EJB private ConcurrencyInitializer concurrencyInitializer;
#EJB private Demo self;
#PostConstruct
public void startup() {
self.startThread();
}
#Asynchronous
public void startThread() {
//This line applies the workaround
concurrencyInitializer.init();
//Everything beyond this point is my original application logic
threadFactory.newThread(
new Runnable() {
#Override
public void run() {
System.out.println("Do something.");
}
}
).start();
}
}
/**
* A utility class used to get around a bug in Glassfish that allows
* Concurrency resources (ManagedThreadFactory, ManagedExecutorService, etc)
* to be injected before they are ready to be used.
*
* Derived from solution by Per-Axel Felth in: https://stackoverflow.com/questions/23900826/glassfish-4-using-concurrency-api-to-create-managed-threads
*/
#Singleton
public class ConcurrencyInitializer {
/**
* The number of milliseconds to wait before try to
*/
public static final long RETRY_DELAY = 500L;
/**
* The maximum number of concurrency attempts to make before failing
*/
public static final int MAX_RETRIES = 20;
/**
* Repeatedly attempts to submit a Runnable task to an injected ManagedExecutorService
* to trigger the readying of the Concurrency resources.
*
* #return true if successful (Concurrency resources are now ready for use),
* false if timed out instead
*/
public boolean init() {
final AtomicBoolean done = new AtomicBoolean(false);
int i = 0;
try {
while (!done.get() && i++ < MAX_RETRIES) {
executorService.submit(new Runnable() {
#Override
public void run() {
done.set(true);
}
});
Thread.sleep(RETRY_DELAY);
}
} catch(InterruptedException e) {
//Do nothing.
}
return done.get();
}
}
It's related to a Glassfish bug. I ran into the same bug myself some time ago and built a workaround. Thing is, the thread factory is injected alright, but if you use it "too early" you'll end up with an IllegalStateException.
My workaround code is listed below. It uses an injected executor service to detect when app is loaded and concurrency utils are available and then executes the actual startup logic in method init.
#Singleton
#Startup
public class Demo {
#Resource(name = "concurrent/__DefaultManagedThreadFactory")
ManagedThreadFactory threadFactory;
#Resource
ManagedExecutorService executorService;
#EJB
Demo me;
#PostConstruct
public void startup() {
me.waitAndInitialize();
}
#Asynchronous
public Future<?> waitAndInitialize() {
try {
final AtomicInteger done = new AtomicInteger(0);
int i = 0;
while (done.intValue() == 0 && i < 20) {
System.out.println("Is executor service up?");
i++;
executorService.submit(
new Runnable() {
#Override
public void run() {
int incrementAndGet = done.incrementAndGet();
System.out.println("Run by executorservice");
}
});
Thread.sleep(500);
}
if (done.intValue() == 0) {
Logger.getAnonymousLogger().severe("Waited a long time for the ExecutorService do become ready, but it never did. Will not initialize!");
} else {
init();
}
} catch (Exception e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "Exception in waitAndInitialize: " + e.getMessage(), e);
}
return new AsyncResult<>(null);
}
private void init() {
threadFactory.newThread(
new Runnable() {
#Override
public void run() {
System.out.println("Do something.");
}
}
).start();
}
}
I suspect that your ManagedThreadFactory is not being injected correctly so the "Demo" component is not started.
The Java EE 7 spec mandates that a managed thread factory be made available in JNDI with the name "java:comp/DefaultManagedThreadFactory", therefore try changing #Resource to
#Resource(name="java:comp/DefaultManagedThreadFactory")
I'm not familiar with Glassfish (I'm a WildFly kind of guy) but you may not see this reference in any JNDI tree display. It may be linked internally to "concurrent/__DefaultManagedThreadFactory" (which is not a resource name btw).
Failing that you can also try
#Resource(lookup="concurrent/__DefaultManagedThreadFactory")

Categories

Resources