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")
Related
EDIT: It turns out that my docker container was closing because of an errant health check failing. This caused the kubernetes probe to fail too many times and killed the pod. Since the command came from outside the JVM, it is likely not possible for the code to know when the container around the JVM was killed. Leaving this question up in case someone finds an answer.
I have a Java SE project that reads in arguments to process files. I am using Weld-SE for injection. After a few minutes of running, the weld container shuts down mid progressing without explanation. The following is a skeleton of my code. Here in my Main Class
#ApplicationScoped
public class Main {
#Setter //Lombok annotation
private Scheduler scheduler;
public void schedule(String[] filenames) throws InterruptedException {
scheduler.schedule(filenames);
}
#PreDestroy
public void cleanUp() {
log.info("PreDestroy - Main");
//clean up omitted
}
public static void main(String[] args) {
Weld weld = new Weld();
Main main = null;
try (WeldContainer container = weld.initialize()) {
main = container.select(Main.class).get();
Scheduler scheduler = CDI.current().select(Scheduler.class).get();
main.setScheduler(scheduler);
main.schedule(args);
log.info("Main - completed processing");
} catch (Exception e) {
log.info("Exception occurred: " + e.getMessage(), e);
} finally {
log.info("Main Finally - Shutting down Weld");
CDI.current().destroy(main);
weld.shutdown();
}
}
}
Here is my Scheduler class
#Named
public class Scheduler {
private ThreadPoolExecutor executor;
private Map<Future<?>, Importer> beanMap = new HashMap<>();
private static final Duration sleepDuration = Duration.ofSeconds(45);
#PostConstructor
public void init() {
//setup executor
}
#PreDestroy
public void cleanUp() {
log.info("PreDestroy - Scheduler");
//clean up omitted
}
public void schedule(String[] filenames) throws InterruptedException {
for(String filename : filenames) {
Importer caller = CDI.current().select(Importer.class).get();
caller.setFilename(filename);
Future<?> future = executor.submit(caller);
beanMap.put(future, caller);
}
while(!isDone()) {
Thread.sleep(sleepDuration.toMillis());
log.info("Remaining threads: {}, getRemaining());
destroyCompleted();
}
}
//Returns true only when all threads are completed
private boolean isDone() { //code omitted }
//Returns number of not completed threads
private int getRemaining() { //code omitted }
//Clean up any completed Importers
private boolean destroyCompleted() { //code omitted }
}
Here is my Importer code
#Named
public class Importer implements Callable<String> {
#Setter //lombok annotation
private String filename;
public void cleanUp() {
log.info("PreDestroy - Importer");
//clean up omitted
}
public String call() {
List<String> content = //extract file content
for(int i = 0; i < content.size; i++) {
if (i+1 % 10000 == 0) {
log.info("Processed {} rows in file {}", i+1, filename);
}
//rest of loop omitted
}
}
}
The file test.txt has around 100,000 lines so I can tell that the crash happens mid file processing. So after my code runs for a few minutes I get the following at the end of my log
Processed 50000 rows in file test.txt
Processed 60000 rows in file text.txt
PreDestroy - Scheduler
PreDestroy - Importer
PreDestroy - Main
WELD-ENV-002001: Weld SE container 03128098-039d-46db-97e5-8538a52a38cc shut down
I am logging "org.jboss" at DEBUG level. I can see that the container was shutdown midway through processing a file, but I don't see why it occurred. Is there some type of listener that I can extend/implement to see why shut down command happened?
For future reference: You can define an observer method for the BeforeShutdown event which you can use to at least close all open files and such before shutdown. It won't necessarily give you a reason for why it's shutting down, but it's a start.
If you say the JVM process was terminated from outside, then there's probably an InterruptedException thrown somewhere which you can catch. Note that catching InterruptedException and not re-interrupting the thread is a bug most of the time. In your case, you should react to it with an orderly shutdown when calling Thread#sleep. If the thread gets interrupted, someone wants to cancel the execution. They probably have a good reason for doing so; don't think you know better than them!
At the very least you can periodically check the interrupt flag of your threads at some convenient point during execution to initiate an orderly shutdown of your task.
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);
}
}
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);
}
}
}
I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users from the whole database. So I want to keep the servlet continuously running for that.
Your problem is that you misunderstand the purpose of the servlet. It's intented to act on HTTP requests, nothing more. You want just a background task which runs once on daily basis.
EJB available? Use #Schedule
If your environment happen to support EJB (i.e. a real Java EE server such as WildFly, JBoss, TomEE, Payara, GlassFish, etc), then use #Schedule instead. Here are some examples:
#Singleton
public class BackgroundJobManager {
#Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// Do your job here which should run every start of day.
}
#Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// Do your job here which should run every hour of day.
}
#Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// Do your job here which should run every 15 minute of hour.
}
#Schedule(hour="*", minute="*", second="*/5", persistent=false)
public void someFiveSecondelyJob() {
// Do your job here which should run every 5 seconds.
}
}
Yes, that's really all. The container will automatically pickup and manage it.
EJB unavailable? Use ScheduledExecutorService
If your environment doesn't support EJB (i.e. you're not using not a real Java EE server, but a barebones servletcontainer such as Tomcat, Jetty, etc), then use ScheduledExecutorService. This can be initiated by a ServletContextListener. Here's a kickoff example:
#WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
Where the job classes look like this:
public class SomeDailyJob implements Runnable {
#Override
public void run() {
// Do your daily job here.
}
}
public class SomeHourlyJob implements Runnable {
#Override
public void run() {
// Do your hourly job here.
}
}
public class SomeQuarterlyJob implements Runnable {
#Override
public void run() {
// Do your quarterly job here.
}
}
public class SomeFiveSecondelyJob implements Runnable {
#Override
public void run() {
// Do your quarterly job here.
}
}
Do not ever think about using java.util.Timer/java.lang.Thread in a Java EE / Servlet based environment
Last but not least, never directly use java.util.Timer and/or java.lang.Thread in Java EE. This is recipe for trouble. An elaborate explanation can be found in this JSF-related answer on the same question: Spawning threads in a JSF managed bean for scheduled tasks using a timer.
I would suggest using a library like quartz in order to run the task at regular intervals. What does the servlet really do ? It sends you a report ?
You can use cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
Implement two classes and call startTask() in main.
public void startTask()
{
// Create a Runnable
Runnable task = new Runnable() {
public void run() {
while (true) {
runTask();
}
}
};
// Run the task in a background thread
Thread backgroundThread = new Thread(task);
// Terminate the running thread if the application exits
backgroundThread.setDaemon(true);
// Start the thread
backgroundThread.start();
}
public void runTask()
{
try {
// do something...
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
In a production system that may have multiple non-jee containers running. Use anot enterprise scheduler like Quartz scheduler which can be configured to use a database for task maamgememt.
I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.