RMI RemoteException - java

Any idea why do I get RemoteException while trying to invoke methods on Unix machine from Windows?
I am inside the network and don't think this is because of firewall problem as I can do "telnet" from Windows to Unix box after starting the RMI server at the unix box. I also could not understand why is it going to local loopback IP?
Stack Trace:
RemoteException occured, details java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused: connect
java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused: connect
Many thanks in advance.

You probably don't have your hostname configured properly on your Linux box. I bet if you ping $(hostname) from your Linux box, it will ping 127.0.0.1. Usually this is because of an entry in your /etc/hosts file.
There's a couple of ways to solve the problem. The hard way would be to get your Linux box to resolve its own hostname to its IP address properly. You can edit your /etc/hosts file, setup your DNS server, whatever you've got to do. The challenge is that while this may make things more technically correct, you run the risk of breaking things that relied on the old behavior.
The path of least change would be to set the system property java.rmi.server.hostname to the hostname or IP address of your Linux box. (i.e. java -Djava.rmi.server.hostname=$(hostname) ...).
Why?
The Java RMI registration server is actually a network wide registration server. Objects on other machines can bind themselves to this registry.
When a remote object is registered, the registration includes the network address as part of the registration. By default, the address it uses is 'the IP address of the local host, in "dotted-quad" format.' In your setup, this address is 127.0.0.1.
When your Windows box contacts the registration service for the address of the remote object, it gets back 127.0.0.1. It then tries to contact the remote object at that address. That's why it's going to the loopback address.

I suggest a solution based on customized RMISocketFactory.
Like explained on Sun Site, you can provide your own SocketFactory :
http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/socketfactory/
My solution use this mecanism for intercept client socket creation, and replace the host received (127.0.0.1) by the good IP, well known by the client.
Th rest of the communication mechanism is still based on java rmi standards.
With this implementation, the exporter does not have to know it's own IP, which is sometimes no easy (multiple network interfaces ...)
Here are the tree classes, the Factory, the Server and the Client. The Hello class and interface are also uploaded to be exhaustive.
Hope it should be utile
SocketFactory:
import java.io.IOException;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
/**
* Socket Factory for RMI calls.
*
* This classe, instanciated from server when RMI objects are exported, is send
* to the client who use it (transparently) for create sockets which call remote objects.
*
* This implementation give the ability to modify dynamically the target host cible.
*
* The host will not be aware of it's own IP.
*/
public class MySocketFactory extends RMISocketFactory implements Serializable {
/**Target host for RMI calls, setted by caller. */
private static String server = "localhost";
/**
* Create a client socket, replacing required host by the host setted when the service is called,
* via {#link #setServer(String)}.
* The host received is usually 127.0.0.1, depending on property java.rmi.server.hostname on the exporter.
*/
#Override
public Socket createSocket(String host, int port) throws IOException {
System.out.println("change host from " + host + " to " + server);
return getFactory().createSocket(server, port);
}
/**
* Create a server socket.
*/
#Override
public ServerSocket createServerSocket(int port) throws IOException {
return getFactory().createServerSocket(port);
}
/**
* Use default RMI factory.
*/
private RMISocketFactory getFactory() {
return RMISocketFactory.getDefaultSocketFactory();
}
/**
* Save the target host. This method must be called before use of a service (before Naming.lookup).
*/
public static void setServer(String host) {
server = host;
}
}
Exporter :
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.UnicastRemoteObject;
/**
* RmiExport
*/
public class MyRmiExporter {
/**
* java -Djava.security.policy=java.policy MyRmiExporter
*/
public static void main(String[] args) throws RemoteException, IOException {
System.setSecurityManager(new RMISecurityManager());
Hello export = new HelloImpl();
RMISocketFactory sf = new MySocketFactory();
UnicastRemoteObject.unexportObject(export, true);
Remote stub = UnicastRemoteObject.exportObject(export, 0, sf, sf);
String url = "rmi://0.0.0.0:" + Registry.REGISTRY_PORT + "/Hello";
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Naming.rebind(url, stub);
System.out.println("Exported " + url);
}
}
Client :
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.registry.Registry;
public class MyClient {
/**
* java MyClient localhost
*/
public static void main(String[] args) throws IOException, NotBoundException, InterruptedException {
String host = args[0];
MySocketFactory.setServer(host);
String url = "rmi://" + host + ":" + Registry.REGISTRY_PORT + "/Hello";;
System.out.println("look up " + url);
Hello proxy = (Hello) Naming.lookup(url);
System.out.println("OK, remote getted !");
System.out.println(proxy.hello("bonjour"));
}
}
Bean :
import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote, Serializable {
String hello(String mess) throws RemoteException;
}
Impl :
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class HelloImpl extends UnicastRemoteObject implements Hello {
public HelloImpl() throws RemoteException {
}
#Override
public String hello(String mess) throws RemoteException {
return "hello : " + mess;
}
}
last and least, java.policy :
grant {
permission java.security.AllPermission;
};

