. . .

Using other Services


In ApiOmat, you can execute CRUD operations on class objects of other services. To be able to communicate with other services, you first need to set up a used service relation. Once this is done, ApiOmat provides libraries for each used service that helps you to send requests to the used service's API. The library contains the model classes and an API client for each model.
The following sections describe how to set up your used service relation and how to use the service libraries to communicate with their API clients.

Please be aware of the inheritance and reference limitations which are described in Service Limitations.
Also: By default, all used service artifacts will be re-resolved every time you build your service.
The section "Automatic updating of used services" describes how this works, why it is done and how to change it.

Setting a used Service Library Relation

Ensure used Service Library is deployed to Host

Before setting a used service relation and before you can use the service library, you need to generate the library and deploy it to the Innkeeper service, which acts as a Maven repository for the artifacts.
To do this, you just need to call the following Brewer REST endpoint:

curl -X PUT $BREWER_BASE_URL/brewer/ms/$USEDSERVICE_NAME/v/$USEDSERVICE_VERSION/lib/deployToHost -u $AUTH

Once the library has been successfully generated and deployed, you can set the used service relation.
There are two ways to do this:

Option A) via REST

The first option to create a used service relation between two services is to call a specific YAMBAS REST endpoint. Afterwards, the generated service project will contain all the project files you need.
However this is not supported under the following circumstances:

  • You already deployed your generated service to Innkeeper and downloaded it without setting the flag merge=false

  • You have your sources locally and downloaded the service via the brewer:download Maven goal

The reason for that behaviour is that we don't overwrite all files (such as pom.xml or application.yml) to give you more freedom during development.
Therefore, you'd have to download the generated service using the merge=false flag and manually merge the changes in pom.xml and application.yml, or adapt the files manually according to option B (see below).

To set a used service relation via REST, use the following YAMBAS endpoint:

curl -X POST $YAMBAS_BASE_URL/yambas/rest/modules/$SERVICENAME/v/$SERVICEVERSION/parent -d "parentModuleName=$USEDSERVICE_NAME&parentModuleVersion=$USEDSERVICE_VERSION" -u $AUTH

To remove a used service relation, use the following REST endpoint:

curl -X DELETE $YAMBAS_BASE_URL/yambas/rest/modules/$SERVICENAME/v/$SERVICEVERSION/parent/$USEDSERVICE_NAME/v/$USEDSERVICE_VERSION" -u $AUTH

Once the used service relation is set, you need to trigger the first generation of the service either by using the compile action in the Dashboard or by calling Brewer's service generation REST endpoint (see step 5 in the Tutorial "Model your Service" or go to Brewer's usage documentation).
After generating and downloading your service, you can continue with integrating it into your IDE and skip option B to progress with the next section.

Option B) Code-first via Dependency

If you already generated your modelled service, you can set the used service relation in a code-first manner. In other words: This section contains the steps you need to do manually which are done automatically in the previous section.
In general, you just need to add the used service as a library dependency to the POM of your service and configure some Spring project features.
But let's go into detail:

Insert used Service Lib Dependency

First, check that the Innkeeper repositories to the artifacts are configured correctly within your POM. Normally, this should be done automatically by Brewer, but if you need to manually add these repositories, see the section Downloading and uploading your Service of the tutorial. The Innkeeper repositories are needed to locate the used service library we generated earlier.

Next, add the following Maven dependency to the POM of your generated service project:

<dependency>
<groupId>com.apiomat.microservice</groupId>
<artifactId>usedservice-lib</artifactId>
<version>1.0.0</version>
</dependency>

The artifactId consists of the used service name in lowercase followed by the suffix -lib. The version should match the service version you want to use.
After that, you need to update your Maven project to resolve the new dependency and get access to the other service.

Configure Feign Clients

We use Feign for communication between different service APIs. Feign is a declarative technology that simplifies web service client implementation (refer to the official Spring Cloud documentation to learn more about Feign).
Feign clients are used in our services to easily access other services' REST endpoints.

