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
Related
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
I'm looking for a secure way to tunnel RMI traffic.
In My application(java Webstart) i must assume that the only port that is open is port 80.
I have the looked att socketfactories for rmi but do i really need a proxy then.
I need to do all my tunneling on the client side.
The only firewall i am trying to get past is on the client side.
I'm not able to open 1099 with port ranges above.
Would be nice to see some implementations.
Thanks!
Port 1099 was reserved for RMI at IANA in about 1995. There is no reason for it not to be open for outbound access in the client-side firewall.
RMI can be made to use fixed port numbers by supplying a port number when constructing (super(port)) or exporting (exportObject(object, port)). Better still, if you create the Registry within the server JVM via LocateRegistry.createRegistry(), all subequently exported remote objects will use that port unless they specify a different port or they use a server socket factory.
BUT ... RMI already includes HTTP tunneling 'out of the box'. No external solution required. You have to deploy the RMI-Servlet provided with the JDK, at the server end.
(a)
although not the newest fashion, exposing remote services with Hessian and Burlap seems to be a simple solution to avoid problem working across firewalls: http://hessian.caucho.com/doc/
see sample code for the server and client side:
http://www.javatpoint.com/spring-remoting-by-hessian-example
(b) or consider using Spring HttpInvokder (see some sample code here: http://www.javatpoint.com/spring-remoting-by-http-invoker-example)
HttpInvokder provides more customization options through the RemoteInvocationFactory, RemoteInvocationExecutor and HttpInvokerRequestExecutor strategies (for example, to add custom context information (such as user credentials) to the remote invocation, or using java’s built-in object serialization etc.), see:
http://docs.spring.io/spring-framework/docs/2.0.x/api/org/springframework/remoting/support/RemoteInvocationFactory.html
We are using Embedded Jetty as our webserver running on port 8080 and want to monitor the application on Jconsole. We are using the following system property when starting the Jetty server specific to JMX:
-Dcom.sun.management.jmxremote.access.file=jmxremote.access
-Dcom.sun.management.jmxremote.password.file=jmxremote.password
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=8081
Although, JMX and Webserver are running on two different ports, is there a way for client to access JMX via Jconsole/JvisualVM using port 8080? Is JMX Proxy going to help me in anyway? Is it possible in any way?
Thanks in advance.
Ajay
Not without some effort. In a nutshell, there can always only be a single server on one port (or the other way around: Servers can't share a port).
If JMX was supporting HTTP requests, then you could run it as a servlet on the same HTTP server. There would be one port (used by the HTTP server) and then the HTTP URLs would allow the server to determine whether the client wanted to talk to JMX or the web application.
But JMX doesn't support HTTP requests directly. You can try Jolokia (see this question) or you can write servlets which allows a client to query certain mbeans (but without JMX protocol).
JMX specification have Connector that can use any protocol as transport, see http://en.wikipedia.org/wiki/File:Jmxarchitecture.png
I'm curious about how JConsole and JMX work together. Specifically, I have read this JConsole Guide which mentions that
jconsole uses a JMXConnector client to connect to the JMXConnectorServer in
the target application. If the application isn't started with the JMX agent
then there isn't a JMXConnectorServer and jconsole doesn't have anything to
connect too. In that case it uses a HotSpotTM VM specific mechanism to start
the JMX agent in the target VM. Once the agent is started then jconsole connects
as normal.
When I start jconsole it simply needs a port and hostname for the JMX information, so I'm wondering if its possible to access the MBeans through any arbitrary tcp connection (and thus any programming language), or if there is something special that jconsole is also doing?
I know how to access the MBean Factory though java, but I am curious if I can access these items through an arbitrary language via TCP or another straightforward mechanism. Also see link discussing rest connector.
By default, the JMX server provides connection via RMI. That will make it tricky to access the server through an arbitrary language.
However, the JMX server is not limited to RMI as the communication protocol. The architecture is extensible and pretty much any transport protocol might be used - but it would need to be written almost from scratch.
Take a look at Jolokia - they do a pretty amazing stuff to let you talk to the MBean servers via a bunch of protocols (REST is one of them), amongst other things.
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...