Related

Caused by: java.net.NoRouteToHostException: No route to host

I am trying to deploy my Jersey project from eclipse on openshift and I am getting this error in the tail files Caused by: java.net.NoRouteToHostException: No route to host
before when I had like this:
String host = "jdbc:mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/bustrackerserver"
I got this error:
'java.lang.NumberFormatException: For input string: “OPENSHIFT_MYSQL_DB_PORT”'
I have pinged this ip address 127.10.230.440 and I am getting response
I checked whether some of the port 8080, 3306 are being used from my local mashine but they are just being used from eclipse.
Apple class.
package org.busTracker.serverSide;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
#Path("myresource")
public class Apple {
//String host = " jdbc:mysql://${env.OPENSHIFT_MYSQL_DB_HOST}:${env.OPENSHIFT_MYSQL_DB_PORT}/serv‌​erside";
//String host = "jdbc:mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/bustrackerserver";
String host = "jdbc:mysql://127.10.230.440:3306/bustrackerserver";
String user = "adminNMccsBr";
String password = "K3SV5rbxh8qP";
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* #return String that will be returned as a text/plain response.
*/
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting to database…");
conn = DriverManager.getConnection(host,user,password);
Map<String, String> env = System.getenv();
for (String envName : env.keySet()) {
System.out.format("%s=%s%n",
envName,
env.get(envName));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// ignore
}
}
}
return "Hello, from apple class 14.05.15 13:30!";
}
}
Your MySQL is not listening on TCP/IP and hence your attempt to connect is failing. You sort of answered your question when you said:
I checked whether some of the port 8080, 3306 are being used from my local mashine but they are just being used from eclipse.
In other words, MySQL is not listening on localhost. To confirm this another way, try connecting to MySQL from the command prompt:
mysql -u adminNMccsBr -h 127.10.230.440 -p YOUR_DB_NAME
I expect this to fail. The solution to your problem is to configure MySQL to listen on localhost. In the /etc/my.cnf config file, under the [mysqld] line, add the following:
bind-address = 127.10.230.440
This is not a Java problem, it's a MySQL problem.

Connection time out in Java Server-Client

