I am running an application using tomcat as the container - at start up, several files need to be found and loaded. However, if one of these files doesn't exist or can't be read, I want to log the exception and exit the app, which I am currently doing using System.exit(1)... however, is there a better way of doing this?
Any help is much appreciated!
I dont know if this fits your needs but it actually worked for my app. The listener is
called at application start, if it is declared in your web.xml:
<listener>
<listener-class>your.package.TestServletListener</listener-class>
</listener>
There you can do testing and call the ShutdownThread if one fails. It will connect to Tomcats shutdown port and send the shutdown command as a String:
public class TestServletListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("Starting app, running 5 tests ...");
// do tests ...
for (int i = 0; i < 5; i++) {
System.out.println("testing ... " + i);
waitFor(1000);
}
// If a test failed call:
System.out.println("test failed!");
new ShutdownTask().start();
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.print("Stopping app, cleaning up (takes 3 sec) ... ");
waitFor(3000);
System.out.println("done");
}
private void waitFor(int i) {
try {
Thread.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
class ShutdownTask extends Thread {
#Override
public void run() {
try {
Socket s = new Socket("127.0.0.1", 8015);
PrintStream os = new PrintStream(s.getOutputStream());
os.println("shutdown");
s.close();
System.out.println("Shutting down server ...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You need to make sure that the shutdown port and shutdown command are in sync with your Tomcats server.xml:
...
<Server port="8015" shutdown="shutdown">
...
For example, you could pass them as context parameters in your web.xml. Like System.exit(...) this is not going to work (without further config) if Tomcat is running with a SecurityManager.
You should consider embedding Tomcat, i.e. have your AppStarter class perform those checks and then start Tomcat:
public class AppStarter {
public static void main(String[] args) {
// Check if everything is ready...
if (file1.exists() && file2.exists() && condition3) {
// Start Tomcat here.
}
else {
System.out.println("Invalid configuration.");
}
}
}
You can find how to embed Tomcat tutorials on the Internet.
Related
I am doing a project about chatting application. I'm using sockets. I'm creating this JFrame that gives me the option to connect as a server or a client. When I run my Options JFrame (choose to run as server or client) and I press server button some of my code gets skipped in the action listener. I already spend hours debugging and I don't know why some of my code gets skipped.
private void serverBtnMtd() {
try {
System.out.println("Running server Method");//Testing
MyServer myServer = new MyServer();//server gets Created and shows up
myServer.initializeServer();//Skipped
myServer.setVisible(true);//Skipped
System.out.println("End Running server Method");//Testing
} catch (Exception e) {
e.printStackTrace();
}
}
Action listener
btnServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
serverBtnMtd();
}
});
My Main Method
public class MyMain {
public static void main(String args[]) {
ServerOrClient mainApp = new ServerOrClient();
mainApp.setVisible(true);
mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
When I run my server class without the options JFrame everything runs. All of the skipping of code happens on the Action listener. I did some println's to test if all my code gets run and only the "Running server Method" shows up in my command line.
Server generally have infinite loops. So your code isn't skipped, just the new MyServer thing doesn't finish to resume your code. Put the code in a new thread.
You need to add:
setFocusable(true);
to your constructor
I have embedded Jetty into my Eclipse RCP application successfully.
In my RCP application, when user click some button, a browser will be opened and some servlet page shown. The jsp files are in a separated directory, it is a angulajs web application.
I am trying to shutdown embedded Jetty server from Eclipse UI plugin when user closes the RCP.The server is started in a class named Workshop which is part of web project, so I dont have access to Server instance to call, server.stop() from Eclipse UI Plugin.I have tried below code, but in vein.
1>Configure ShutdownHook to Workshop class of web project
server = new Server();
server.setConnectors(new Connector[] { connector });
server.setHandler(handlers);
server.start();
handlers.addHandler(new ShutdownHandler(server, "abc"));
server.setStopAtShutdown(true);
server.setGracefulShutdown(7_000);
ShutdownThread.getInstance().run();
2> In my Eclipse UI Plugin, I have added
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
URL url = new URL("http://localhost:" + resultPortNo + "/shutdown?token=" + shutdownCookie);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.getResponseCode();
logger.info("Shutting down " + url + ": " + connection.getResponseMessage());
} catch (SocketException e) {
// logger.debug("Not running");
// Okay - the server is not running
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
HtppUrlConnection throws 404-NotFound response code.So Jetty server is still running. How do we handle embedded Jetty shutdown from Eclipse UI Plugin.
I did read lot of articles, but cannot find answer to my question.
Any help will be appreciated.Thank you.
Problem : Every time jettyServer.stop was called, Interrupt Exception was thrown and jetty server continued to run.
Solution : (1) Added Executor Service with daemon thread in the Servlet code to stop the Jetty server
JettyShutdownServlet.js
-----------------------
ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
pool.execute(new Runnable() {
#Override
public void run() {
if (null != jettyServer) {
try {
jettyServer.stop();
jettyServer.join();
} catch (Exception e) {
logger.info("Error when stopping Jetty: " + e.getMessage());
}
}
}
});
(2) Adding the servlet inside the Jetty startup code.
servletContextHandler.addServlet(new ServletHolder(new JettyShutdownServlet(server)), "/shutdown");
(3) Adding shutdownhook to Eclipse UI class
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
String shutdownurl = "http://localhost:" + resultPortNo + "/api/shutdown";
URL url = new URL(shutdownurl);
HttpURLConnection connection =(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
try {
connection.getResponseCode();
connection.disconnect();
} catch (SocketException e) {
// logger.debug("Not running");
// Okay - the server is not running
connection.disconnect();
}
} catch (Exception x) {
// exception during shutdown
Activator.error("Unable to shutdown Jetty Server.\n" + x.getMessage());
}
}
});
This solved my problem and hope it will be of some help to others.
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")
I have an RCP application that uses a connection to a in-memory database. There is one circumstance that, when shutting down windows, the application is killed without giving it a chance to close the connection to the database.
I researched a little and it seems that adding a Shutdown hook is the best way to detect this event and do cleanup in a Java application. However, what is the correct way to do process this if you have an RCP application, possibly with multiple editors open?
Note: this blog entry suggests the following implementation for the shutdown hook:
The shutdown code must be run in the UI thread and should not be run if the workbench is being closed by other means. All dirty editors are automatically saved. This avoids prompting the user who is probably at home sleeping when their computer is shutdown. Finally the workbench is closed.
(so not exactly your scenario, but the implementation is still interesting in that it shows how to run it within the UI thread)
private class ShutdownHook extends Thread {
#Override
public void run() {
try {
final IWorkbench workbench = PlatformUI.getWorkbench();
final Display display = PlatformUI.getWorkbench()
.getDisplay();
if (workbench != null && !workbench.isClosing()) {
display.syncExec(new Runnable() {
public void run() {
IWorkbenchWindow [] workbenchWindows =
workbench.getWorkbenchWindows();
for(int i = 0;i < workbenchWindows.length;i++) {
IWorkbenchWindow workbenchWindow =
workbenchWindows[i];
if (workbenchWindow == null) {
// SIGTERM shutdown code must access
// workbench using UI thread!!
} else {
IWorkbenchPage[] pages = workbenchWindow
.getPages();
for (int j = 0; j < pages.length; j++) {
IEditorPart[] dirtyEditors = pages[j]
.getDirtyEditors();
for (int k = 0; k < dirtyEditors.length; k++) {
dirtyEditors[k]
.doSave(new NullProgressMonitor());
}
}
}
}
}
});
display.syncExec(new Runnable() {
public void run() {
workbench.close();
}
});
}
} catch (IllegalStateException e) {
// ignore
}
}
}
It is set, as you said, in the IApplication:
public class IPEApplication implements IApplication {
public Object start(IApplicationContext context) throws Exception {
final Display display = PlatformUI.createDisplay();
Runtime.getRuntime().addShutdownHook(new ShutdownHook()); }
// start workbench...
}
}
You should override the preShutdown method on your class that extends WorkbenachAdvisor. Return false to halt the shutdown process or true to continue.
I tried the following code, that I execute from my IApplication implementor start() method, before the RCP application is actually launched:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
if (PlatformUI.isWorkbenchRunning()) {
PlatformUI.getWorkbench().close();
}
logger.info("Shutdown request received");
cleanup();
}
});
Where cleanup() closes the connection to the database. Close should ask the users to save if there is any documents open.
This question already has answers here:
How to start/stop/restart a thread in Java?
(9 answers)
Closed 7 years ago.
I have created a program which searches for files in a source folder. If it finds any file, it processes that file and moves it to a destination folder, then looks for a new file in the source folder. It has to keep on checking the source folder for a file.
I have used a thread to look for files in the source folder. The problem I am facing is whenever any exception is thrown during file processing, the thread gets stopped. I want the thread to be running even if an exception is thrown. It has to move the file that caused the error to some other folder and look for a new file in the source folder. How can I make the thread keep on running?
Eg:
public void run() {
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){
...
}
Update :
I should be more clear in my question. Actually there are 4 source folders and 4 destination folders. I have to perform the same operation in each source & destination pair. So i have created 4 threads in one class and do the operation in separate class.
class MainClass
{
public static void main(String[] args){
for(int i=0;i<4;i++){
SearchClass search = new SearchClass();
Thread thread = new Thread(search);
thread.start();
}
}
}
class SearchClass
{
public void run() {
try {
searchfile();
} catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){ ... } }
All the thread wont stop running eventhough it caught any exception in middle. How can i do that?
If a thread is dying due to an uncaught exception, the answer is simple: catch the exception at an appropriate place so that you can keep going. Either catch the exception within your searchfile method, or make the run method call searchfile in a loop.
If you want your thread to keep running use a loop.
public void run() {
while(!Thread.interrupted())
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
Inside your catch, you can move the file to the error folder then create a new object of the same thread and start it again.
unless i got you wrong, your code is missing the "keep running" nature, i.e. you need to have a loop somewhere:
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(4);
// for each of your 4 folders
while (true) {
Future<File> searchResult = service.submit(new SearchTask());
try {
File foundFile = searchResult.get();
// handle found file
} catch (Exception e) {
// handle exception
}
}
}
private static class SearchTask implements Callable<File> {
#Override
public File call() {
return searchFile();
}
public File searchFile() {
// search & return found file
}
}
note that this is just a very simple extension of your example. it is still missing the parametrization of the SearchTask to actually be specific for a folder, handling of files & exceptions, etc. as mentioned in previous answers, your SearchTask should implement Runnable (i prefer Callable...), and IMHO it's always better to use an ExecutorService than to spawn threads manually. hope this helps...
I'm not entirely sure if this will work, yet here's a try.
public void run() {
try {
searchFile();
} catch(Exeption e) {
e.printStackTrace();
if(!Thread.currentThread().isAlive())
Thread.currentThread().start();
}
}
you said that the exception may be thrown during file process , so i put the processFile() in a try-catch block. but if it may be thrown during search, you may put it in a try-catch too.
public void run() {
while(!terminated) {
findNextFile();
try {
processFile();
} catch {
// handle error
}
}
}
Here are my assumptions based on your question and your clarification:
Each thread, in the run() method, only calls searchfile() once and not in a loop
your searchfile() method has a loop in it and you want that loop to continue running even if an exception is thrown in it.
you have some way of initializing each thread that you aren't showing us (and that isn't terribly important for this specific quiestion)
searchfile() does not declare that it throws any Exception
You aren't using a logging framework, but are instead using System.out (although using a logging framework is a Really Good Idea
Java 5 is OK (otherwise you'll have to use a different for() loop below
With these assumptions, you don't want to plan to catch an Exception in your run() method except for the purpose of logging that something went very wrong:
public void run() {
try {
searchfile();
} catch (RuntimeException e) {
System.out.println("Something went very wrong! Unexpected RuntimeException");
e.printStackTrace();
}
}
Note that the code catches RuntimeException. Always catch the most specific Exception that will do what you need. Then what you need is something such as the following in your searchfile() method:
File[] files = directory.listFiles();
for (File file : files) {
try {
// Do your normal file/directory processing here
} catch (Exception e) {
System.out.println("Exception processing file " + file.getName() + " " + e);
// Move "file" to another area
}
}
Since you are trapping unexpected Exceptions in the main loop of your Thread, your thread will continue processing after handling the Exception.
You can easily go with a workaround. Just run the needed logic for some amount of times and finish the job based on some criteria.
public class ThreadRestartWorkaround extends Thread {
public static void main(String[] args) {
ThreadRestartWorkaround th = new ThreadRestartWorkaround(5);
th.start();
}
private int maxCycles;
private int currentCycle;
public ThreadRestartWorkaround(int maxCycles) {
this.maxCycles = maxCycles;
}
#Override
public void run() {
while(executeSomeLogicUntilReachingTheLimit());
System.out.println("Finished due to exceeding the maxCycles config");
}
private boolean executeSomeLogicUntilReachingTheLimit() {
currentCycle++;
System.out.println("Executing logic for " + currentCycle + " time");
return currentCycle < maxCycles;
}
}
And the output is
Executing logic for 1 time
Executing logic for 2 time
Executing logic for 3 time
Executing logic for 4 time
Executing logic for 5 time
Finished due to exceeding the maxCycles config