Java RMI programming a service - java

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.

Related

Java - How to simultaneously run two static and void functions with Executor Service

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;
}
}
});

Send greeting to a newly connected client

I'm writing a tcp server with netty and want to send some greetings to all newly connected clients. As of now I'm intending to do that with ChannelInitializer
ServerBootstrap b;
//...
b.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>()) {
public void init(SocketChannel ch){
ch.pipeline(). //...
ch.writeAndFlush(Unpooled.copiedBuffer("Hi there!", CharsetUtil.UTF_8));
}
}
Since everything in netty is asynchronous I'm not sure if this is the right way to send greeting on connection succeeded. Can someone suggest a recommended way?
You should do this via a ChannelInboundHandlerAdapter once the channelActive callback is executed.
Something like:
public class GreetingHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelActive(ChannelHandlerContext ctx) {
ch.writeAndFlush(Unpooled.copiedBuffer("Hi there!", CharsetUtil.UTF_8));
}
}

How to automatically connect to TCP server after disconnection in netty

I have a scenario where I am establishing TCP connection using netty NIO, suppose server went down than how can I automatically connect to server when it comes up again ?
Or Is there any way to attach availability listener on server ?
You can have a DisconnectionHandler, as the first thing on your client pipeline, that reacts on channelInactive by immediately trying to reconnect or scheduling a reconnection task.
For example,
public class DisconnectionHandler extends ChannelInboundHandlerAdapter {
#Override
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
/* If shutdown is on going, ignore */
if (channel.eventLoop().isShuttingDown()) return;
ReconnectionTask reconnect = new ReconnectionTask(channel);
reconnect.run();
}
}
The ReconnectionTask would be something like this:
public class ReconnectionTask implements Runnable, ChannelFutureListener {
Channel previous;
public ReconnectionTask(Channel c) {
this.previous = c;
}
#Override
public void run() {
Bootstrap b = createBootstrap();
b.remoteAddress(previous.remoteAddress())
.connect()
.addListener(this);
}
#Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
// Will try to connect again in 100 ms.
// Here you should probably use exponential backoff or some sort of randomization to define the retry period.
previous.eventLoop()
.schedule(this, 100, MILLISECONDS);
return;
}
// Do something else when success if needed.
}
}
Check here for an example of Exponential Backoff library.

what does the constructor of UnicastRemoteObject class do

I have some questions about the UnicastRemoteObject class.
take the following code:
public class MaxImpl extends UnicastRemoteObject implements Max{
public MaxImpl () throws RemoteException {}
#Override
public int getMax(int[] A) throws RemoteException {
// ...
return max;
}
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
MaxImpl max = new MaxImpl();
Naming.rebind("maximum", max);
} catch (RemoteException ex) {
System.out.println(ex.getMessage());
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
}
}
}
what does the following statement do:
MaxImpl max = new MaxImpl();
generate a stub.
generate a stub and create a remote object so that it can receive
invocations of its remote methods from remote clients.
the above code is executed indefinitely, Why? I suppose there's a loop:
while(true){ ServerSocket server = ...; }
generate a stub.
No.
generate a stub and create a remote object so that it can receive invocations of its remote methods from remote clients.
No.
It exports the remote object, which consists of:
Open a ServerSocket
Start a thread listening at that socket.
Create a stub object containing the IP address, the port used at (1), and a remote object identifier.
Note that (1( and (2) Can be shared between remote objects using the same port so it may not happen precisely as above.
Now the existence of the thread at (2) will prevent the JVM from exiting.

RMI multithread skeleton

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.

Categories

Resources