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.
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.
It seems like a duplicate question of how to kill a process already running on that port, but it is a different question. When I killed the process and restart it, it still gives me that error message, seems like Netbeans has a problem, and the error message got stuck and keeps appearing even when the port is not in use.
I've used the tool at : http://www.yougetsignal.com/tools/open-ports/ to check the port : 6600
Here is what it says :
My code looks like the following :
import java.io.*;
import java.util.*;
import com.sun.net.httpserver.*;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import Utility.*;
public class Http_Server
{
static int Port=6600,Thread_Count=50,Resume_Count=0; // 8080
InetSocketAddress addr;
HttpServer server;
static String App_Id="Resume_App";
static Resume_Loader Resume_loader;
static Get_Time Timer=new Get_Time();
static Vector<String> Current_Keywords_Vector=new Vector();
static boolean Debug_B=true;
public Http_Server(int Port)
{
if (Port>-1) this.Port=Port;
Srart_Server();
}
void Srart_Server()
{
try
{
Resume_loader=new Resume_Loader();
addr=new InetSocketAddress(Port);
server=HttpServer.create(addr,0); // Line : 34
server.createContext("/"+App_Id,new MyHandler(server));
server.setExecutor(Executors.newCachedThreadPool());
server.start();
Out("Server is listening on port : "+Port);
}
catch (Exception e)
{
Resume_App.Save_To_Log(e.toString()+"\n"+Tool_Lib_Simple.Get_Stack_Trace(e));
e.printStackTrace();
Out(e.toString());
}
}
private static void out(String message) { System.out.print(message); }
private static void Out(String message) { System.out.println(message); }
public static void main(String[] args) { Http_Server Demo=new Http_Server(-1); }
}
It was running fine yesterday, but this morning I changed :
InetSocketAddress addr; to static InetSocketAddress addr;
HttpServer server; to static HttpServer server;
When I ran it, I got the following error message :
Server is listening on port : 6600
java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:437)
at sun.nio.ch.Net.bind(Net.java:429)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at sun.net.httpserver.ServerImpl.<init>(ServerImpl.java:100)
at sun.net.httpserver.HttpServerImpl.<init>(HttpServerImpl.java:50)
at sun.net.httpserver.DefaultHttpServerProvider.createHttpServer(DefaultHttpServerProvider.java:35)
at com.sun.net.httpserver.HttpServer.create(HttpServer.java:130)
at Http_Server.Srart_Server(Http_Server.java:34)
at Http_Server.<init>(Http_Server.java:24)
at Http_Server.main(Http_Server.java:51)
Then I realize if they are static, they might keep them selves in memory and occupy the port, so I changed them back to non-static like the above code. But now when I run it, the error message keeps appearing, and in Netbeans there is a "notification" saying something like : "package-info.class is in wrong place, delete it or put it in the right sub directory ..." don't remember the exact wording. But when I open the url, the web page works fine as if there is no error message, and when I stop the server the page won't appear as it supposed to be.
So it seems like a Netbeans 8.0.2 malfunctioning, but I don't know how to make the error message not appear, or as it suggested how to delete "package-info.class" or put it into the correct sub dir, I can't even find where it is, how to fix it ?
Regarding :
there is a "notification" saying something like : "package-info.class is in wrong place, delete it or put it in the right sub directory ..." don't remember the exact wording
Please make it happen again and copy and paste or screenshot the exact wording into your question.
I think it would be much better to explicitly call shutdown() on your ExecutiveService and stop(1) on your HttpServer rather than hoping garbage collection will do it. And it would allow you to control print some messages confirming it.
eg.
InetSocketAddress addr = new InetSocketAddress(6600);
ExecutorService es = Executors.newCachedThreadPool();
HttpServer server = HttpServer.create(addr, 0);;
server.createContext("/foo", new HttpHandler() {
#Override
public void handle(HttpExchange he) throws IOException {
String response = "My Response";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.getBytes());
os.close();
}
});
server.setExecutor(es);
server.start();
System.out.println("Press enter to stop server.");
// block waiting for user to press enter.
System.in.read();
System.out.println("Shutting down");
server.stop(1);
es.shutdownNow();
System.out.println("should be shutdown now.");
Also at the bottom of netbeans there is a status line.
If you see this you need to click the little x to stop whatever process you launched but perhaps forgot about.
So I created a basic client-server program in java. It starts out like this:
Client connects to Server
Server asks for Client's name
Client responds with name
Server greets Client
After this, Client speaks and the Server repeats the words back
I got this to work without too much trouble using this tutorial. The problem comes whenever I try to introduce multiple clients. I thought that it would work because I'm using multiple threads, however, the second clients just hangs until the first client quits and then it starts it work (the server does accept input from the second client, but it doesn't respond with anything until the first client quits).
Here is the code I'm using:
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket listener;
public Server(int port) throws IOException {
listener = new ServerSocket(port);
}
public void run() {
while(true) {
try {
Socket server = listener.accept();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("What is your name?");
DataInputStream in = new DataInputStream(server.getInputStream());
String user_name = in.readUTF();
out.writeUTF("Hello "+user_name);
while(true) {
String client_message = in.readUTF();
out.writeUTF(client_message);
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int port = 6006;
try {
Thread t = new Server(port);
t.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Can someone explain what I'm doing wrong?
I have looked at the using Runnable instead of Extends Thread, but I ran into even more problems there, so I want to try and work with this first.
Incoming connections are only handled by the line listener.accept();. But after you got a client connected, you're stuck in the while loop. You need to create a new Thread (or Runnable executed on an ExecutorService if you expect high load), and start it, then immediately accept the next connection.
In a nutshell, this is what is going wrong.
You are using exactly ONE thread as the server.
Blocking this thread when you call listener.accept()
This is what you need to do:
Create two classes
1: Server - Similar to what you have now, but instead of doing the actual work of acting as an echo server, it just spawns a new Thread which starts listening on a NEW PORT (which you can select randomly), and sends the client the address for this new port. The client will then get the new port number and would try to connect to the server on the new port.
2: The Echo thread - This starts a new listener on the port passed, and does the job of echoing to whoever is listening.
OR:
You start a UDP server rather than a TCP server, and all this will not matter then, but that is out of the purview of this specific question.
On my machine, the following code compiles within Eclipse but throws an exception within Netbeans. The error message says "Exception in thread "main" java.net.BindException: Address already in use".
What is the proper configuration within Netbeans to make this code compile? It seems like the problem has to do with the fact that I have two main functions. If I start running either one of the apps, the second will fail to start, throwing the exception posted above.
Server.java
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
Server myServ = new Server();
myServ.run();
}
public void run() throws Exception {
ServerSocket mySS = new ServerSocket(9999);
Socket SS_accept = mySS.accept();
InputStreamReader mySR = new InputStreamReader(SS_accept.getInputStream());
BufferedReader myBR = new BufferedReader(mySR);
String temp = myBR.readLine();
System.out.println(temp);
}
}
Client.java
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
Client myCli = new Client();
myCli.run();
}
public void run() throws Exception {
Socket mySkt = new Socket("localhost", 9999);
PrintStream myPS = new PrintStream(mySkt.getOutputStream());
myPS.println("Hello server");
}
}
The problem is due to the fact that you left one instance of your server running and then started another one.
The way to achieve what I want is to right-click on the particular class (ex. Server.java) that I want to run and select "Run this file". This enables me to run only the Server app. Then, do the same process for the other file, Client.java.
However, Netbeans is somewhat confusing/deceiving in this particular circumstance. What Netbeans does is it runs the Server process, but labels that process as the name of the project (ex. MyTestNetworkingProject) and puts a run number on it, thus giving us MyTestNetworkingProject run #1 (it actually leaves out the #1 on the first process). Then, if I go to the Client.java file and select "Run this file", it generates a second process, MyTestNetworkingProject run #2. It then generates a second results window down at the bottom of the screen, as it generates these in new tabs as new processes get created.
Because of the nature of my specific code, what I wanted to see in my results window to confirm that my application was working was I wanted to observe the Server.java results window (which in this case is MyTestNetworkingProject run #1). Given my exact sequence of steps outlined above of running the different files, run #2 is the last run process and thus the tab on top, covering the run #1 tab. I can click on run #1 and see the results I was hoping to see in the console ("Hello server"), but I just have to know/remember that MyTestNetworkingProject run #1 represents the Server app and not the Client app.
Uncool, IMO.
If you write this in Windows OS,you can use "netstat -nao" to see which process use the 9999 port.If it is some unimportant process,you can kill this process.Otherwise you can change the port of the pragram.
I change the port address and it work for me in the Neat Beans IDE . This problem will come if we used the same port address for other one times . so to fix this error you have to change the port address and I am sure it will work
Server.java
public class SocServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5001);
Socket client = server.accept();
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeBytes("Hello Sockets\n");
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client.java
public class SocClient {
public static void main(String[] args) {
try {
Socket socClient = new Socket("localhost", 5001);
InputStream is = socClient.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String receivedData = br.readLine();
System.out.println("Received Data: " + receivedData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
refer above code and it works for me..
I did try the method catch and solved the problem.
I am trying to get a rmi connection going. I have ran into many security issues but have been unable to find a way past all this. I execute my jar file with:
java -Djava.security.policy=java.security.AllPermission -jar "myjarfile"
The code I have been using to create this is:
public class server
{
public static void main(String args[])throws Exception
{
if (System.getSecurityManager() == null)
System.setSecurityManager ( new RMISecurityManager() {
public void checkConnect (String host, int port) {}
public void checkConnect (String host, int port, Object context) {}
});
try
{
sampleserverimpl server = new sampleserverimpl();
System.out.println("SERVER IS WAITING");
LocateRegistry.createRegistry(2020);
//Runtime.getRuntime().exec("rmiregistry 2020");
Naming.rebind("//localhost:2020/SERVER", server);
}
catch(Exception e)
{
System.out.println(e);
}
}
};
The error trace I am receiving is:
Exception in thread "RMI TCP Connection(idle)" java.security.AccessControlExcept
ion: access denied (java.net.SocketPermission 127.0.0.1:31199 accept,resolve)jav
a.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.io.EOFException
I have tried different ways to get around this, can anyone see the issue here?
Thanks
-Djava.security.policy accepts a URL which points to a policy file which in turn contains the permissions. So you should have: -Djava.security.policy=/some/path/my.policy as the JVM argument where the my.policy file contains:
grant {
permission java.security.AllPermission;
};
Also, in order to avoid the NULL check present in your code and the manual creation of a SecurityManager, you can request a SecurityManager be automatically installed for your application by passing the JVM switch: -Djava.security.manager.
Your final JVM invocation should look like:
java -Djava.security.manager -Djava.security.policy=/some/path/my.policy
This is two separate exceptions. The first is a permission problem. The second one, the EOFException, could have any of a number of causes. I would need to see java -version and the complete stack trace to assist further.