The EnableFeignClients annotation in the main class of the service specifies the packages to be scanned during application startup for available Feign client interfaces.
To enable Feign clients for your used service, add the base package path of the used service to the annotation.
In this example, you'd have to add com.apiomat.microservice.usedservice to the annotation of the class com.apiomat.microservice.myservice.MyServiceApplication:

@EnableFeignClients( basePackages = { "com.apiomat.microservice.myservice", "com.apiomat.microservice.usedservice" } )
public class MyServiceApplication extends SpringBootServletInitializer
{
[...]

Additionally, the Feign clients need some connection configuration details which are set in the application.yml file of your generated service that uses the service library:

feign:
client:
config:
UsedService:
connectTimeout: 5000
readTimeout: 5000
requestInterceptors:
- com.apiomat.service.base.feign.RequestHeaderRequestInterceptor

Now you are ready to call the used service library to access its classes.

Communicating with other Services

This section shows you how to call the used service via the provided API clients
The service library contains all model classes of the used service and an API client for each model. These API clients provide methods to create, update, read and delete objects of the used service classes by automatically sending REST requests to the used service's API.

Technically, the API client classes are the Feign clients that have been configured and can be injected as Spring components. The following example shows you how to call the read endpoint of a used service class:

[...]
import com.apiomat.microservice.myservice.model.MyClass;
import com.apiomat.microservice.usedservice.model.UsedServiceClass;
import com.apiomat.microservice.usedservice.service.UsedServiceClassApiClient;
 
[...]
public class MyClassApiServiceImpl extends AbstractMyClassApiServiceImpl
{
@Autowired
private UsedServiceClassApiClient usedServiceClient;
 
[...]
 
@Override
public MyClass load( final String appName, final String id )
{
/* example: the UsedClass object is loaded via id to get the foreignId for the facadeObj */
final UsedServiceClass usedClass = this.usedServiceClient.getSpecificUsedServiceClass( appName, id, false )
 
final MyClass facadeObj = new MyClass( );
facadeObj.setForeignId( usedClass.getForeignId( ) )
 
return facadeObj;
}
}

Other methods to execute CRUD operations can be found within your IDE with the help of the auto-complete feature on the injected ApiClient.

Automatic updating of used Services

As used services do not have SNAPSHOT versions, Maven does not automatically retrieve updates from the hosting service. This can be very inconvenient for development, as you would have to create a new version of the service for every change or manually retrieve the updated artifact(s).

To solve this problem, we have added the Maven goal dependency:purge-local-repository to the POM of every generated service. This goal updates used service artifacts by deleting and re-retrieving them every time the service is built (e.g. with mvn package).

By default, the goal is applied to every used service. If you only want to apply it to specific services, you can use the configuration properties <include> and <exclude> of the goal to do so (see linked documentation above for details).
For example, here is a case where only one out of three used services is being updated:

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
 
<groupId>com.apiomat.microservice</groupId>
<artifactId>batservice</artifactId>
<packaging>war</packaging>
<name>BatService</name>
<version>1.0.0</version>
<description></description>
 
<!-- ... -->
 
<!-- used services -->
<dependency>
<groupId>com.apiomat.microservice</groupId>
<artifactId>redservice-lib</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.apiomat.microservice</groupId>
<artifactId>blueservice-lib</artifactId>
<version>2.1.0</version>
</dependency>
<!-- Still in development -->
<dependency>
<groupId>com.apiomat.microservice</groupId>
<artifactId>greenservice-lib</artifactId>
<version>1.1.6</version>
</dependency>
<!-- end used services -->
 
<!-- ... -->
 
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>update-used-services</id>
<phase>process-sources</phase>
<goals>
<goal>purge-local-repository</goal>
</goals>
<configuration>
<includes>
<include>com.apiomat.microservice:greenservice-lib</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
 
<!-- ... -->
 
</project>