How to share object between java applications? - java

I have 2 separate Java Applications running at a time. (Two separate javaw.exe) I need to share an object between them while they are running.
What is the simplest way to achieve this without having any permanent storage?

Objects and their instance variables can be shared between threads in a Java program, which is pretty simple task.
If you require to share objects (instance of it) between two programs, with out data storage, next choise would be using RMI Socket Communication or Java messaging service.

You can use TCP
Use a local software port, say
localhost:999.
Make one application as server (listening on this port) and other as client (will connect to server at localhost:999, but will use different port for it's own use).
Client will serialize your object to stream.
Server does de-serialize!
Example: http://www.java-samples.com/showtutorial.php?tutorialid=1167

I think that Hazelcast works fine for this type of situation. It practically requires no setup (more than that you need to add the dependencies to the Hazelcast jars). The following code sample shows how to setup a shared Map.
// Code in process 1
Config cfg = new Config();
HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
Map<Integer, String> sharedData = instance.getMap("shared");
sharedData.put(1, "This is shared data");
// Code in process 2
Config cfg = new Config();
HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
Map<Integer, String> sharedData = instance.getMap("shared");
String theSharedString = sharedData.get(1);
Hazelcast support various shared data structures including Map, Queue, List, AtomicLong, IdGenerator etc. The documentation is good and in my experience the implementation is solid.

You must decide if you prefer shared and updated state, or simply send an one-time-message-object.
In the first case you would have to share a "remote reference" to some object. RMI is a good approach.
In the second case you only need to serialize the object you want to share and send it. You can send it serialized (converted to byes) over a socket as Ankit said or even you can use:
RMI :) The sender connects to a RMI registered receiver, invokes a method with the mesasge object as a param and forgets about the RMI object
Java Messaging Service (JMS), maybe an overkill...
some other creative but simple thing...

If you can't store the object permanently, you need to transfer it somehow. This can be done either via network or some sort of shared memory.
For first (network) approach, use serialization (java.io.Serializable) and transfer the object over socket. This will require writing socket listeners.
Second approach will require using and configuring a third party library (e.g. EHCache).

Perhaps Oracle Coherence? That works like an in memory map shared across applications.

Related

Session management in Thrift

I can't seem to find any documentation on how session management is supposed to be done in Thrift's RPC framework.
I know I can do a
TServer.setServerEventHandler(myEventHandler);
and observe calls to createContext (called when a connection is established) and processContext (called before every method call). Still, I have to get whatever session state I maintain in those message into the handler itself.
So how can I access session information in my handlers?
Not sure if there isn't also a way to use the ServerEventHandler approach mentioned in my question, but here's how I was able to create one handler per connection.
Rather than providing a singleton processor instance, containing a handler instance, once, like this:
XProcessor<XHandler> processor = new X.Processor<XHandler>(new XHandler());
TServer server = new TSimpleServer(new TServer.Args(serverTransport)
.processor(processor));
I instead create and provide a TProcessorFactory:
TProcessorFactory processorFactory = new TProcessorFactory(null)
{
public TProcessor getProcessor(TTransport trans)
{
return new X.Processor<XHandler>(new XHandler());
}
};
TServer server = new TSimpleServer(new TServer.Args(serverTransport)
.processorFactory(processorFactory));
There is no such thing as an built-in session management with Thrift. Remember, Thrift is supposed to be a lightweight RPC and serialization framework. Managing sessions it considered outside the scope, located at least one layer on top of Thrift.
I'm not so sure, if the events approach will work, but maybe it does - I never tried it that way.
My recommendation would be to include the session ID (or whatever equivalent you use) into each call. That's how we do it, and it works quite well.
Altough quite handy, the "one handler per connection" model does not scale very far by design (same is true for the "Threaded" servers, btw). Imagine any multiple of your choice of 1000 connections hammering your service in parallel. If there is the slightest chance of that scenario becoming reality, you should think of a different solution, because most likely the approach you are about to use will not scale.
Actually, there are some plans to integrate kind of "header" data, but that stuff is not in the Apache Thrift code base yet.

How can I share memory between two Java web services?

I got two Java web services, hosted in Tomcat on the same server.
Is there any way to share memory (objects) between them?
I can turn the sharing into some kind of web methods calls, however
this is complicated, a lot of changes are required.
this is not really sharing, objects are duplicated, although it should work for my case.
this will expose methods that should not be called by the clients.
Not that I know of. Sounds like it's fraught with peril. It's hard enough to synchronize objects in one app; you have no hope with two. What good could this possibly do?
If it's common methods you need, put them into a service that both can call. If it's common data, put it in a database.
Is there any way to share memory (objects) between them?
You can create a shared memory region that is shared by two JVMs. You can do this using native code, or (in theory) by mapping a file into the address-space of two apps.
But you can't put Java objects in that region. The JVM doesn't support this, either in Java code or in native code. (And even if you could, synchronization would be a big problem.)
So could you use shared memory to share data between two JVMs?
Maybe. But you'd need to treat the share memory segment as a kind of database, and implement a scheme for copying object state between the segment and each JVM's heap. And you'd need to implement a robust synchronization scheme, probably using semaphores.
In short, it would be a significant amount of work to implement, and it wouldn't "feel" like the JVMs were sharing objects. It would be easier to use an existing database or distributed caching solution.
Try using JCS:
http://commons.apache.org/proper/commons-jcs/
Hope it helps! ;)
On Inter process communications, Java says:
To facilitate communication between processes, most operating systems
support Inter Process Communication (IPC) resources, such as pipes and
sockets. IPC is used not just for communication between processes on
the same system, but processes on different systems.
I would rather go for pipes or sockets. This will make your life a lot easier and your web services more flexible, as they can run on two separate machines still with the ability to talk to each other as if they were setting side by side.
This is being said, back to practice. Say for example you have a set of objects {a,b,c} you want to share between your services. Create a data store class that holds {a,b,c} objects and whenever there is an update, do it in the data store dataStore.setA(A new_a). Behind the scene, and for every update, the local data store will notify the remote data store sitting in the other application and transmit all the updates that have just been made. The following DTO can be used to transmit all changes from one data store to another:
public class ObjectUpdateEvent<Source> implements Serializable {
private String fieldName;
private Object previousValue;
private Object newValue;
private Source source;
// Constructor...
}
Updating an the object "a" can be done the following way
public class DataStore{
// .....
public setA(A new_a){
ObjectUpdateEvent<DataStore> updateDto = new ObjectUpdateEvent<DataStore>();
updateDto.setPreviousValue(a);
updateDto.setNewValue(new_a);
sendUpdateDto();
a = new_a;
}
}
EDIT: This is exactly what #duffymo mentioned above.
How about using a shared library.
You can refactor your logic, move them to a separate library, and build as a separate jar.
The jar should be place in tomcat_home/lib directory.
And in your web apps the library dependency should be set as provided ( in maven )
You store create and store the objects you need to be shared in the shared memory, and access them from any web

