My application use rmi for serve client request to manipulate data on a database (using JDBC). I would like that skeleton run a thread for each client's operation request. I need just to to something like
public MySkeleton implement MyInterface {
public string method1() {
myThread.start();
}
or something else?
You don't need to do anything special whatsoever, the RMI framework takes care of spinning off new threads automatically for you. Try it with the simplest server possible, you will see that every time a new client connects it is always able to connect to the server straightaway:
public interface Server extends java.rmi.Remote {
void doIt () throws java.rmi.RemoteException;
}
public class ServerImpl extends java.rmi.server.UnicastRemoteObject implements Server {
public ServerImpl() throws java.rmi.RemoteException {
super();
}
public void doIt () {
System.out.println ("Starting in " + Thread.currentThread().getName());
try { Thread.sleep(10000); } catch(InterruptedException t) {}
System.out.println ("Stopping in " + Thread.currentThread().getName());
}
public static void main (String[] argv) throws Exception {
java.rmi.registry.LocateRegistry.createRegistry(1099);
java.rmi.Naming.rebind ("//localhost/Server", new ServerImpl ());
}
}
public class Client {
public static void main(String[] argv) throws Exception {
((Server) java.rmi.Naming.lookup("Server")).doIt();
}
}
I would like that skeleton run a thread for each client's operation request.
RMI already does that.
I need just to to something like
No you don't. Just write the method normally. RMI will multithread it for you.
Related
I'm trying to have my program be ready to send a message inputted by user and listen for an incoming message simultaneously.
I tried using Executor Service but it always gives an error that says the functions can't be static or void.
Because of this, I tried making my two functions (that I need to run simultaneously) non-static and return a String that I wouldn't do anything with. Unfortunately, I still get an error and I think it due to the fact that my functions use the static class variables declared prior.
Here's the error I get:
EchoClient.java:66: error: <anonymous EchoClient$1> is not abstract
and does not override abstract method call() in Callable
callables.add(new Callable() {
Here's me the code simplified and without the Executor Service:
class EchoClient
{
public static DatagramSocket socket; public static InetAddress receiver; public static int port;
public static void main( String args[] ) throws Exception
{
//Initialization of socket, receiver and port
while(true)
{
sendMessage();
receiveMessage();
}
}
public static void sendMessage() throws IOException
{
//Actions to send message
}
public static void receiveMessage() throws IOException
{
//Actions to receive message
}
}
The functions I want to run simultaneously are sendMessage() and receiveMessage(). Right now I'm using a while loop so the program can only send a message before waiting to receive one and vice versa.
I'm really not that familiar with Java, so I'm just hoping for a simple implementation of Executor Service.
Since you know that you will need 2 Threads you can use a FixedThreadPool:
Executor executor = Executors.newFixedThreadPool(numberOfThreads);
To execute a Task you just need to call the execute methode with your runnable as a parameter:
executor.execute(() -> {
while (true) {
try {
sendMessage();
} catch (IOException e) {
e.printStackTrace();
break;
}
}
});
As described in a separate question, when using Undertow, all the processing should be done in a dedicated Worker thread pool, which looks like this:
public class Start {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addListener(8080, "localhost")
.setHandler(new HttpHandler() {
public void handleRequest(HttpServerExchange exchange)
throws Exception {
if (exchange.isInIoThread()) {
exchange.dispatch(this);
return;
}
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender()
.send("Hello World");
}
})
.build();
server.start();
}
}
I understand that BlockingHandler can be used for explicitly telling Undertow to schedule the request on a dedicated thread pool for blocking requests. We could adapt the above example by wrapping the HttpHandler in an instance of BlockingHandler, like so:
.setHandler(new BlockingHandler(new HttpHandler() {
This would work for calls that we know are always blocking.
However, in case some code is non-blocking most of the time, but sometimes requires a blocking call, how to turn that blocking call into a non-blocking one? For example, if the requested value is present in cache, the following code would not block (it's just fetching from some Map<>), but if it's not, it has to be fetched from the database.
public class Start {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addListener(8080, "localhost")
.setHandler(new HttpHandler() {
public void handleRequest(HttpServerExchange exchange)
throws Exception {
if (exchange.isInIoThread()) {
exchange.dispatch(this);
return;
}
if (valueIsPresentInCache(exchange)) {
return valueFromCache; // non-blocking
} else {
return fetchValueFromDatabase(); // blocking!!!
}
}
})
.build();
server.start();
}
}
According to the docs, there is a method HttpServerExchange.startBlocking(), but according to JavaDoc, unless you really need to use the input stream, this call is still a blocking one.
Calling this method puts the exchange in blocking mode, and creates a
BlockingHttpExchange object to store the streams. When an exchange is
in blocking mode the input stream methods become available, other than
that there is presently no major difference between blocking an
non-blocking modes
How would one turn this blocking call into a non-blocking one?
The correct way is to actually do the logic in the IO thread, if it is non-blocking. Otherwise, delegate the request to a dedicated thread, like this:
public class Example {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addListener(8080, "localhost")
.setHandler(new HttpHandler() {
public void handleRequest(HttpServerExchange exchange)
throws Exception {
if (valueIsPresentInCache(exchange)) {
getValueFromCache(); // non-blocking, can be done from IO thread
} else {
if (exchange.isInIoThread()) {
exchange.dispatch(this);
// we return immediately, otherwise this request will be
// handled both in IO thread and a Worker thread, throwing
// an exception
return;
}
fetchValueFromDatabase(); // blocking!!!
}
}
})
.build();
server.start();
}
}
I'm following Jenkov's tutorial on vertx. Here I have two files:
MyVerticle.java:
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
public class MyVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) {
System.out.println("MyVerticle started!");
}
#Override
public void stop(Future stopFuture) throws Exception {
System.out.println("MyVerticle stopped!");
}
}
and VertxVerticleMain.java:
import io.vertx.core.Vertx;
public class VertxVerticleMain {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle());
}
}
After running VertxVerticleMain.java, I saw "MyVerticle started!" in Eclipse's console but don't know how to call stop in MyVerticle.
Jenkov said that The stop() method is called when Vert.x shuts down and your verticle needs to stop. How exactly do I shut down my Vert.x and stop this verticle? I want to see MyVerticle stopped! in the console.
From the Vert.x docs:
Vert.x calls this method when un-deploying the instance. You do not call it yourself.
If you run Vert.x from a main method and you terminate the JVM process (by clicking the 'stop' button in Eclipse, for example), Vert.x probably isn't signaled to undeploy the verticles, or the JVM terminates before Vert.x has time to undeploy the verticles.
You can do a number of things to ensure that the verticle will be undeployed and the stop() method will be called:
Start the Verticle using the vertx commandline. When you stop the process (or tell vert.x to stop), Vert.x will make sure that all verticles are undeployed.
You can programmatically undeploy the deployed verticles by fetching the list of deploymentId's and calling undeploy for all id's:
vertx.deploymentIDs().forEach(vertx::undeploy);
You can programmatically tell Vert.x to stop:
vertx.close();
You can add a shutdown hook to make sure that one of the options above is executed on JVM termination:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
vertx.close();
}
});
You can either programmatically undeploy the verticle by calling the Vert.x API, or just stop the Java process, which in term triggers the Vert.x process to stop.
By the way, it's worth asking yourself whether it's really necessary that the stop() method is always called when the process running the verticle stops. You can never be sure that that happens; when the process is forced to stop or killed, the stop() method might not be called.
your code should add super.stop() and super.start() function like that:
public class MyVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) {
//must call super.start() or call startFuture.complete()
super.start(startFuture);
System.out.println("MyVerticle started!");
System.out.println("Verticle_stopFuture.start(): deployId=" + context.deploymentID());
}
#Override
public void stop(Future stopFuture) throws Exception {
//must call super.stop() or call stopFuture.complete()
super.stop(stopFuture);
System.out.println("MyVerticle stopped!");
}
}
and VertxVerticleMain.java:
public class VertxVerticleMain {
static String verticle_deployId;
public static void main(String[] args) throws InterruptedException {
System.out.println("start main(): thread="+Thread.currentThread().getId());
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new MyVerticle(), new Handler<AsyncResult<String>>(){
#Override
public void handle(AsyncResult<String> asyncResult) {
if (asyncResult.succeeded()) { // khi startFuture.complete() đc gọi
System.out.println("asyncResult = DeployId =" + asyncResult.result());
verticle_deployId = asyncResult.result();
} else { //khi startFuture.fail() đc gọi
System.out.println("Deployment failed!"); //vì chưa đc cấp id
}
}
});
// waiting for Verticle context is allocate by Vertx
Thread.currentThread().sleep(500);
Set<String> deploymentIDs = vertx.deploymentIDs();
System.out.println("============== (sleeped 500ms wait for Context allocated), list of deploymentIDs: number Deployments =" + deploymentIDs.size());
for(String depId: deploymentIDs){
//
System.out.println(depId);
}
//close verticle here
vertx.undeploy(verticle_deployId);
}
}
I am new to java rmi. And I want to create a rmi program as a service. For example, I got a remote interface:
public interface Handler implements Remote {
public void insert (String str) throws RemoteException, NotBoundException;
}
public class HandlerImpl extends UnicastRemoteObject implements Handler {
public HandlerImpl (int port) {
super(port);
}
public void insert (String str) throws RemoteException, NotBoundException {
// insert string to a file
}
}
And I also have a class to register it:
class Server {
public Server () {
Registry svcReg = LocateRegistry.createRegistry(999);
Handler handler = new HandlerImpl (1000);
svcReg.rebind("insert", handler);
}
}
Now if a write the program with
Server server = new Server();
When the program terminates, the service is gone. What is proper way to make Server like a service that it runs in the background and the "remote method" can still be called?
Thanks!
You can use the Apache Commons Daemon to accomplish that.
I created a UDP server. Here's a skeleton
public class UDPserver {
public static void main(String[] args) throws Exception{
while(true){
.... some code ...
packet = new DatagramPacket ( data , data.length, packet.getAddress(), packet.getPort() );
.... some code ...
socket.receive( ... );
}
}
}
Now, i want to make it handle multiple requests, so i checked out that i have to implement Runnable.
public class UDPserver implements Runnable { }
I read that I also need to have a run(). But i don't understand run(). should i put the whole while(true) statement inside run()? what about main()? Can anyone show how to change my code above to handle multiple requests?
thanks
move all the code inside the run method of UDPServer (including the while(true))
In your main method :
UDPServer udpServer = new UDPServer();
udpServer.start();
To make sure that no excpetion won't break your main loop, remember to catch and handle all exceptions that might be rasied inside the while(true) loop
You can also use new thread for each new connection for performing. For example:
class PacketPerforming extends Thread {
DatagramPacket pak;
PacketPerforming(DatagramPacket pak) {
super();
this.pak = pak;
}
public void run() {
// do somethoing with pak
}
}
// in your server thread
while (true) { // i prefered wirte for (;;)
DatagramPacket pak; // take pak object form remote socket
PacketPerforming perform = new PacketPerforming(pak);
perform.start();
}