x I have overriden the LifecycleBase.start() method like the following. but in Catalina 8.x this method has become final.
Could anyone tell me how to solve this Problem please.
Here is the sourcecode
public void start() throws LifecycleException
{
super.start();
if(condition)
{
File checkDataFile = new File(DataFilePath);
if(containerLog.isDebugEnabled())
containerLog.debug("checking secureDataFile: " + checkDataFile.getAbsolutePath());
another code ...
}
else
{
throw new LifecycleException("illegal arguments");
}
}
public void stop() throws LifecycleException
{
// sync via realm-object -> so the stop-event has to wait for active threads finishing their operations
synchronized(this)
{
super.stop();
}
}
You may use startInternal() and stopInternal(), both methods are abstract protected and are called respectively by start() and stop() .
Of course don't call super.start() and super.stop() or you are in for a StackOverflowError, since start() and stop()are already calling your custom "internal" methods.
Also read carefully the contract from these two methods :
startInternal()
Sub-classes must ensure that the state is changed to org.apache.catalina.LifecycleState.STARTING during the execution of
this method. Changing state will trigger the
org.apache.catalina.Lifecycle.START_EVENT event. If a component fails
to start it may either throw a org.apache.catalina.LifecycleException
which will cause it's parent to fail to start or it can place itself
in the error state in which case stop() will be called on the failed
component but the parent component will continue to start normally
and
stopInternal()
Sub-classes must ensure that the state is changed to
org.apache.catalina.LifecycleState.STOPPING during the execution of
this method. Changing state will trigger the
org.apache.catalina.Lifecycle.STOP_EVENT event.
If you want to see what happens with more details, look at the code of
one of the latest versions of
org.apache.catalina.util.LifecycleBase .
Related
I have an OSGI bundle of a following structure:
//...
public ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
//...
#Activate
public void activate() {
executor.submit(new Runnable() {
#Override
public void run() {
//call 3 functions and log the data
}
}
}
#Deactivate
public void deactivate(){
//call 2 other functions
}
The executor in the activate method makes sure that 3 functions are called in a separate from all other bundles thread, because those functions actually implement some sophisticated Windows-message-loop, i.e. a while true loop, that's why, in order not to block other bundles, it is activated in a separate thread. Now what I've sadly noticed, that in order to run 2 functions in deactivate method I need to run them in the same thread, in which 3 functions in activate method were run. Simply speaking, I need to be sure, that activate and deactivate methods of my bundle run in the one same thread, but still to keep this bundle activation separated (in an own thread) from the other bundles.
My question is: how to implement this?
I am not a guru in concurrency in Java, I've tried simply to call this executor in the deactivate method too but I don't know how to do it with one Runnable task, since in deactivate I have only to call 2 functions and in activate only 3 functions and no other calls should be made.
UPD: sorry, I forgot to mention, that there is a routine in another bundle, which calls in certain situations context.getBundle(0).stop() in order to call a deactivation for all bundles. If I want just to add the same submit routine in the deactivate method as is in activate, then in such situation I could clearly see, that those 2 functions from deactivate method of my bundle in the submit's body were not called.
Simply do another executor.submit in deactivate. As it is a single threaded executor it will make sure only one thread processes both.
The only question is how to shut down the executor reliably. Normally after deactivate a component should have closed all its resources.
This sounds like a very common problem. I would just make it explicit you're using a thread and use the methods in Thread that were designed for this. At activate you start the thread, at deactivate you interrupt it. Your main loop watches the interrupt status and executes your deactivate functions after it is interrupted. After interrupt, it is best to join the thread to ensure your activate() method does not return before the background thread has finished running your deactivate functions.
Since exiting the framework (stopping bundle 0) must stop all bundles, and a stopped bundle will deactivate its components, this should all work.
public class Foo extends Thread {
#Activate void activate() { start(); }
#Deactivate void deactivate() throws Exception { interrupt(); join(); }
public void run() {
while(!isInterrupted()) try {
... your 3 function loop
} catch( InterruptedException e) {
break;
}
... 2 deactivate functions
}
}
I have defined this kind of Android Java class, where native function baresipStart() never terminates:
package com.tutpro.baresip;
public class BaresipThread extends Thread {
public void start() {
baresipStart();
}
public void kill() {
baresipStop();
}
public native void baresipStart();
public native void baresipStop();
}
I then call its start() function from another Java class:
BaresipThread thread;
thread = new BaresipThread();
thread.start();
The result is that baresipStart() function starts to run fine, but rest of the application becomes completely unresponsive.
Why is that and how to fix the code so that baresipStart() function runs in the background without stopping all other activity?
Thread.start() is responsible for actually creating the new thread of execution and setting it running. By overriding it as you did, you cause it to instead run baresipStart(), in the thread that invokes start().
Instead of overriding start(), you should override run(). This method is what defines the work to be performed in the new thread of execution.
Furthermore, if native method baresipStart() indeed never returns then you have a problem. Your application cannot terminate while it has any active threads. Supposing that you intend for baresipStop() to cause the thread to finish, you should arrange for baresipStart() to return (or to throw an unchecked exception) when execution is terminated by an invocation of baresipStop(). Do be aware, however, that those native methods need to be thread-safe, because they will, perforce, be invoked by different Java threads.
Thanks for your explanation. I got the new baresip thread started by removing BaresipThread object altogether and replacing the three lines above with this:
new Thread(new Runnable() {
public void run() {
baresipStart();
}
}).start();
User can stop the resulting process via its user interface after which the application is terminated.
I suddenly got a weird problem in my application, but I am not sure if I can isolate the issue. I couldn't reproduce the bug in a SCCEE, but maybe someone could help me understand what happens by answering the 2 questions below.
The Context:
I have, basically this:
...
Some treatment
->call to json-io to parse a Json String to Java Objects. see below
...
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
myUI.start();//starts my user interface
}
});
Usually, everything goes fine. But I added to the treatments a call to Json IO (a library that parses Json to Java and that I generally use without any trouble).
Now, one of my other library is yelling:
Caused by: java.lang.NullPointerException
at net.sourceforge.jeuclid.elements.support.ClassLoaderSupport.loadClass(ClassLoaderSupport.java:65)
After some researches, I discovered that it is because Thread.currentThread().getContextClassLoader() returns null.
I went to the run() above and discovered that the only difference between the 2 executions is that the Event Dispatched Thread that used to belong to the group main now belongs to system:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println(Thread.currentThread());
//returns Thread[AWT-EventQueue-0,6,system] instead of Thread[AWT-EventQueue-0,6,main]
myUI.start();//starts my user interface
}
});
In the end, I could solve the problem with
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
myUI.start();//starts my user interface
}
}
});
The Questions:
1) What kind of things can make the EDT change group ?
2) What are the consequences of writing Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); ? Is it a good or a bad idea ?
If your invocation of SwingUtilities.invokeLater is the first action that relies on the presence of the EDT, that thread will be created as a byproduct. So the created thread inherits the thread group of the thread which created it, e.g.
ThreadGroup tg=new ThreadGroup("foo");
new Thread(tg, ()->
SwingUtilities.invokeLater(() -> System.out.println(Thread.currentThread()))
).start();
when performed as first action of an application, will print
Thread[AWT-EventQueue-0,6,foo]
as you can verify on Ideone.
But note that the thread group has no impact on the context class loader, it’s rather a symptom of the same cause. The context class loader is just inherited exactly like the thread group when the thread is created, e.g.
ClassLoader dummyLoader=new URLClassLoader(new URL[0]);
Thread.currentThread().setContextClassLoader(dummyLoader);
SwingUtilities.invokeLater(() ->
System.out.println(Thread.currentThread().getContextClassLoader()==dummyLoader));
will print true; (verify on Ideone).
So apparently, the context loader of the thread which invokes SwingUtilities.invokeLater, initiating the EDT creation, is already null (and that thread is in the system group). Setting the context loader to ClassLoader.getSystemClassLoader() means setting it to its default, so it has no negative impact unless you encounter an environment where the context loader is intentionally set to a non-default loader, though null can not be considered to be such a case. In other words, identifying the place, where it is set to null and fixing that, is the better choice.
is it possible to have a method be called when the main thread or the entire program terminates? I'm aware of Thread's .join() method, but I do not think it will work on the main thread. For example, if I create a temporary directory, I would like to delete that temporary directory when the program terminates, but I would like for that to happen when the program terminates, not after something like the main method.
I do not want this:
public static void main() {
....Do something
....Delete temp directory
}
Simply add a shutdown hook..
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("ERMEHGERDDD");
}
});
From the Javadoc: A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.
The shutdown hook will be called when all non-deamon threads finish or if System.exit() is called.
As user:Mad Programmer mentioned above, you could use ShutdownHook.
public static void main(String[] args)
{
ShutdownHookThread shutdownHook = new ShutdownHookThread();
Runtime.getRuntime().addShutdownHook(shutdownHook );
}
private static class JVMShutdownHook extends Thread
{
public void run()
{
// tempDirectory.delete();
}
}
I see four possible methods.
Use your own Thread subclass with an overridden run() method. Add a finally block for thread termination.
2.Use a Runnable with similar decoration, perhaps as a wrapper around the supplied Runnable. A variant of this is to subclass Thread in order to apply this wrapper at construction time.
3.Create a 2nd thread to join() on the real thread and thus detect its termination.
4.Use instrumentation to rewrite the Thread.run() method as above.
I'm trying to execute some task periodically using guava AbstractScheduledService :
public class MyService extends AbstractScheduledService {
public MyService() {
}
#Override
protected void runOneIteration() {
doStuff();
}
private void doStuff() {
// Do stuff
}
#Override
protected Scheduler scheduler() {
return Scheduler.newFixedRateSchedule(0, 8, TimeUnit.HOURS);
}
}
So this service should execute some task periodically every 8 hours but it never actually does. The inherited isRunning() method returns false and the runOneIteration() method never gets invoked.
I have managed to make it work by calling the startAsync() method (inherited from parent class) from my service constructor but I don't see any reference saying this is the way it should work.
Have I missed something here? Is this the way the AbstractScheduledService works?
AbstractScheduledServiced implements Service. The Service interface describes lifecycle methods including startAsync. The ServiceState enum literals contain documentation on what they mean. A Service in NEW state (just created):
A service in this state is inactive. It does minimal work and consumes minimal resources.
For the Service to do something useful you have to transition it to the state RUNNING
A service in this state is operational.
That's why you have to start the Service before it does anything.
I would also advise against calling startAsync from the constructor and instead calling it from the Code that creates your MyService instance. It is rarely an expected thing to have such heavy side effects (creation of Threads) in the constructor.