I'm wondering how to log information when a server has successfully started. I cannot do this as simple as that:
createServer().start(Exit.NEVER);
System.out.println("Server is running...");
because the instruction createServer().start(Exit.NEVER) doesn't return back. This is a call to external library that uses a method with a loop similar to while(true).
I cannot also run the server in a new thread and then log information about successful start because the server may throw exception and hence there was a failure.
public void start () {
new Thread("Server") {
#Override
public void run() {
try {
createServer().start(Exit.NEVER);
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
}.start();
System.out.println("Server is running...");
}
Last solution I can think of is to wait a couple of second after createServer().start(Exit.NEVER) and then log the successful start as there was no exception thrown. This is not a perfect solution as we can wait for example 5 seconds and the log the successful start but one second later the server may throw exception.
How do I then can tell whether the server has started successfully and hence log this information?
EDIT
The server I'm using is Takes https://github.com/yegor256/takes.
Related
So I currently have a lot of code, it will be difficult to break it all down into an SSCCE but maybe I will attempt to do so later if necessary.
Anyways, here is the gist: I have two processes communicating via RMI. It works. However I want to be able continue if the communcation if the host process (JobViewer) exits and then returns all in the life of the client process (Job).
Currently I have the binded name saved to a file everytime a Job starts up, and the JobViewer opens this file on startup. It works great, the correct binded name works. However, I get a NotBoundException every time I try to resume communication with a Job that I know for fact is still running when the JobViewer restarts.
My JobViewer implements an interface that extends Remote with the following methods:
public void registerClient(String bindedName, JobStateSummary jobSummary) throws RemoteException, NotBoundException;
public void giveJobStateSummary(JobStateSummary jobSummary) throws RemoteException;
public void signalEndOfClient(JobStateSummary jobSummary) throws RemoteException;
And my Job also implements a different interface that extends Remote with the following methods:
public JobStateSummary getJobStateSummary() throws RemoteException;
public void killRemoteJob() throws RemoteException;
public void stopRemoteJob() throws RemoteException;
public void resumeRemoteJob() throws RemoteException;
How do I achieve this? Here is some of my current code that inits the RMI if it helps...
JobViewer side:
private Registry _registry;
// Set up RMI
_registry = LocateRegistry.createRegistry(2002);
_registry.rebind("JOBVIEWER_SERVER", this);
Job side:
private NiceRemoteJobMonitor _server;
Registry registry = LocateRegistry.getRegistry(hostName, port);
registry.rebind(_bindedClientName, this);
Remote remoteServer = registry.lookup(masterName);
_server = (NiceRemoteJobMonitor)remoteServer;
_server.registerClient(_bindedClientName, _jobStateSummary);
I get a NotBoundException every time I try to resume communication with a Job that I know for fact is still running when the JobViewer restarts.
That can only happen if the JobViewer didn't rebind itself when it started up. More usually you get a NoSuchObjectException when you use a stale stub, i.e. a stub whose remote object has exited. In this case you should reaquire the stub, i.e. redo the lookup().
Why is the client binding itself to a Registry? If you want to register a callback, just pass this to the registerClient() method instead of the bind-name, and adjust its signature accordingly (using the client's remote interface as the parameter type). No need to have the server doing a lookup to the client Registry. No need for a client Registry at all.
My solution was to have the Job ping the JobViewer every so often:
while (true) {
try {
_server.ping();
// If control reaches here we were able to successfully ping the job monitor.
} catch (Exception e) {
System.out.println("Job lost contact with the job monitor at " + new Date().toString() + " ...");
// If control reaches we were unable to ping the job monitor. Now we will loop until it presumably comes back to life.
boolean foundServer = false;
while (!foundServer) {
try {
// Attempt to register again.
Registry registry = LocateRegistry.getRegistry(_hostName, _port);
registry.rebind(_bindedClientName, NiceSupervisor.this);
Remote remoteServer = registry.lookup(_masterName);
_server = (NiceRemoteJobMonitor)remoteServer;
_server.registerClient(_bindedClientName, _jobStateSummary);
// Ping the server for good measure.
_server.ping();
System.out.println("Job reconnected with the job monitor at " + new Date().toString() + " ...");
// If control reaches here we were able to reconnect to the job monitor and ping it again.
foundServer = true;
} catch (Exception x) {
System.out.println("Job still cannot contact the job monitor at " + new Date().toString() + " ...");
}
// Sleep for 1 minute before we try to locate the registry again.
try {
Thread.currentThread().sleep(PING_WAIT_TIME);
} catch (InterruptedException x) {
}
} // End of endless loop until we find the server again.
}
// Sleep for 1 minute after we ping the server before we try again.
try {
Thread.currentThread().sleep(PING_WAIT_TIME);
} catch (InterruptedException e) {
}
} // End of endless loop that we never exit.
I am trying to stop Tomcat Service and a custom service (which i have created in windows) using JNA in my Java program. Sometimes Tomcat service takes longer time to stop.
W32Service service = null;
long startTime = System.currentTimeMillis();
boolean isStopped = false;
try
{
W32ServiceManager serviceManager = new W32ServiceManager();
serviceManager.open(Winsvc.SC_MANAGER_ALL_ACCESS);
service = serviceManager.openService(serviceName, Winsvc.SC_MANAGER_ALL_ACCESS);
//service.queryStatus().dwWaitHint = 60000;
synchronized (service) {
service.stopService();
}
service.close();
} catch (Exception ex)
{
System.out.println("Timeout happened.");
}finally{
if(null != service.getHandle()){
while(!isStopped){
if(service.queryStatus().dwCurrentState == Winsvc.SERVICE_STOPPED
|| System.currentTimeMillis()-startTime >= Constants.SERVICE_STOP_WAIT_TIME){
isStopped=true;
}
}
if(System.currentTimeMillis()-startTime >= Constants.SERVICE_STOP_WAIT_TIME){
System.out.println("Service Continuing.....");
throw new ServiceNotStoppedException("Service Not Stopped after 2 minutes");
}else{
System.out.println("Service Stopped");
isStopped=true;
}
}else{
System.out.println("Service Stopped.");
isStopped=true;
}
}
In the above code, i am catching a Runtime Exception thrown which give the below message.
java.lang.RuntimeException: Timeout waiting for service to change to a non-pending state.
at com.sun.jna.platform.win32.W32Service.waitForNonPendingState(W32Service.java:162)
at com.sun.jna.platform.win32.W32Service.stopService(W32Service.java:98)
at com.taskkill.sample.Sample.stopService(Sample.java:32)
at com.taskkill.sample.Sample.main(Sample.java:12)
I have checked previous threads on similar topic but couldn't find any resolution. It is waiting for a default time and throwing error. Is there any way we can extend this time dwWaithint? (I have tried //service.queryStatus().dwWaitHint = 60000;) but it doesn't work. Tomcat Service is eventually stopping/Hung while using this method. This works but is there a better way to handle the RunTimeException?
If i use command prompt process by the following code, it returns exit code "0" immediately, whereas the process is still stopping in the background.
String[] stopTomcat = { "sc", "stop", "Tomcat7" };
Process tomcatProcess = Runtime.getRuntime().exec(stopTomcat);
Here's what I know so far (please correct me):
In the RabbitMQ Java client, operations on a channel throw IOException when there is a general network failure (malformed data from broker, authentication failures, missed heartbeats).
Operations on a channel can also throw the ShutdownSignalException unchecked exception, typically an AlreadyClosedException when we tried to perform an action on the channel/connection after it has been shut down.
The shutting down process happens in the event of "network failure, internal failure or explicit local shutdown" (e.g. via channel.close() or connection.close()). The shutdown event propagates down the "topology", from Connection -> Channel -> Consumer, and when the Channel it calls the Consumer's handleShutdown() method gets called.
A user can also add a shutdown listener which is called after the shutdown process completes.
Here is what I'm missing:
Since an IOException indicates a network failure, does it also initiate a shutdown request?
How does using auto-recovery mode affect shutdown requests? Does it cause channel operations to block while it tries to reconnect to the channel, or will the ShutdownSignalException still be thrown?
Here is how I'm handling exceptions at the moment, is this a sensible approach?
My setup is that I'm polling a QueueingConsumer and dispatching tasks to a worker pool. The rabbitmq client is encapsulated in MyRabbitMQWrapper here. When an exception occurs polling the queue I just gracefully shutdown everything and restart the client. When an exception occurs in the worker I also just log it and finish the worker.
My biggest worry (related to Question 1): Suppose an IOException occurs in the worker, then the task doesn't get acked. If the shutdown does not then occur, I now have an un-acked task that will be in limbo forever.
Pseudo-code:
class Main {
public static void main(String[] args) {
while(true) {
run();
//Easy way to restart the client, the connection has been
//closed so RabbitMQ will re-queue any un-acked tasks.
log.info("Shutdown occurred, restarting in 5 seconds");
Thread.sleep(5000);
}
}
public void run() {
MyRabbitMQWrapper rw = new MyRabbitMQWrapper("localhost");
try {
rw.connect();
while(!Thread.currentThread().isInterrupted()) {
try {
//Wait for a message on the QueueingConsumer
MyMessage t = rw.getNextMessage();
workerPool.submit(new MyTaskRunnable(rw, t));
} catch (InterruptedException | IOException | ShutdownSignalException e) {
//Handle all AMQP library exceptions by cleaning up and returning
log.warn("Shutting down", e);
workerPool.shutdown();
break;
}
}
} catch (IOException e) {
log.error("Could not connect to broker", e);
} finally {
try {
rw.close();
} catch(IOException e) {
log.info("Could not close connection");
}
}
}
}
class MyTaskRunnable implements Runnable {
....
public void run() {
doStuff();
try {
rw.ack(...);
} catch (IOException | ShutdownSignalException e) {
log.warn("Could not ack task");
}
}
}
I am not sure what is happening here. I am starting a RMI server in a separate JVM. While connecting to the instance calling the remote method, the method get stuck after a very short time. The execution continues as soon as I shutdown the client process.
What am I doing wrong?
class Client
...
//name some kind of name
String name= "HelloService";
//libname points to a runnable jar with the server class as main class
ProcessBuilder jvm= new ProcessBuilder(javaPath, "-jar", libname, "-n", name);
jvm.start();
//Waiting for RMI server to start
try { Thread.sleep(10000); } catch ...
try {
Registry registry= LocateRegistry.getRegistry(1199);
//String as input and String as output
IRemoteService<String, String> service= (IRemoteService<String, String>) registry.lookup(name)
String returnVal= service.execute("SomeValue");
return returnVal;
} catch ...
Following by the server code snip. The server code is packed in a runnable jar with itself as the MainClass.
class Server implements IRemoteService<String, String>
//Is not returning a value, due the fact that I liked to examine the behaviour of
//this method. Doing this by running an infinite loop.
public String execute(String str) {
log.info("Running doExectue from "+getClass().getSimpleName());
int i=0;
while(true) {
i++;
log.info(String.valueOf(i));
}
}
protected static void register(String name, IRemoteService service) {
try {
IRemoteService rsStub= (IRemoteService) UnicastRemoteObject.exportObject(service,0);
Registry registry= LocateRegistry.getRegistry(1199);
try {
registry.bind(name, rsStub);
} catch (ConnectException ce) {
registry= LocateRegistry.createRegistry(1199);
registry.bind(name, rsStub);
}
} catch ...
}
public static void main(String[] args) {
String rmiName= args[1];
IRemoteService<String, String> service= (IRemoteService<String, String>) new Server();
register(rmiName, service);
}
Now if I start the client the log file displayes 36 runs of the loop in method "execute". Than it stops. There is no other client getting this object or calling this method too.
It starts a again and is running forever as soon as I killed the Client process.
For me it looks like that the client is blocking the execution of the remote server methods. But I have no clue how to overcome this situation.
Thanks for any help in advance,
Danny
What you describe is impossible. The client can't block the server while the server is executing a remote method. Find another explanation.
thanks for your support. You are right a RMI client can't block the server. So I was really confused. But I found the failure.
It about the process is writing to the console. As soon as the buffer is full the process is stopping to wait for someone collecting the output.
After I removed the ConsoleAppender from the log configuration the job runs as expected.
I'm using java mail to connect with gmail and I'm keeping one store for the all actions. (Store is set to static.).
And the IMAPFolder instances are attached with imap listeners. So the folders are kept always open. (Folder close is not called any time) But while running after few minutes I'm getting FolderClosedException. After that exception, though the folder can be reopened but the idle() command cannot be issued again, which will result in NullPointerException.
Is there any wrong with keeping folders open always?
Thanks in advance.
===================================================================
[Edit]
Here I'm pasting the actual code i'm doing POC with. The NullPointerException comes when I check .isConnected() after reconnecting the store. Below is the run method of Thread which sends idle() command to the store.
public void run() {
while (true) {
try {
System.out.println("Checking connectivity...");
if (store.isConnected()) {
store.idle();
System.out.println("IDLE send...");
} else {
Thread.sleep(5000);
System.out.println("Tring to connect...");
//Trying to reconnect to the store.
store.connect();
System.out.println("Previous store connected again");
}
} catch (InterruptedException ex) {
System.out.println("InterruptedException...");
} catch (StoreClosedException ex) {
System.out.println("StoreClosedException...");
} catch (MessagingException ex) {
System.out.println("MessagingException...");
}
}
}
Here is the stack trace:
Exception in thread "Thread-1" java.lang.NullPointerException
at com.sun.mail.imap.IMAPStore.waitIfIdle(IMAPStore.java:1881)
at com.sun.mail.imap.IMAPStore.getStoreProtocol(IMAPStore.java:946)
at com.sun.mail.imap.IMAPStore.isConnected(IMAPStore.java:1347)
at pocworks.POCWorks1$IDLEThread.run(POCWorks1.java:125)
Generally, mail servers don't like you to keep connections open when you're not using them. Typical IMAP servers will give you 30 minutes before they time out an unused connection; Gmail may be more aggressive.