Normal calls depend on the JAR packages of business clients. Generic calls do not depend on second-party packages. A generic call passes the name of the method to be called, the method signature, and parameter values to the specific GenericService API for service calling. Generic calls are applicable to some gateway applications that cannot depend on all the service-specific second-party packages. hsf-ops service testing also depends on generic calls.

Prerequisites

Use APIs to configure HSF services

You can set generic to true in HSFConsumerBean so that the HSF consumer ignores failures of API loading.

HSFApiConsumerBean hsfApiConsumerBean = new HSFApiConsumerBean();
hsfApiConsumerBean.setInterfaceName("com.alibaba.middleware.hsf.guide.api.service.OrderService");
hsfApiConsumerBean.setVersion("1.0.0");
hsfApiConsumerBean.setGroup("HSF");
// [Specify] generic settings: hsfApiConsumerBean.setGeneric("true");
hsfApiConsumerBean.init(true);

// Use the GenericService API to obtain the proxy: GenericService genericOrderService = (GenericService) hsfApiConsumerBean.getObject();
// ---------------------- Call -----------------------//
// [Call] Initiate an HSF generic call to return results of the Map type.
Map orderModelMap = (Map) genericOrderService.$invoke("queryOrder",
                            // The array of input parameter types of the method (xxx.getClass().getName())
                            new String[] { Long.class.getName() },
                            // Parameter. If the parameter is of the plain old Java object (POJO) type, it must be converted to the Map type.
                            new Object[] { 1L});

The $invoke method that is provided by GenericService contains the name of the actually called method, type of the input parameters, and parameters. This helps the provider locate the method based on the contained information. Provider-dependent API JAR packages are unavailable. Therefore, an input parameter of the custom data transfer object (DTO) type must be converted to the Map type that can be serialized by the consumer.

Call methods and parameter description
  • Methods do not have input parameters and support only methodName: service.$invoke("sayHello", null, null).
  • The generic method type is supported, such as List<String>. Pass only the java.util.List that is the value of List.class.getName(). Do not pass java.util.List<String>. Otherwise, the method cannot be found.
  • If the format of a call method is uncertain, the caller can write a unit testing that depends on the second-party package for generic calls. A description format of the Map type for POJO Bean can be generated by using the generalize() method of the com.taobao.hsf.util.PojoUtils utility class that is provided by HSF.
    Map pojoMap = (Map) PojoUtils.generalize(new OrderModel());
  • Pass the demo whose parameters are of the POJO type.
     class User {
        private String name;
        private int age;
        // Use the standard POJO format. The getter and setter methods are omitted here.
       }
    
       // Directly use the Map type to construct a generic parameter of the POJO type. Map param = new HashMap<String, Object>();
       param.put("age", 11);
       param.put("name","Miles");
       // If the input parameter is a child class of the declared parameter type, pass the class field to indicate the actual type of the POJO. The provider must have this type.
       param.put("class", "com.taobao.User");

Use Spring to configure HSF services

Spring Framework is a component that is widely used in applications. If you do not want to configure HSF services by using APIs, you can configure them by using Spring XML. The following XML configuration has the same effect as the preceding API configuration:

<bean id="CallHelloWorld" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean">
    <!--[Specify] the interface for service subscription. -->
    <property name="interfaceName" value="com.alibaba.middleware.hsf.guide.api.service.OrderService"/>
    <!--[Specify] the version of the service. -->
    <property name="version" value="1.0.0"/>
    <!--[Specify] the group to which the service belongs. -->
    <property name="group" value="HSF"/>
    <property name="generic" value="true"/>
</bean>

Notes

  • By default, the routing rule does not take effect if the consumer does not include the interface class in a generic call.
  • The generic call performs worse than a normal call.
  • A service exception is thrown if -Dhsf.generic.throw.exception=true is configured. The default value is false and indicates that the exception is generalized into the returned results of the Map type.

    If an exception class exists in your on-premises environment and the exception class is not of the RuntimeException type or its child class, UndeclaredThrowableException is thrown. This is because the exception is not declared in com.taobao.hsf.remoting.service.GenericService. The actual exception can be retrieved through getCause.

    If the exception class does not exist in your on-premises environment, com.taobao.hsf.util.GenericInvocationException is thrown.