I've been using RMI for a project I am currently working on and I want to bind from multiple hosts to a single RMI registry.
However when I attempt to do so I get an error saying
java.rmi.AccessException: Registry.Registry.bind disallowed; origin / 192.168.0.9 is non-local host
I did so googling and it seems that RMI stops remote hosts from binding by default, what I want to know is there some way of overriding or bypassing this?
If anyone any suggestions on how to get past this issue they would be highly appreciated, i've tried using different policy files and overriding the security manger but none seem to work.
There's a way to get around the limitation but it is what it is: a work-around. Anyway, feel free to try it out. It works for us.
On the host that is running the central RMI registry run a small service which will bind a remote object with just one remote method: proxyRebind. The implementation of this method simply binds the object that is supplied to it in the central registry (this would not fail because the registry is on the same machine as this service).
All other hosts would simply lookup this remote object and invoke proxyRebind with their own remote objects.
This works because look-up on remotely hosted registries is allowed. Your original attempt failed because binding on remotely hosted registries is not allowed.
Let me know if you need any further clarity on this.
/RS
2 There's a way to get around
the limitation but it is what it is: a
work-around. Anyway, feel free to try
it out. It works for us.
On the host that is running the
central RMI registry run a small
service which will bind a remote
object with just one remote method:
proxyRebind. The implementation of
this method simply binds the object
that is supplied to it in the central
registry (this would not fail because
the registry is on the same machine as
this service).
All other hosts would simply lookup
this remote object and invoke
proxyRebind with their own remote
objects.
This works because look-up on remotely
hosted registries is allowed. Your
original attempt failed because
binding on remotely hosted registries
is not allowed.
Let me know if you need any further
clarity on this.
This perfectly works. The only thing to take care is following should be always set correctly.
-Djava.rmi.server.hostname="LOCAL HOST IP"
I may be misunderstanding your question, if so please let me know.
I have limited experience with Java RMI, we used it in our Design Patterns class with the Proxy Pattern. (Textbook: Headfirst Design Patterns)
We were not able to get our projects working from outside the university network, but they worked perfectly when connected directly to the network. According to our professor, it wasn't possible to use RMI in our implementation over the internet or wan. A solution she suggested was that a VPN would be required. I believe Vladimir is correct in that it has to do with it being a local naming service.
I may be wrong, but it looks like rmiregistry application is essentially a wrapper over local naming service. Which means there is no way to make it point to remote objects.
What you need is a Naming implementation, and clustered at this. Consider to move into J2EE AS clustering solution. JNDI tree is shared within the cluster.
Thanks for everyones answers the solution I came up with in the end was to use the Cajo Framework this gives a very flexible system for distribution and it allowed for me to handle the registry as I saw fit. It can also work behind NATs, firewalls, and HTTP proxies, which is very useful.
I believe that the method of proxying suggested by rndm.buoy will work in some cases but its may be troublesome on some system. RMI seems to have some issues with associating to the wrong Network Interface I particularly had this issue when running on Debian based Linux distributions.
Related
Sorry if this questions was already asked and answered, i just really have no clue how to ask formulate this question.
So i've got the next issue. I got the access through RDP to the machine in some private network. Also we got some services which is accessible in that private network. That service, which is basically some corporate repository is a place where some dependecies in our project pulled of from. What i trying to do is to configure this project locally, and for that purpose i need the posibility to pull that depenedencies of from that repository on my local machine. This dependecies are pulled by Maven, and as far as i understand basically during the pulling process, it's just a http requests back'n'forward process. In my thoughts, theoreticaly, i could configure somehow some sort of proxy from computer to the RDP machine, and pass all that incoming traffic to the remote machine and answer on the requests there (on the remote machine) and get answers on my local machine.
One more thing worth to mention. I use ZScaller proxy to connect to that machine via RDP. Again, from my thoughts, not that was really an issue, but just in case.
My questions, is that possible, and how can i do it? Any tips for that.
Thank you very much!
I'm trying to use AWS as a scalable analytics tool. I'm using apache zeppelin as an interactive shell to a Spark cluster and trying to plot using wisp. This is causing a problem as the plotting approach in wisp is to start a web app based on what I think is a jetty server. This works well on my local machine but on AWS it does not work as it picks up the private IP address rather than the public one.
Within wisp, it uses java.net.InetAddress.getLocalHost.getCanonicalHostName
to retrieve the IP address of the machine. This always returns the private FQDN address. How can I make the java function return the public IP address or FQDN AWS provides without hardcoding something in wisp every time I spin up a cluster and rebuilding?
I have tried changing /etc/hosts and /etc/hostname but both have no effect. I don't really know where java.net.InetAddress.getLocalHost.getCanonicalHostName
is getting it's address from.
Any help or advice greatly appreciated.
Dean
I'm an idiot. It was a port issue. It appears that despite displaying the private IP, it's still available on the public IP.
Turn off the internal firewall with sudo ufw disable (on an ubuntu vm anyway, look up the alternative command for your flavour of vm).
Next, go to the AWS EC2 Management page for your account and click on the security group of your instance.
On the security group page, edit the inbound rules and add a custom tcp rule.
Under ports, put in '1 - 65536' and under source put in '0.0.0.0/0'. Please note, that what you have just done is open all ports on your instance to all incoming traffic from everywhere. You have just put down a welcome mat to the internet. I do not recommend doing this long term and it is extremely stupid. It worked for my proof of principle set up though and that is all I was aiming to do. I'll now be looking at ways to make it secure.
Thanks to everyone for their restraint in not mocking me for being a moron.
I am very new to jxfs things. I have a requirement to call jxfs server which is in cloud server from the jxfs client which is in ATM environment.. How can i call?.. I need to call this one through the Jxfs RMI concept. It would be appreciated one if any example code is available. If atleast you are having code for calling from jxfs server to jxfs client, please post it.
Thanks in advance guys.
One of the interesting things about J/XFS and remote device access (based on RMI) is that it is just matter of configuration.
You need to configure a J/XFS repository in order to handle a remote device (basically set 'remoteAccess' to true).
Then accessing these devices from the programming point of view is just the same as they were local devices.
Architecture is explained here: ftp://ftp.cencenelec.eu/CWA/CEN/WS-J-XFS/cwa14923/cwa14923-01-2004-May.pdf
Details, when programming may differ depending on the J/XFS implementation you are using.
Trying to answer your question below:
Whenever you want to access a device remotely in J/XFS, RMI is used. You need to make the following setup:
On a server (should be accessible) you need to start a JxfsServer. The JxfsServer will use a Read.repository
whith all the ATM's and devices configured on them as workstations, with the right IP addresses.
On the ATM, you need to install:
J/XFS libs
J/XFS device services for the devices on the ATM
Setup the DSstarter:
Will use the SpecificDeviceManagerRMI connecting to the JxfsServer you started before.
On your server (cloud) wherever you are going to use the J/XFS client you can get the remote controls by performing
the J/XFS initialization as follows:
jxfsDM_ = JxfsDeviceManager.getReference();
jxfsDM_.initialize("com.jxfs.forum.communication.rmi.SpecificDeviceManagerRMI,<atmWorkstation>,AppTest,2006;<jxfsserverhostname>,");
Then you can get the remote device controls with getDevice(...), and start using them as if they were local devices.
Please, note that handling RMI ports can be tricky, specially in a secured environment as ATM network. Make sure all the ports you need are open.
Consider this setup:
So there's a JMX Server and we want it to be reachable from different JMX Clients, but the problem is that these different JMX clients knows HostX by different names/addresses. For the sake of the example lets say that HostA knows HostX by the name of hostx but HostB knows HostX by the name of hostxshadow.
I'm looking for recommendations on how to solve this problem under the following scenarios:
Where I have control over the source code of the JMX Clients and JMX Server.
Where I have no control over the source code, i.e. I can set System Properties on the JVM, but that's it.
The basic problem to be solved is that in the RMI world the server-side decides how a client should connect (right?). So setting e.g. java.rmi.server.hostname on HostX isn't going to help. As I see it I can only make either HostA happy or HostB happy, but not both at the same time.
Is the conclusion really that any RMI Server can only work if all clients would use the same name to access it?
Your conclusion is correct. It's a design flaw in RMI. There is an underlying assumption that there is a single 'most public' hostname or IP address by which the server host can be contacted by everybody.
Your statement about the host embedding its own name or address in the stub is also correct.
RMI is one possible transport of JMX. Another solution is JMXMP and switching to it is very simple, check at http://meteatamel.wordpress.com/2012/02/13/jmx-rmi-vs-jmxmp/ or
http://blog.markfeeney.com/2010/10/jmx-through-ssh-tunnel.html.
The basic problem to be solved is that in the RMI world the server-side decides how a client should connect (right?). So setting e.g. java.rmi.server.hostname on HostX isn't going to help. As I see it I can only make either HostA happy or HostB happy, but not both at the same time.
This is not going to help you but for others, the trick to do is to set the java.rmi.server.hostname system property to a name that means something on HostA which is inside of the firewall but another thing to HostB which is outside.
For example, in EC2 land we set the hostname property to be the EC2 node's "public hostname" which we get by doing a:
wget -q -O - http://169.254.169.254/latest/meta-data/public-hostname
This resolves to be some like:
ec2-54-1-2-3.compute-1.amazonaws.com
On the box itself and any others that are inside of EC2 this resolves to be 10.1.2.3 while on the outside world it resolves to the externally facing IP 54.1.2.3. Amazon does this DNS work by default. You may need to adjust the /etc/hosts file as necessary to get the names to be correct.
For more details on EC2 and JMX, see: How to connect to Java instances running on EC2 using JMX
I am creating an application in which I have a central (server?) PC.
When at a particular position (or event) in the central PC, a XML file is dumped. The program reads that XML in which remote PC IP is given (any PC).
The command is transmitted to that PC, that PC will execute that command.
The command may be one of various types and for each command that PC has a separate class file.
Per command it will create an object of that type and run the desired method.
Question: What is the best technology with which I can implement this architecture?
Ok, what is your question?
The simplest way to do this may be to use RMI.
However, have you considered using a JMS queue as this would allow you to distribute the work evenly across many PCs without having to allocate a specific PC to a specific task. i.e. you give a queue the tasks you want to perform and the next available PC performs that task.
Take a look at Java RMI
Obligatory Wiki link and quote and why this can apply to your implementation:
The Java Remote Method Invocation
Application Programming Interface
(API), or Java RMI, is a Java
application programming interface that
performs the object-oriented
equivalent of remote procedure calls
(RPC).
(even across machine boundaries)
RMI is also the first that came up in my mind. But I think to give a really good answer we need some more details about what is done on the remote PC. My guess is that you are building a distributed Worker Thread Pattern
Other options can be:
JMS.
Web Services.
Etc.
You have several options.. You can use RMI, you can have a JMS Queue/Topic or even a Http Pub/sub. Each one of these has pros/cons.
With RMI, you can make the remote PCs open a connection to the server on startup to avoid the firewall issues. This way you only need to open the incoming/outgoing ports only on your central PC.
With JMS, you can register a listener from each of the remote PCs to a Topic/Queue opened by your JMS container. Any message you put in the Queue/Topic, you have a message filter set by using IP that way the message will only go to one targeted PC. I like this approach because of the lose coupling between your remote PCs and Central PC. But in this approach, since you don't have an open connection between your remote and your central pc, your Central PC will not have the similar control that you would get in the RMI system.