I'm looking for a communication channel between two java programs running on the same machine. I've found a few options (RMI and XML-RCP) but none of the examples that I found show exchange of objects wich class it's non-primitive and not know on JDK (our own objects).
So, what's the easy technology to use when I want to do this (note that Utils.jar it's on the classpath of Server.jar and Client.jar):
Utils.jar:
class MyClassRequestParams { ... }
class MyClassReturnParams { ... }
Client.jar:
// Server creation
...
// Send request
MyClassRequestParams params = new MyClass...
MyClassReturnParams response = server.send("serverMethodName", params);
Server.jar:
MyClassRequestParams serverMethodName(MyClassRequestParams params)
{
MyClassReturnParams response = new MyC...
// do processing
return response;
}
Just make your transport classes implement the Serializable interface, and everything will be fine with RMI. Note that every object referenced bt the transport object should also be Serializable.
The RMI tutorial uses an example with a custom Task interface implemented by a Pi custom class that is not a "standard" JDK class.
You may also consider Versile Java (I am one of its developers). Follow the link for an example of making remote calls and defining remote interfaces. It implements a platform-independent standard for remote ORB interaction, currently also available for python.
Related
I am currently facing problems integrating the existing Piketec TPT Java API (http://javadoc.jenkins.io/plugin/piketec-tpt/com/piketec/tpt/api/package-summary.html) in a Java project by using Reflection.
The TPT Api provides an interface called "TptApi", which contains several abstract methods, that are used to access TPT projects.
I have already integrated other APIs such as the Dox4j-API, where a class instance was used as invokation target. Obvisouly, this is not the correct way for accessing method from an interface.
My goal is to access the method "OpenResult openProject(File f)" from the TptApi interface (http://javadoc.jenkins.io/plugin/piketec-tpt/com/piketec/tpt/api/TptApi.html#openProject-java.io.File-).
My code:
ClassLoader cl = new URLClassLoader(...);
Map c = new HashMap();
File file = new File("test.prj");
c.put("TptApi", cl.loadClass("com.piketec.tpt.api.TptApi"));
c.put("OpenResult", cl.loadClass("com.piketec.tpt.api.OpenResult"));
//The way I did it with 'normal' classes, not applicable with the interface:
//Object target = ((Class) c.get("TptApi")).newInstance();
OpenResult or = (OpenResult)((Class) c.get("TptApi")).getMethod("openProject", new Class[]{File.class}).invoke(target, new Object[]{_file});
So how do I access abstract interface methods by Reflection?
I just stumbled over this Question so let me answer it even if it is a bit outdated. I read in your comments that you assume you do not need the TPT tool itselfe to use the API. That is simply wrong. The API is just a way to communicate via RMI with an open TPT instance. To connect to TPT the TPT instance must have enabled RMI and you have to know the configurable port and binding name. You can do that in the Preferences under "TPT API" or by starting TPT with command line arguments "--apiPort " and "--apiBindingName ". Now you can obtain the TptApi instance using these two lines of code:
Registry registry = LocateRegistry.getRegistry(HOST, PORT); // get Server/RMI-Registry
TptApi remoteApi = (TptApi)registry.lookup(BINDING_NAME); // get TPT-API
My initial post did not assume that TPT is not necessary for the usage of the API. It indeed is. The way how to enable the API in TPT is well-documented, the two lines of code you posted are also ok. The problem I described is to access the API by using Java reflection. For other APIs I could do this by using "newInstance" to get access to the tool. With TPT, the corresponding API object is an interface instead of a class, so there is no way to instantiate it. Therefore I wanted to know how this specific API can be accessed via reflection.
I am trying to develop a simple SMTPclient for testing purposes using the SubethaSmtp client package. i want to use the SMTPClient class instead of the SmartClient class for more control but i have not been able to figure out how to write mail data using SMTPClient, the only OutputStream exposed to public or external subclasses is the one for sending commands, the ones for sending data (after sending the DATA command) is exposed only to classes in the same package (SmartClient).
am i missing something here? i would like to know how a direct subclass of SMARTClient can written to work around this problem.
Looks like you are correct, you cannot simply extend the SMTPClient and get access similar to the one that SmartClient has, being a same-package class.
At this point you can either:
1) Fork your own version of the app from https://github.com/voodoodyne/subethasmtp and do whatever the hell you like with it, or
2) Go all the way and implement your own version of SMTPClient, as the package protected SMTPClient.dotTerminatedOutput;, used by SmartClient.dataWrite() actually is just instantiated like so
...
this.rawOutput = this.socket.getOutputStream();
this.dotTerminatedOutput = new DotTerminatedOutputStream(this.rawOutput);
...
Assume that we've some interface my.gwt.shared.Facade in shared package of our GWT project (exists both server and client) and two implementation of it: class my.gwt.client.ClientFacadeImpl (exists only client) and class my.gwt.server.ServerFacadeImpl (exists only server).
Is there any way to write a piece of code or annotation that substitute ClientFacadeImpl in client side and ServerFacadeImpl in server side?
Thanks all for the answers and discussion. I've found simple and elegant solution for my needs.
So, I've interface my.gwt.shared.Facade and two classes: class my.gwt.client.ClientFacadeImpl and class my.gwt.server.ServerFacadeImpl.
interface Facade {
Map<Boolean, Facade> FACADES = new HashMap<Boolean, Facade>();
}
Now, we should fill you FACADES interface. This is done like that:
public class MyEntry implements EntryPoint {
static {
Facade.FACADES.put(true, ClientFacadeImpl.INSTANCE); // client side
}
And
#Startup
#Singleton
public class Initializer {
#PostConstruct
private void init() {
Facade.FACADES.put(false, ServerFacadeImpl.INSTANCE); // server side
// other things
}
}
Now, when I need to get appropriate Facade, I just write
Facade facade = Facade.FACADES.get(GWT.isClient());
Also in this case in map is only corresponding to server or client side implementation.
P. S. Goal of this question was to allow handling of some GwtEvents fired on client direclty on server and vice-versa. This solution removed large set of DTO (data transfer objects) and simplified code a lot.
There's no answer to your question other than "it depends". Or rather, of course there are ways of doing what you ask, but would you accept the tradeoffs?
Given that you tagged the question with dependency-injection, let's start with that. If you use a DI tool with GWT, it's likely GIN (Dagger 2 would work, but it's still under development). In that case, just use distinct modules for GIN client-side and Guice server-side that bind() the appropriate implementation.
For a few releases, GWT.create() can be made to work outside a GWT (client) environment (i.e. on the server side). You have to register a ClassInstantiator on the ServerGwtBridge as an alternative to the rebind rules from gwt;xml files. So you could have a <replace-with class="my.gwt.client.ClientFacadeImpl"> rule in your gwt.xml, and a ClassInstantiator returning a ServerFacadeImpl on the server side.
Finally, you can also use a static factory and replace it with a client-side specific version by way of <super-source>.
A last one, but I'm unsure whether it'd work: you could use an if/else using GWT.isClient(), and annotate your ServerFacadeImpl with #GwtIncompatible to tell the GWT compiler that you know it's not client-compatible.
Can anyone suggest any design pattern to dynamically differentiate the memcahce instances in java code?
Previously in my application there is only one memcache instance configured this way
Step-1:
dev.memcached.location=33.10.77.88:11211
dev.memcached.poolsize=5
Step-2:
Then i am accessing that memcache in code as follows,
private MemcachedInterface() throws IOException {
String location =stringParam("memcached.location", "33.10.77.88:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then i am invoking that memcache as follows in code using above MemcachedInterface(),
Step-3:
MemcachedInterface.getSoleInstance();
And then i am using that MemcachedInterface() to get/set data as follows,
MemcachedInterface.set(MEMCACHED_CUSTS, "{}");
resp = MemcachedInterface.gets(MEMCACHED_CUSTS);
My question is if i introduce an new memcache instance in our architechture,configuration is done as follows,
Step-1:
dev.memcached.location=33.10.77.89:11211
dev.memcached.poolsize=5
So, first memcache instance is in 33.10.77.88:11211 and second memcache instance is in 33.10.77.89:11211
until this its ok...but....
how to handle Step-2 and Step-3 in this case,To get the MemcachedInterface dynamically.
1)should i use one more interface called MemcachedInterface2() in step-2
Now the actual problem comes in,
I am having 4 webservers in my application.Previoulsy all are writing to MemcachedInterface(),but now as i will introduce one more memcache instance ex:MemcachedInterface2() ws1 and ws2 should write in MemcachedInterface() and ws3 and ws4 should write in ex:MemcachedInterface2()
So,if i use one more interface called MemcachedInterface2() as mentioned above,
This an code burden as i should change all the classes using WS3 and WS4 to Ex:MemcachedInterface2() .
Can anyone suggest one approach with limited code changes??
xmemcached supports constistent hashing which will allow your client to choose the right memcached server instance from the pool. You can refer to this answer for a bit more detail Do client need to worry about multiple memcache servers?
So, if I understood correctly, you'll have to
use only one memcached client in all your webapps
since you have your own wrapper class around the memcached client MemcachedInterface, you'll have to add some method to this interface, that enables to add/remove server to an existing client. See the user guide (scroll down a little): https://code.google.com/p/xmemcached/wiki/User_Guide#JMX_Support
as far as i can see is, you have duplicate code running on different machines as like parallel web services. thus, i recommend this to differentiate each;
Use Singleton Facade service for wrapping your memcached client. (I think you are already doing this)
Use Encapsulation. Encapsulate your memcached client for de-couple from your code. interface L2Cache
For each server, give them a name in global variable. Assign those values via JVM or your own configuration files via jar or whatever. JVM: --Dcom.projectname.servername=server-1
Use this global variable as a parameter, configure your Service getInstance method.
public static L2Cache getCache() {
if (System.getProperty("com.projectname.servername").equals("server-1"))
return new L2CacheImpl(SERVER_1_L2_REACHIBILITY_ADDRESSES, POOL_SIZE);
}
good luck with your design!
You should list all memcached server instances as space separated in your config.
e.g.
33.10.77.88:11211 33.10.77.89:11211
So, in your code (Step2):
private MemcachedInterface() throws IOException
{
String location =stringParam("memcached.location", "33.10.77.88:11211 33.10.77.89:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then in Step3 you don't need to change anything...e.g. MemcachedInterface.getSoleInstance(); .
You can read more in memcached tutorial article:
Use Memcached for Java enterprise performance, Part 1: Architecture and setup
http://www.javaworld.com/javaworld/jw-04-2012/120418-memcached-for-java-enterprise-performance.html
Use Memcached for Java enterprise performance, Part 2: Database-driven web apps
http://www.javaworld.com/javaworld/jw-05-2012/120515-memcached-for-java-enterprise-performance-2.html
I am trying to send an object in java over a physical network (not over localhost) but it seems I have something wrong.
The interface to the object (client and server have this):
public interface distributable extends Serializable {
public void test();
}
The Object I am trying to send (only server has this):
class ObjectToSend implements distributable {
public ObjectToSend() {
}
public void test() {
system.out.println("worked!");
}
}
Server:
private ObjectToSend obj = new ObjectToSend();
obj_out_stream.writeObject(obj);
obj_out_stream.flush();
Client:
private distributable ReceivedObj = null;
try {
ReceivedObj = (distributable) obj_in_steam,readObject();
} catch (ClassNotFoundException e) {
System.err.println("Error<w_console>: Couldn't recieve application code!");
}
ReceivedObj.test();
Everything was working when the ObjectToSend class implemented Serializable and I wasn't using an interface because all my classes were in one directory so the client 'knew' about the object. Now I want it to work across a physical network so the client only has the interface to the object. It seems that client can not receive the object as the exception is thrown every time.
As the other answers suggest, the Client also has to know the class of the object you want to send.
Usually, one creates three packages/projects for such a classic client-server example:
Common: Code that is used by client and server; the class definition of the objects you want to send from the server to the client belongs here
Client: All code only the client needs to know about
Server: All code only the server needs to know about
To be able to serialize and deserialize objects with objectinput/outputstream the classes must implement Serializable.
Also the deserializer must be able to find the classes on the classpath that you are trying to deserialize since this is embedded in the Serialized form.
If you want the client to have only the interface -- at compile time -- then you'll need to download the actual class from the server at run-time.
Jini (aka Apache River) makes this easy.
It's supposed to be like this. What can you do with a class whose code you don't have?
Have a look here: stackoverflow.com/questions/8175052/java-polymorphism-my-teacher-claims-you-can-distribute-an-executable-object-thr