Java RMI without RMI Registry

I am rather new to java RMI and am trying to create a Peer 2 Peer bit torrent like application wherein multiple instances of the same peer may be on the same machine. This would mean that I would need to be able to have more than one remote object of the same type registered on the same machine. The RMI registry seems to only allow me to have one implementation of a Remote Object on any machine as the registry would not be able to differentiate between which of the objects it should be returning a reference to. Is there a way to bypass the registry such as by specifying an IP and port where I know the other peer is exposing its remote object? If not do you have any ideas how I would be able to create multiple instances of the same object on the same machine? Any help with this would be greatly appreciated...
You can either start multiple rmi registries on different ports, or better bind the instances of the object under different names multiple times. But the best way is probably to do the logic in your code and return a new remote object every time it is needed. E.g. dependent on a parameter:
public MyRemoteObject connect(String name) throws java.rmi.RemoteException {
if("first".equals(name)){
return firstinstance;
}else if("new".equals(name)){
return new MyRemoteObject();
}
...
}
or something like this...
I would suggest you to forget about RMI - IMHO this technique is not applicable for your use case.
Define yourself a network protocol including a serialization and deserialization logic and use this for sending and receiving data on a raw socket connection.

How to access static variable of another program

I want to make two programs. where program 1 will have a static collection and some getter/setter to access/update its values.
I want that program 2 should be able to access/call getter/setter of program1. so that static collection can be shared among many programs/process
*i dont want to engage any port.
You can't just declare a variable static (or super-static) and expect it to be available in code outside of your program - it just doesn't work that way. What you need is some sort of inter-process communication, and the possibilities are endless. To name a few:
- serialize / deserialize to and from a file (local or on the network)
- sockets (basically, you open a network connection between two ports on localhost)
- a database
- shared memory (whether this is possible depends on the OS)
Your OS of choice may offer other means, but the principle remains the same: whenever the variable changes, one application needs to notify the other.
This cannot be done just with static variables. They are accessable everywhere inside the JVM your program run in, but can't be accessed that simple. Use RMI, or sockets, or input streams to handle this interprocess communication.
There is no strait way to do this. RMI or CORBA should work. But it will be an overkill. You may use plain old sockets to communicate between Java apps. Or use java.nio channels.

Sending an object over the Internet

I define a class, and then I instate an object of that class type. I want to send this object to another Java application running on a different computer transparently. What is the best technology to accomplish this?
You'll want to start by looking into serialization with the Java Serializable interface. Sun has a good article on it called Discover the secrets of the Java Serialization API.
Refer to the Java Sockets tutorial for information on actually transferring the serialized object over the network.
you can create object streams using the java API and send any serializable object. but you'll have to mind that these go unencrypted through the network:
on the sender's side:
CustomObject objectToSend=new CustomObject();
Socket s = new Socket("yourhostname", 1234);
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
out.writeObject(objectToSend);
out.flush();
and on the receiving end:
ServerSocket server = new ServerSocket(1234);
Socket s = server.accept();
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
CustomObject objectReceived = (CustomObject) in.readObject();
There are a lot of ways to do this. Here are some things to look into and you can pick the one that would work best for your application.
J2EE
RMI
Object Serialization pushing the bits over a Socket
Webservices
Pretty much any communication framework will allow you to push objects over a network in one way or another. You just need to review them and see which works for your application. A quick google should find even more methods.
A (de facto) standard to implement this would be to use a web service, for example using JAX-WS which is bundled in Java 6. See this tutorial for a java-first sample (i.e. using annotations). This is pretty straight forward and easy.
There are other approaches such as Serialization over a Socket, RMI, EJBs but, when working over the Internet, web services are a kind of natural choice as they rely on existing standards (SOAP, HTTP) and deal easily with firewalls (which might be a real issue for all other solutions).
Java provides (binary) object serialization using the ObjectOutputStream (and ObjectInputStream). You can just writeObject() into the stream and readObject() on the other end. All you need to do for this to work is implement the Serializable interface.
But rather than doing that manually, you may be interested in taken it one level up and using Remote Method Invocation. With RMI you can call methods on objects that live in another JVM, and all the serialization and networking happens under the hood.
And for the sake of completeness, there is also XML bean serialization, if you cannot use the binary format. That XML format is very generic (read: verbose and ugly), but there are some popular libraries (like XStream) that create alternative XML serializations.

Categories