Generic call

Update time: 2019-06-21

Generic calls provide the ability for clients to initiate calls without having to rely on the server`s interface. Currently, the generic call of SOFARPC only supports using Hessian2 as the serialization protocol under the Bolt communication protocol.

SOFABoot environment

Publish Service

There is nothing special about publishing a service. Just publish the service normally, for example:

<!-- generic -->
<bean id="sampleGenericServiceImpl" class=""/>
<sofa:service ref="sampleGenericServiceImpl" interface="">

Reference Service

<sofa:reference jvm-first="false" id="sampleGenericServiceReference" interface="">
        <sofa:global-attrs generic-interface=""/>

The jvm-first can be left empty according to the actual situation. The interface should be the general interface of generic call. As for the generic-interface, you can just write in the name of the interface to be called.

Initiate a call

 GenericService sampleGenericServiceReference = (GenericService) applicationContext
 GenericObject genericResult = (GenericObject) sampleGenericServiceReference.$genericInvoke("sayGeneric",
            new String[] { "" },
            new Object[] { genericObject });


ConsumerConfig<GenericService> consumerConfig = new ConsumerConfig<GenericService>()
GenericService testService = consumerConfig.refer();

String result = (String) testService.$invoke("sayHello", new String[] { "java.lang.String" },new Object[] { "1111" });

You can set the service as a generic service and set the interface name of the server by setGeneric as above. GenericService is used as a generic service, and GenericService can initiate generic calls. You need to pass in the method name, method type, and method parameters when invoking a call.

If the parameter or return result is also required to be generalized on the client side, you can achieve this with GenericObject.

GenericObject genericObject = new GenericObject("");
genericObject.putField("str", "xxxx");
genericObject.putField("num", 222);

GenericObject result = (GenericObject) testService.$genericInvoke("echoObj",
                    new String[] { "" },
                    new Object[] { genericObject });

String str = result.getField("str");
String num = result.getField("num");

The serialization result can be obtained as above. The instructions for the complete generalization call are as follows:

* Java Bean
public class People {
    private String name;
    private int    age;
    // getters and setters

 * Interface provided by the service provider
interface SampleService {
   String hello(String arg);
   People hello(People people);
   String[] hello(String[] args);

 * Client
public class ConsumerClass {
   GenericService genericService;

   public void do() {
      // 1. $invoke only supports the scenario where the method parameter types exsit in the current application`s ClassLoader.
      genericService.$invoke("hello", new String[]{ String.class.getName() }, "I'm an arg");
      // 2. $genericInvoke supports the scenario where the method parameter types do not exist in the current application`s  ClassLoader.
      // 2.1 Construct parameters
      GenericObject genericObject = new GenericObject(""); // Specify the full path class name in the constructor.
      genericObject.putField("name", "Lilei"); // Call putField to specify the field value.
      genericObject.putField("age", 15);
      // 2.2 make a call without a return type specified,  then the returned result type is GenericObject.
      Object obj = genericService.$genericInvoke("hello", new String[]{""}, new Object[] { genericObject });
      Assert.assertTrue(obj.getClass == GenericObject.class);
      // 2.3 make a call with the return type specified.
      People people = genericService.$genericInvoke("hello", new String[]{""}, new Object[] { genericObject }, People.class);
      // 2.4 make a call, and the parameter type is array.
      String[] result = (String[]) proxy.$genericInvoke("hello", new String[]{new String[0].getClass().getName()}, new Object[]{ new String[]{"args"} });