1

I'm working on a project where I have two programs which need to invoke methods on some of each other's objects.

I do this by sending JSON objects over a TCP connection. These objects have a receiverID, methodName, and then a list of parameters. Each program has a HashMap from receiverIDs to actual object instances, and then I use reflection to invoke the method with the supplied methodName on the correct object instance.

This works, but it forces the methods that get called remotely to have an array of strings as their parameter. Then I have to look at the order that the parameters are packed into the array and read through it on the other end to parse each parameter into what the actual parameters of the method are.

This definitely doesn't feel like a very clean way to accomplish my goal, but I'm not sure how else to do it. I suppose I could mark each parameter with a type and then cast them based on the type, but I would have to add code for each new type of parameter that I want to pass.

  • Here the language matters. The capabilities of the programming language might help to make the implementation easier. What's the language? – Laiv Feb 1 '18 at 21:40
  • There's a paradigm named Convention over Configuration. If It was Java, you could implement annotations to annotate classes, methods, arguments, attributes, ... – Laiv Feb 1 '18 at 21:43
  • @Laiv One program is in Java and the other is in C#. I will look into the things you mentioned. Thanks! – lane spangler Feb 2 '18 at 0:07
  • See also Protocol Buffers – Erik Eidt Feb 2 '18 at 15:50
1

There are two possibilities as far as I can see:

  • the method name determines the parameters:

     string method1(string arg1, double arg2)
    

In this case you could supply a wrapper method (each method has one wrapper) that takes the JSON parameter object and builds the call. This is essentially the same as a decoration, and you might be able to do this using annotations, depending on what language you're using (as Laiv observed:

     *********
     * Wrapper
     *********
     string method1ViaJSON(json *pack):
         return this.composeReply(
              method1(
                  extractString('arg1', pack),
                  extractDouble('arg1', pack)
             )
         )

      # Decorators.
      @jsonReturning("string")
      @jsonCallable(name = "arg1", type = "string")
      @jsonCallable(name = "arg2", type = "double")
      def method1(arg1, arg2):
          ...

      /**
       * Annotations.
       */
      @jsonable(arg1 = "string", arg2 = "double", returns = "string")
      public String method1(String arg1, double arg2) {
          ...
      }
  • the caller establishes the parameter, and their type determines what method will be called:

     string method1(string arg1, double arg2)
    
     string method1(string arg1, string arg2)
    
     string method1(double arg1)
    

In this case you need to encode the type in the JSON, either in the name or as an ancillary property:

{
    "strArg1": "This is a string",
    "dblArg2": 12345.678
}

or { "arg1": { "type": "string", "value": "This also is a string" } }

Of course, the callee will always need to verify that the supplied data are of the correct type; this will not be accepted:

    { "type": "double", "value": "toil and trouble" }

Basically, the JSON endpoint is one, and it decodes the parameters based on method, or invokes the method through the appropriate wrappers and decorators. These either cascade the call down to the original method, or raise an exception ("Bad Parameter").

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.