Archived

This forum has been archived. Please start a new discussion on GitHub.

Implementing null object pattern for proxies on client-side

I have a simple Node interface:
interface Node
{
    ["cpp:const"] idempotent string getName() throws ExceptionBase;

    ["cpp:const"] idempotent Directory* getParent() throws ExceptionBase;

    ["cpp:const"] idempotent string getFullPath() throws ExceptionBase;
};
which is implemented on server side. I wanted to have another kind of Node on the client side which would be returned from methods when there is no connection and used like this:
public NodePrx findNode(name: String) {
    try { return nodeFinder.findNodeByName(name); }
    catch(Ice.LocalException e) { return new NoConnectionNodePrx(name); }
    // user exceptions pass through
}
and tried to implement it like this:
public class NoConnectionNodePrx implements NodePrx {
    private final String _name;

    public NoConnectionNodePrx(String name) { _name = name; }

    public String getName() { return name + "(No connection)" }

    public DirectoryPrx getParent() { return null; }

    public String getFullPath() { return ""; }

    // same for methods with __ctx parameters
}
But this doesn't work, because NodePrx actually extends Ice.ObjectPrx, which has a lot of methods I can't implement by myself. Is there a "default" implementation of ObjectPrx or some other way to do what I want?

Comments

  • benoit
    benoit Rennes, France
    Hi,

    You can't implement your own proxy on top of the generated proxy (or at least not without significant efforts).

    Instead, I recommend setting up a local object adapter and register a servant that implements the Node interface. This way, you can return the proxy for this local Ice object if no remote Ice objects are available. You can rely on collocation optimization to avoid having to listen on endpoints (see here for information on collocation optimization). To create an object adapter without endpoints, suitable for collocation optimization, you can call the following to create the object adapter:
       Ice::ObjectAdapterPtr adapter = communicator->createObjectAdapter("");
    

    Cheers,
    Benoit.
  • I've tried this, and it works, but didn't give me quite what I wanted. In particular, it doesn't help if connection is lost or regained in the process of working with a proxy. And I would need significant changes in my program to change proxies dynamically in this situation.
  • matthew
    matthew NL, Canada
    What do you want to occur if the connection is lost?
  • Actually, now that I think of it, I can just access all proxies via my own collocated adapter, where servants would keep a reference to the real remote proxies, and delegate calls when they have a connection (and return dummy values when they don't).
  • matthew
    matthew NL, Canada
    This sounds remarkably complicated. To me doing that is abusing the Ice object model. You'd have to explain this to any client of your interface, and correctly implement all these semantics in any programming language through which you'd want to access the server. My experience tells me that tricks like this seem to be initially clever but in the long run they turn out to be a maintenance nightmare.
  • This could happen only on client, I agree that it doesn't make sense to do this on server.
  • matthew
    matthew NL, Canada
    I think you've missed my point. I don't think you could implement your suggestion on the server, and I don't think it is a good idea to do it on the client. What benefit does this give you, or to put it another way what problem are you trying to solve?