Look at the following use case.
I have a client (Java) application, which wants to get/set the state of another, remote application (C). The communication between them is done via SIP, which is run in another thread.
The SIP interface can do the following:
sendMessage
onRequest
I have two ideas for the architecture:
RPC (JSON-RPC)
Define a class which does the marshalling/unmarshalling for JSONRPCRequests and JSONRPCResponse (http://software.dzhuvinov.com/json-rpc-2.0-base.html)
Define a Invoker class, which has something like a call(server, name, arguments) method.
In the Invoker class, the name and arguments are put into a JSONRPCRequest and sent via the SIP layer sendMessage
Now comes my problem. How do i actually get the right back to the caller? The control flow is now:
The onRequest method is called, but I do now know whether it is the answer to my previous call. What i do is putting all responses reaching my server into a Map, and just poll that list in the Invoker.
A rough sketch might be;
Invoker (provides API to client)
class Invoker {
private Channel channel;
public Invoker(Channel channel) { this.channel = channel; }
public Object call(String server, String name, Object .. args) {
JSONRPCRequest req = ...;
channel.sendMessage(server, req.toString());
while( ! channel.hasResponse(req.id()) {
Thread.sleep(42);
}
return channel.getResponse(req.id()).result();
}
}
Channel (interface to messenger):
class Channel {
private Map<Object, JSONRPCResponse> responses = new //;
private Sip sip = new Sip() {
public void onRequest(String msg) {
JSONRPCResponse response = JSONRPCResponse.parse(msg);
responses.put(msg.id(), response);
}
};
public void sendMessage(String server, String message) {
sip.sendMessage();
}
public boolean hasResponse onRequest(Object id) {
responses.hasKey(id);
}
public JSONRPCResponse getResponse(Object id) {
responses.get(id);
responses.delete(id);
}
}
SIP (messenger itself):
abstract class Sip {
public void sendMessage(String msg) {
// SIP magic
}
public abstract void onRequest(String msg);
}
Is there a better way to do that? My biggest problems/code smells are:
the blocking in Invoker
the protocol is in Invoker, maybe I want to switch marshalling to something else
the map as mean to get the correct response for a request
the SIP abstract method looks strange
No error handling
No timeout
Message Passing
Is there an easy way to get rid of RPC, and implement something like RPC with just message passing? Any hints for pattern are welcome. I do not need the code itself, I am totally fine with just architecture. I tried to google for message passing implementations, and how they actually change state with it, but I did not find anything useful. How to implement timeout/ error handling?
Any good books/literature on that topic is also welcome, as I never programmed such distributed stuff.
Any other ideas on which protocol to use inside SIP to change state is welcome, too, as RPC was my initial thought, and I did not find anything other useful.
The code will not compile, I guess, it was just to visualize my idea.
Define a service interface that has meaningful (for the us case) methods. Instead of using blocking calls, have the client supply a ResponseHandler that will be invoked when the operation is complete:
interface ResponseHandler {
void onComplete(Response response);
void onError(Throwable error);
}
interface SomeService {
void set(String attribute, Object value, ResponsHandler responseHandler);
void get(String attribute, ResponseHandler responseHandler);
}
The implementation of the Service interface can use any suitable protocol, but it has to correlate requests with responses in order to invoke the correct callbacks.
Related
I am trying to define a static method in the service interface to make an rpc call. But it doesn't allow me to do so. here I am pasting my code
Client class
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics) {
String url = GWT.getModuleBaseURL() + "domesticservice";
domesticServiceAsync = (DomesticServiceAsync) GWT.create(DomesticService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) domesticServiceAsync;
endpoint.setServiceEntryPoint(url);
domesticServiceAsync.sendDomesticData(product,dma,yrmnths,dist,metrics,new Domestichandler<Void>() );
}
public class Domestichandler<Void> implements AsyncCallback<Void> {
#Override
public void onFailure(Throwable caught) {
String error = caught.getMessage();
System.out.println(error);
}
public void onSuccess(Void result) {
System.out.println("perfect");
}
}
Service
public interface DomesticService extends RemoteService {
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics);
}
public interface DomesticServiceAsync {
void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics,AsyncCallback<Void> callback);
}
Server side -
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics) {
System.out.println(product);
}
Basically I am trying to send the values from the front interface to the server side and I don't want any return value. But the values passed to the server side should be stored globally in the server class so i can access those values in different method. I tried changing all the senddomestic values to static but it won't allow me to do so? why?
Because RemoteServiceServlet needs to invoke your service methods somehow and the implementation expects instance methods. But this shouldn't prevent you from assigning the method data to static fields. Just be aware of multi threading.
GWT always uses instance methods for RPC calls, static methods are not possible in this case.
What is important to understand about GWT is that any RemoteServiceServlet instances are created and maintained by the servlet container (e.g. Tomcat). The servlet container might create a number of servlet instances on startup (Tomcat creates 6 RemoteServiceServlet instances by default) and then uses load balancing to determine which servlet handles an RPC request at a particular point in time. Depending on settings of course, you have little control over which RemoteServiceServlet instance exactly will handle a specific RPC request.
Therefore, if you want to store information on the server side globally using RPC calls, the idea proposed by YuPPie to use static fields of your RemoteServiceServlet implementation is a BAD idea. You will have no idea which of the RemoteServiceServlet instances maintained by the server contains your static data, and any subsequent calls to retrieve the data will give erratic results.
You have a few options, though. Storing the information in a database (or something similar) is the most straightforward option, but from your post I'm guessing you want something simpler. A singleton class which holds your data is probably the way to go. A thread-safe example:
public class DataContainer
{
private static DataContainer _singleton;
private String _dataField1;
public static synchronized DataContainer getInstance()
{
if (_singleton == null)
_singleton = new DataContainer();
return _singleton;
}
public synchronized String getDataField1()
{
return _dataField1;
}
public synchronized void setDataField1(String dataField1)
{
_dataField1 = dataField1;
}
}
Then in the server side implementation of your RPC call you could do something like:
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics)
{
DataContainer.getInstance().setDataField1(product);
}
This way, if there are multiple servlet instances they will all share the singleton instance of DataContainer, thus giving you a place to store your data globally. I hope this will help you.
Say I've got a logging service deployed to some (jaxrs-compliant) container.
#Path("/logger")
public class LogService
{
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
System.out.println(msg);
// ...
}
}
If I make the following request to the container hosting this service, I expect to see the output of my message to the container's stdout log:
GET <host>:<port>/logger/log?msg=foo
Now I'd like to change the implementation of this log message at runtime with behavior specified by some arbitrary client.
For example, say we had an interface:
public interface LoggerApi
{
void logMessage(final String msg);
}
and the service was redefined to use an implementation of this interface:
#Path("/logger")
public class LogService
{
public static LoggerApi LOGGER = new LoggerApi()
{
void logMessage(final String msg)
{
System.out.println(msg);
}
}
#GET
#Path("/log")
public Response log(final String #QueryParam("msg") msg)
{
LOGGER.logMessage(msg);
// ...
}
}
The question thus becomes, how can I hot swap the implementation of logger with a new implementation defined by some client external to the server.
My first instinct was that RMI and/or dynamic proxies could get me where I wanted to be, but I'm not soo sure with all the security policy madness.
Essentially what I want is the ability to do the following:
#Path("/config")
public class ConfigService
{
#POST
#Path("/loggerApi")
public Response setLoggerApi(final LoggerApi clientSuppliedLogger)
{
LogService.LOGGER = clientSuppliedLogger;
// ...
}
}
Thoughts?
(Oh and I know this poses a severe security risk and such a pattern ought never be used in production environments. My interest is in designing a mock service where the service's behavior and side effects can be defined by the integration tests calling the mock service)
I think the short answer may be no, but I'm hoping I can get alternative suggestions. Assume I have a data object and a data service. The data service is an interface and has the following method.
public Data getData();
I'm creating a proxy for the service using the following invocation handler plus Netty to do what I'd call asynchronous rpc. The proxy is on the client side.
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Convert the call into an async request that returns a ListenableFuture
APCRequest request = new APCRequest(serviceType, method, args);
ListenableFuture future = apcClient.asyncMessage(request);
// This blocks until the future finishes
return future.get();
}
This works fine. However, if my client is a UI, I end up wrapping the service call in something like a SwingWorker. I'd prefer to come up with a way of returning the ListenableFuture that I already have sitting there. Is there any way I can accomplish that without creating a separate, asynchronous service API. For example:
public ListenableFuture<Data> getData();
If I could have my InvocationHandler return the wrong type, I could use something like this.
public abstract class AsyncServiceCall<S, D> { // S = service type, D = expected doCall return type
protected final S service;
protected AsyncServiceCall(Class<S> serviceType, APCClient client) {
ProxyFactory proxyFactory = new ProxyFactory(client);
// The true tells the proxyFactory we're expecting a ListenableFuture<D>
// rather than the real return type.
service = proxyFactory.createProxy(serviceType, true);
}
// Sub-classes would make a normal method call using this. For
// example, service.getData()
public abstract Object doCall();
#SuppressWarnings("unchecked")
public ListenableFuture<D> execute() {
return (ListenableFuture<D>) doCall();
}
Is there another way of accomplishing what I want? Performance isn't an issue for me, so blocking until the proxy can get the return value from the future is still an option if there's no simple way of doing what I want. It just seems like a waste since I want an asynchronous call in the UI anyway.
Keeping my service API simple is more of a priority than anything. I want to be able to prototype using a simple service provider that instantiates service implementations directly and plug in my remoting protocol / server that's using dynamic proxies / Netty late in the development cycle.
If you want to keep your API simple then I would suggest providing only the async API in the interface - it's much easier to wrap up a synchronous implementation in an asynchronous API than vice-versa.
public interface DataService {
public ListenableFuture<Data> getData();
}
public abstract class LocalDataService implements DataService {
public ListenableFuture<Data> getData() {
SettableFuture<Data> result = SettableFuture.create();
try {
Data theData = computeData();
result.set(theData);
} catch(Throwable t) {
result.setException(e);
}
return result;
}
protected abstract Data computeData() throws Throwable;
}
I have Threads that listens to incoming HTTP messages , i want to enable other developer that use my code to be able to use the messages that i received in any time. I saw in some mobile OS you can implement class and override onRecive function to receive the messages .
is this the right architecture to use in this case? if yes how could i implemented and if its not what is the best way to do it.
You can have a interface which another develoepr can implement and register with your code to be notified when a new message etc has arrived. There are any number of ways this can be achieved.
You could use the built in Observable class. or you could do something like this.
public interface Listener<T> {
public void onEvent(T t);
}
public class Listenable<T> {
private final List<Listener<T>> list = new CopyOnWriteArrayList<Listener<T>>();
public void register(Listener<T> listener) {
if (!list.contains(listener)) list.add(listener);
}
public void unregister(Listener<T> listener) {
list.remove(listener);
}
public void onEvent(T t) {
for (Listener<T> tListener : list)
tListener.onEvent(t);
}
}
The caller could implement the Listener interface or provide an object which does. It then registers this with the Listenable. The listenable can notify all registered listeners.
Take a look at the Observer Pattern.
You can have an interface called MessageListener:
public interface MessageListener{
void onMessage(String message);
}
Users of your library will create their own MessageListeners and will implement the onMessage method which defines what should be done when a message is received. They will also set (or register) this MessageListener with your "threads" before they are started.
Now whenever your thread gets a message, it will notify the listener(s) registered with it by calling the onMessage method.
I have this situation:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class MessageReceiver
{
MessageListener listener;
public MessageReceiver(MessageListener listener, other arguments...)
{
this.listener = listener;
}
loop()
{
Message message = nextMessage();
listener.onMessageReceipt(message);
}
}
and I want to avoid the following pattern: (Using the this in the Client constructor)
class Client implements MessageListener
{
MessageReceiver receiver;
MessageSender sender;
public Client(...)
{
receiver = new MessageReceiver(this, other arguments...);
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
The reason why i need the above functionality is because i want to call the sender inside the onMessageReceipt() function, for example to send a reply. But I dont want to pass the sender into a listener, so the only way I can think of is containing the sender in a class that implements the listener, hence the above resulting Client implementation. Is there a way to achive this without the use of 'this' in the constructor? It feels bizare and i dont like it, since i am passing myself to an object(MessageReceiver) before I am fully constructed. On the other hand, the MessageReceiver is not passed from outside, it is constructed inside, but does this 'purifies' the bizarre pattern?
I am seeking for an alternative or an assurance of some kind that this is safe, or situations on which it might backfire on me.
The Client's dependencies (such as MessageReceiver) could be injected into it rather than having the Client know how to construct the MessageReceiver:
Client client = new Client(...);
MessageReceiver rcvr = new MessageReceiver(client, ...);
client.setMessageReceiver(rcvr);
However I would suggest looking into breaking the circular dependency between these two classes, it sounds as if something is off in your design.
The real reason why passing this to another class in the first class's constructor is a bad practice is because you are allowing a reference to this to escape before it is fully constructed.
It wont backfire on you as long as this is never referenced before construction. However, you should never rely on that assumption. Concurrency is a big factor here, as well as the contract for the code you pass it to.
Since Client is a MessageReceiver, why not make it one?
public Client extends MessageReceiver implements MessageListener{
/* ... */
}
I don't see where the MessageReceiver is used, so at the moment you could write the code without MessageReceiver like this and it would be effectively the same:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class Client implements MessageListener
{
MessageSender sender;
public Client(...)
{
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
I think a standard publish-subscribe or Observer pattern is probably what you need - but it's hard to tell without understanding the subtleties of the problem that you are trying to solve.