1. Home
  2. Developers
  3. LEAP Framework v1.x
  4. Intra-Feature Service Calls

Intra-Feature Service Calls

Overview

Intra-Feature service calls occur when the currently executing service tries to access a service that is defined within the bounds of a different Leap Feature deployed to the same JVM.

Why is this important?

Within the Leap framework it is technically possible to invoke any service whether it is defined within the same feature or not. This could be done using the direct:<routeName> component provided by Apache Camel. Simply because it can be done does not mean it should be.

Instead, intra-feature service calls need to be made using the FeatureServiceCall API that is provided as part of the Leap Framework. As described in detail by this guide, the FeatureServiceCall class allows developers to call services in other features in such a way that best-practices are followed.

One of the key architectural pillars of Leap states that “Features must be independently deployable and they are independently responsible for service-level authentication and authorization“. Directly invoking a service from another feature would violate this architectural requirement and cause a significant security risk.

Features deployed in different VMs cannot use this method of communication and must choose an appropriate protocol.

How does the FeatureServiceCall API work?

This API prepares a new Exchange to be sent while making the service call. Because FSC uses the ProducerTemplate along with direct, FSC call are synchronous and maintain the original transactional context.

In the same way that the Leap framework sends inbound requests to the appropriate feature and service, FeatureServiceCall (FSC) sets the Exchange Headers necessary for the Exchange to reach the desired service. The required headers need to be set with their respective setters. Required fields are as follows:

  • siteId
  • accountId
  • featureGroup
  • featureName
  • serviceName

Specific scenarios may dictate that the new exchange be configured with the content-type of application/leap+json.vnd. In these cases, use the setter setLeapResponseType(boolean bool) with a value of trueto satisfy the requirements of the destination service.

The FSC API sends the new Exchange to the “baseEntry” route which then guarantees proper security and leap best-practices are enforced.

How to access Response data?

After the secondary service is invoked, the response body and headers are placed into the LeapDataContext (LDC) of the original Exchange. To access the new data that is now in LDC, developers may use any of the numerous methods made available in LeapDataContext such as getContextElement.

The response body is inserted with a tag matching the serviceName provided when the call is made. Exchange headers are inserted with a tag matching the serviceName + “headers”. See the examples at the bottom of the guide.

Examples

The FSC API is a Java class that should not be called directly from the Route, but instead it should be implemented as part of a custom bean. In the following examples you will see how to use FSC in detail.

<!-- Remaining Impl route removed for brevity -->

<route id="example-service-call">
	<from uri="direct:service-call-route" />
    <to uri="bean:myCustomBean?method=getOtherFeatureData" />
</route>
public class myCustomBean {
	public void getOtherFeatureData(Exchange exchange) {
		
		LeapDataContext leapDataContext = null;
		FeatureServiceCall featureServiceCall = new FeatureServiceCall();
		leapDataContext = exchange.getIn().getHeader(LEAP_DATA_CONTEXT, LeapDataContext.class);

		featureServiceCall.setFeatureGroup("HumanResources");
		featureServiceCall.setFeaturename("Employee");
		featureServiceCall.setServiceName("getEmployeeDetails");
		featureServiceCall.setProvider("default");
        featureServiceCall.setLeapResponseType(true);

        featureServiceCall.setSiteId(leapDataContext.getServiceDataContext().getSite().toString());

        // Call service
        featureServiceCall.makeFeatureServiceCall(exchange);

        employeeData = (JSONObject) leapDataContext.getContextElement("getEmployeeDetails").getData().getItems().getData();

        employeeExchangeHeaders = (JSONObject) leapDataContext.getContextElement("getEmployeeDetailsheaders").getData().getItems().getData();
	}
}

Providing Custom Service Headers

In the case that you need to send additional data to a service via headers, those headers can be passed via setServiceCallHeaders(Map<String, Object>).

public class myCustomBean {
	public void getOtherFeatureData(Exchange exchange) {
		
		LeapDataContext leapDataContext = null;
		FeatureServiceCall featureServiceCall = new FeatureServiceCall();
		leapDataContext = exchange.getIn().getHeader(LEAP_DATA_CONTEXT, LeapDataContext.class);
        Map<String, Object> headersToSend = new HashMap<String, Object>();

        headersToSend("arg1", "value1");
        headersToSend("arg2", new JSONObject().toString());

		featureServiceCall.setFeatureGroup("HumanResources");
		featureServiceCall.setFeaturename("Employee");
		featureServiceCall.setServiceName("getEmployeeDetails");
		featureServiceCall.setProvider("default");
        featureServiceCall.setSiteId(leapDataContext.getServiceDataContext().getSite().toString());
        featureServiceCall.setServiceCallHeaders(headersToSend);

        // Call service
        featureServiceCall.makeFeatureServiceCall(exchange);
    }
}
Updated on June 22, 2022

Was this article helpful?

Related Articles