rmi registry binding issue - java

I'm running RMI Regitry on a virtual machine (running Windows XP) with IP: 192.168.133.2
and trying to bind an RMI server (running on different vm XP IP: 192.168.133.3)
by using this code:
Naming.rebind("//192.168.133.2/rmi.2", new RMI());
where
public class RMI extends UnicastRemoteObject
but I get this exception:
java.rmi.AccessException: Registry.Registry.rebind disallowed; origin /192.168.133.3 is non-local host
I figured that the RMI Registry don't accept any rmi server which isn't running on the same
RMI Registry running machine.
but how to make this registry accept my rmi server?
p.s: I'm using JBuilder X as an IDE.
I'm trying to implement a mobile agent which will run on some rmi servers to do some work on them and return the results to the starting station so RMI servers implements the environment that hosts this agent to do its work and send it to the next station which it'll locate through the registry

trying to bind an RMI server (running on different vm XP IP: 192.168.133.3)
Stop right there. You can't do that. You can only bind an RMI server to a Registry running in the same host as the agent that is doing the bind.
Note that that does not necessarily mean the same host as the remote object itself is running in. For example, a client could lookup a remote Registry and bind the stubs retrieved into the local Registry. But you cannot bind anything to a remote Registry.

RMI doesn't provide any sort of "federated" or distributed naming service.
RMI is structured to allow you to run an RMI registry on your server. It hosts services that can be accessed across the network, however the services run locally on that server.
The service being provided must be started - and "rebind" - on the server - not on any client system. Local address only.
Your clients should then reach out to that server...

Related

Remote Profiling in Jprofiler

I have my sample java application running on port 9010 in one of my Azure VM with an IP let say xxx.xx.xx.254. I have installed Jprofiler in another Azure VM, with IP xxx.xx.xx.159. How can i profile the application from xxx.xx.xx.159 (Both machines are Windows)?
I have tried remote profile using direct connection, but it couldn't connect. Also checked with SSH, that too failed as 'Connection timeout'
Is there any step by step process for this connection?
Solution to the problem, how to connect and profile the Remote application from my local machine using JProfiler
"Direct connection" means that you can connect to remote machine on the selected profiling port (8849 by default). This is usually not the case unless the remote machine is on a private network because firewalls will prevent the connection. Also, in that case you must have added the -agentpath VM parameter for loading the JProfiler agent to the start command of the profiled JVM. This parameter can be obtained by invoking the "Session->Integration Wizards->New Remote Integration" wizard.
With SSH connections in JProfiler, you can tunnel the connection through SSH. This will work if you have an SSH server running on the remove machine. SSH connections work for VMs where the JProfiler agent has been loaded with the -agentpath VM parameter as well as in attach mode for all JVMs that are running on the remote system.
The related documentation is available at
https://www.ej-technologies.com/resources/jprofiler/help/doc/main/profiling.html

How to connect remotely via tcp to the h2 database?