I have a small program where a Server-Client program is getting connected on the same network, but the same program shows a connection time out error in the client program. I have connected the two systems using LAN cable.
Server
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class DateServer {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(9090);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
} finally {
listener.close();
}
}
}
Client
import java.io.BufferedReader;
import java.io.IOException ;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.swing.JOptionPane;
public class DateClient {
public static void main(String[] args) throws IOException {
String serverAddress = JOptionPane.showInputDialog(
"Enter IP Address of a machine that is\n" +
"running the date service on port 9090:");
Socket s = new Socket(serverAddress, 9090);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
Since the code runs on the same computer, three possibilities come to my mind:
The problem can be either your firewall/access to port rights or having IP addresses as mentioned by other fellows.
You are setting the IP address of the server wrong.
The IP address of the server does not lie on the subnet mask of your network. If you have literaly connected the two computers with a cable (no routers in the middle) you probably haven't setup a DHCP, i.e., your ip addresses should be manually selected. If the ip is selected randomly, chances are your client computer can't find the server computer. try manually setting the ip addresses of both computers to an invalid address within the same subnet mask range and see if it works.
For example set the following addresses:
client IP: 192.168.1.10
subnetmask: 255.255.255.0
server IP: 192.168.1.11
subnetmask: 255.255.255.0
Connecting the two systems with a LAN cable is not sufficient. You have to ensure they have distinct IP addresses, are both in the same IP subnet, and/or have appropriate IP routing tables defined. More typically you would connect both via a router.

RMI client cannot lookup server - java.rmi.UnmarshalException

I have a java rmi server and a java rmi client in two separate and different machines.
The server is basically a fibonacy calculator. It receives a bunch of numbers and calculates a Fibonacci sequence based on them.
The client simply sends a bunch of numbers for the server to calculate.
The FiboServer project consists of three classes:
IFibonacci.java: an interface
Fibonacci.java: implements the previously defined interface
FibonacciServer.java: Has the main, and runs the server
FibonacciServer.java:
package fiboserver;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class FibonacciServer {
public static void main(String args[]){
if (System.getSecurityManager() == null) {
System.setProperty("java.security.policy", "server.policy");
System.setSecurityManager(new SecurityManager());
}
try{
IFibonacci fib = new Fibonacci();
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind("fibonacci", fib);
System.out.println("Fibonacci Server ready.");
}catch(RemoteException rex){
System.err.println("Exception in Fibonacci.main " + rex);
}
}
}
The client project merely has one class: FibonacciClient.java.
FibonacciClient.java:
package fiboclient;
import fiboserver.IFibonacci;
import java.math.BigInteger;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class FibonacciClient {
public static void main(String[] args) {
if (System.getSecurityManager() == null) {
System.setProperty("java.security.policy", "client.policy");
System.setSecurityManager(new SecurityManager());
}
try{
//args[0] = server Public IP
Registry registry = LocateRegistry.getRegistry(args[0]);
IFibonacci calculator = (IFibonacci) registry.lookup("fibonacci");
//the rest of the args are just numbers to calculate
for(int i = 1; i < args.length; i++){
try{
BigInteger index = new BigInteger(args[i]);
BigInteger f = calculator.getFibonacci(index);
System.out.println("The " + args[i] + "th Fibonacci number "
+ "is " + f);
}catch(NumberFormatException e){
System.err.println(args[i] + " is not an integer.");
}
}
}catch(RemoteException e){
System.err.println("Remote object threw exception " + e);
} catch (NotBoundException e) {
System.err.println("Could not find the requested remote object on "
+ "the server: " + e);
}
}
}
Both projects have a policy file, the server has a server.policy and the client has a client.policy file. Both files have the same content:
grant{
permission java.security.AllPermission;
};
I am launching the FiboServer in the server machine using java -jar FiboServer.jar -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=12.34.56.789
I am launching the client by using java -jar FiboClient.jar 12.34.56.789 1 2 3 4 5.
The server launches without a problem. But when I launch the client I get the error:
Remote object threw exception java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: fiboserver.IFibonacci
Searches on StackOverflow convinced me that this has to do with RMI registry errors or policy file errors. However I know the the policy files are being read correctly and I do not think they have any errors.
What am I doing wrong? Why is this not working?
EDIT:
IFibonacci.java:
package fiboserver;
import java.math.BigInteger;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IFibonacci extends Remote{
public BigInteger getFibonacci(int n) throws RemoteException;
public BigInteger getFibonacci(BigInteger n) throws RemoteException;
}
JAR Files:
Contents of FibonacciClient.jar:
|META-INF
|----Manifest.mf
|fiboclient
|----FibonacciClient.class
Contents of FibonacciServer.jar:
|META-INF
|----manifest.mf
|fiboserver
|----IFibonacci.class
|----FibonacciServer.class
|----Fibonacci.class
The client doesn't have the class named in the exception available on its classpath. You need to deploy it, and any class it depends in, and so on recursively until closure.
Possibly you've renamed/copied the remote interface into another package for the client. You can't do that. It has to be the same at server and client. Same name, same methods, same package.
NB The message in your client 'remote object threw exception' isn't correct. It could be the lookup() throwing the exception. Don't confuse yourself by assuming things that may not be so. Just print the actual error message, exception, and stack trace.

How to pass username and password in the localhost url to connect with the memcached in Java?

Hi, I want to pass the username and password to connect to localhost where I have deployed memcached.
Here is my code.
import java.io.IOException;
import java.net.InetSocketAddress;
import net.spy.memcached.MemcachedClient;
public class MemCaheConnection {
public void ConnectMemCaheConnection() throws IOException{
MemcachedClient c = new MemcachedClient(new InetSocketAddress("localhost", 11211));
c.flush();
}
}
Can anyone help?
without explicit use of http://code.google.com/p/memcached/wiki/SASLAuthProtocol there is no need for username+password, did you check the service is running on port 11211?

How can I configure the source port for a server using Netty to send UDP packets?

I have a server task that uses Netty for socket I/O. It binds to port MY_PORT and receives UDP messages from clients. It responds to these clients, sending messages back to the clients with a destination port of MY_PORT. Using wireshark, I see that the outgoing packets from my server also have a source port of MY_PORT. This all works fine.
The people in charge of the network between the server and clients are having some issues with a load balancer. They said it would help them out if the UDP messages my server sends to the clients had a different source port than the one used for a destination.
I've looked at the Netty API, but I'm not sure how I can do this. It seems that because I've bound to a local port, I must use that for outgoing packets as well?? Here's a stripped down version of my code.
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
public class UdpServer {
private final int port;
private Channel serverChannel;
public UdpServer( int port ) {
super();
this.port = port;
}
public void start() {
NioDatagramChannelFactory serverChannelFactory =
new NioDatagramChannelFactory( Executors.newCachedThreadPool(), 1 );
ConnectionlessBootstrap serverBootstrap =
new ConnectionlessBootstrap( serverChannelFactory );
serverBootstrap.setPipelineFactory( new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() {
return Channels.pipeline( new SimpleChannelHandler() {
#Override
public void messageReceived( ChannelHandlerContext ctx,
MessageEvent e ) {
// TODO, handle message from client
}
} );
}
} );
serverBootstrap.setOption( "reuseAddress", Boolean.TRUE );
final InetSocketAddress trafficAddress = new InetSocketAddress( port );
serverChannel = serverBootstrap.bind( trafficAddress );
}
public void sendMessage( byte[] message, String clientIp )
throws UnknownHostException {
// TODO, how do I control the source port of this packet??
SocketAddress address =
new InetSocketAddress( InetAddress.getByName( clientIp ), port );
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer( message );
serverChannel.write( buffer, address );
}
}
You're already using bind() to set the local address. You can use connect() to connect to a specific destination port (a stretch of the "connect" concept). On a regular datagram socket you could include the remote port in the send request, but not if you're using write(). In that case you must use connect().
They said it would help them out if the UDP messages my server sends to the clients had a different source port than the one used for a destination.
This sounds like complete hooey to me. Net admins seem to have no idea about how source/destination ports are actually allocated. Even if the clients used system-allocated poets rather than a fixed port, which they probably should, the system could still allocate the same port number as the server is using.
However you could probably shut them up, or at least move them on to a different problem, by having the clients use system-allocated ports rather than a fixed port. Unless there is a client-side firewall of course ...

Categories