I am trying to start H2 in server mode to connect an application from another computer. But no matter how hard I have tried, I have not succeeded.
I have seen the documentation and to start the server from the command line is executed:
java -cp h2-2.1.214.jar org.h2.tools.Server -tcpAllowOthers
output:
TCP server running at tcp://127.0.1.1:9092 (others can connect)
PG server running at pg://127.0.1.1:5435 (only local connections)
Web Console server running at https://127.0.1.1:8082 (others can connect)
now from the other pc, as I understand I must execute the connection in the following way:
jdbc:h2:tcp://[server][:port]/[path]/[databaseName]
then it should be:
jdbc:h2:tcp://127.0.1.1:9092/home/mateo/database
But I have read that 127.0.1.1 only works locally. I have also noticed that when I open H2 Console in the examples I have seen, the machine's ip appears, that is to say: 192.168.X.
What am I doing wrong?
(Update)
I am currently using Linux.
I have launched the server from Windows and managed to connect it from Linux successfully following the above steps. But, I still don't understand why it doesn't work in Linux, in Windows it loads the server with the IP address of the machine. It makes me think that I have to do some additional configuration for Linux.
server running
You need to replace local IP address in your JDBC URL with real non-local IP address of your server (jdbc:h2:tcp://127.0.1.1:9092/*** -> jdbc:h2:tcp://192.168.1.4:9092/***, for example). H2 listens all network interfaces of the host, it doesn't matter which address was reported in “runnig at …” message.
You also may need to protect ports 8082 and 9092 from connections from untrusted systems if you have them in your internal network and from connections from external network (make sure your router or whatever you have doesn't redirect connections to the host with database server).

CloudFoundry websocket failed: Establishing a tunnel via proxy server failed

Note: I am not using Pivotal CF.
I have a java application deployed on CloudFoundry. I am using embedded Jetty to host my Jersey REST API. This API is by default exposed on port 8080 by cloud foundry.
My application also needs some websockets to stream data to the browser. I am using Java-WebSocket (https://github.com/TooTallNate/Java-WebSocket) for this. On my local machine, I was using port 8887 for my websocket connection. Everything worked fine.
After deploying on CloudFoundry, I can access my REST API but not my websocket. After searching a bit online, I found that websocket connections are only allowed on port 4443 (http://docs.run.pivotal.io/release-notes/)
I changed my server side to reflect this
import org.java_websocket.server.WebSocketServer;
public class MyWebSocket extends WebSocketServer {
public MyWebSocket() throws UnknownHostException {
super(new InetSocketAddress(4443));
}
#Override
public void onOpen(org.java_websocket.WebSocket websocket, ClientHandshake handshake) {
// Handle this
}
}
On my client side, I am connecting the websocket using the following
wss://my_cf_app.com:4443/
But I am getting the following exception.
WebSocket connection to 'wss://my_cf_app.com:4443/' failed:
Establishing a tunnel via proxy server failed
I also tried to connect the websocket on server side using "PORT" environment variable of CF but I get "Address already in use" error in Java-WebSocket.
I have tried many different things but I am unable to figure this out. Any help would be awesome.
After deploying on CloudFoundry, I can access my REST API but not my websocket. After searching a bit online, I found that websocket connections are only allowed on port 4443 (http://docs.run.pivotal.io/release-notes/)
Port 4443 is specific to Pivotal Web Services (and some installs of CF that run on AWS). Most PCF installs do not have a separate port for WSS, but just use 443 along with the HTTPS traffic. The port used ultimately depends on the load balancer being used in front of the CF installation and what it supports.
You would never have your application listen on port 4443. Port 4443 is the external port for traffic where the load balancer listens. This traffic will be directed to the port assigned to your application, which is $PORT (env variable).
I also tried to connect the websocket on server side using "PORT" environment variable of CF but I get "Address already in use" error in Java-WebSocket.
This is the correct behavior, i.e. you should be listening on the port assigned through $PORT env variable. What the error is telling you is that something is already listening on this port and you cannot have two things listening on the same port.
There is only one port available per application at this time (likely to change in the future). For now, if you have two separate applications listening on two separate ports then you need to push them to CF as two separate applications.
What you can do to make them appear like one application to end users is to map each one to a specific path. See the --route-path argument of cf push or docs for cf create-route.
https://docs.cloudfoundry.org/devguide/deploy-apps/routes-domains.html#create-route

Java RMI: multiple rmiregistry on the same machine

We are developing a client-server application with Java RMI and, for testing, we will use a computer both as client and as server. So both the client and the server applications must call rmiregistry on the same machine, but they are two different JVMs obviously. How can we do that? We hoped that it was necessary only to give different ports to LocateRegistry but we get NotBoundException...
What is the correct way?
You can run as many as you like, but why? You don't need to. Have the server start its own Registry via LocateRegistry.createRegistry(), and have the client lookup that one. You seem to think the client needs its own Registry, which isn't correct.
If you got a NotBoundException clearly either the service wasn't bound at all in any registry, or you looked up the wrong one.
RMI Registry is a server which maintains a registry of services.
So your server should connect to the RMI registry and register itself in it, while client should connect to RMI registry and look up your server
So you need to run a single RMI Registry on your machine.
It seems that you're getting the NotBoundException cause you have two of them

Explain JMX URL

I am trying to understand a JMX service URL.
service:jmx:rmi://192.168.30.10:1234/jndi/rmi://192.168.30.10:2344/jmxrmi
It would be great, if someone can help me understand this.
Thanks
I will reuse an answer I wrote up earlier for this question: Cannot connect to Tomcat's MBeanServer via jconsole in Java6
It's not complete, but might help:
Suppose you have the JMX Server (alias 'JMX Agent' alias 'the JVM you want to connect to') running on 'TARGET MACHINE' with the RMI registry port at 'RMI REGISTRY PORT' and the JMX RMI server port at 'JMX RMI SERVER PORT'.
Note:
The RMI registry tells JMX clients where to find the JMX RMI server port; information can be obtained under key jmxrmi.
The RMI registry port is generally known as it is set through system properties at JVM startup.
The JMX RMI server port is generally not known as the JVM chooses it at random (if no other precautions are taken).
The following URI will lead to successful connection (tested)
service:jmx:rmi://<TARGET_MACHINE>:<JMX_RMI_SERVER_PORT>/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
This looks nasty. Let's cut it apart.
This URI is an RFC2609 "Service Location Protocol URL" (well, it's really an URI, right?)
It is composed of:
service - a constant
jmx:rmi - the service type composed of: abstract type jmx and URL scheme rmi
the rest - the sap (service access protocol specification)
sap is decomposed into:
//<TARGET_MACHINE>:<JMX_RMI_SERVER_PORT> - ipsite
/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi - URL part
A well-informed JMX client connects to the "ipsite" to do JMX-over-RMI exchanges; but what of the JMX client that doesn't KNOW that port? Patience...
URL part is decomposed into:
/jndi/ - This seems to tell the JMX client that it can get lookup information at the location that follows
rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi - Yep, we get information about the JMX RMI Server at the RMI registry, under the lookup key jmxrmi
This is somewhat cart-before-horse, as one has to contact the RMI registry given by the latter part of the SLP URL first.
After scratching head, intuitively, let's try:
service:jmx:rmi://<TARGET_MACHINE>/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
Yes, that works! The JMX RMI server port is nicely obtained from the registry. On second thoughts, the target machine should also be obtained from the registry, thus:
service:jmx:rmi:///jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
Even better, that works, too!
References:
http://download.oracle.com/javase/6/docs/api/javax/management/remote/rmi/package-summary.html
http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXServiceURL.html
http://mx4j.sourceforge.net/docs/ch03s04.html
http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html#gdevg
http://www.rfc-editor.org/rfc/rfc2609.txt
To explain:
service:jmx:rmi://192.168.30.10:1234/jndi/rmi://192.168.30.10:2344/jmxrmi
service:jmx:rmi://192.168.30.10:1234 - says that there is a JMX Agent on the machine with IP address 192.168.30.10. The JMX agent is using (TCP) port 1234 to provide JMX service(s) over RMI (basically acts as an RMI server).
/jndi/rmi://192.168.30.10:2344/jmxrmi - says that the RMI stub to interact with the JMX Agent over RMI can be found in the RMI registry which is running on the machine with IP address 192.168.30.10 and is using (TCP) port 2344. To get the RMI stub you need to lookup the "jmxrmi" binding.
Previous answers suggest that the 2nd part of the URL is to obtain the server port of the JMX RMI server. That is not correct. The JMX RMI server port is (TCP) 1234 and is part of the URL. What you get from the RMI registry is the RMI stub (javax.management.remote.rmi.RMIServerImpl_Stub) which you can use to talk to JMX Agent (MBean Server) over RMI.
Hope this helps.
According to javax.management.remote.rmi
this url is assembled like this
service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname

Categories