Development Basics
This page is an introduction to the basics of developing services with ApiOmat. It consists of a simple introduction to the development workflow and a brief overview of the relevant service assets. Links to further topics will help you dive deeper into service development.
Contents :
Workflow
In a nutshell, you can create a new service in the following steps:
-
Model your service via the ApiOmat Dashboard.
-
Download your service and retrieve project assets.
-
Develop your service and deploy the newly created sources to a repository.
-
Start your service.
-
Retrieve existing logic & code-first approach.
These steps are described in detail in the Development cycle guide.
About the service assets
As the list above guides you to a working service, there are some further technical aspects you should know about.
Package structure
A generated service will have the following architecture (example service "MyService"):
The generated base package is "com.apiomat.microservice.{serviceName}", it contains:
-
The Spring Boot application main class, named after the service with "Application" appended (e.g. MyServiceApplication.java). It contains annotations to start the Spring Boot application and enable Feign:
MyServiceApplication.java@SpringBootApplication
@EnableFeignClients
public
class
MyServiceApplication
extends
SpringBootServletInitializer
-
The main Spring-related configuration, "{serviceName}Configuration.java", that contains the configuration and initialization of all the beans required for your service logic.
-
The "config" package which contains:
-
A SwaggerDocumentationConfig.java class, which contains specific configuration to generate an OpenAPI specification. This is done for all REST endpoints annotated with the @ApiXXX swagger annotations from the springfox-swagger2 library. The OpenAPI specification is available by default at http://localhost:8090/{lowerCaseServiceName}/v2/api-docs and is accessed by the Explorer service to display the API documentation UI.
-
A "{serviceName}ConfigDefinition.java" class that contains the specific ApiOmat application configuration definition of your service. See Configuration Parameters.
-
A "{serviceName}CorsConfiguration.java" class that contains the CORS configuration for your service. See CORS configuration.
-
-
The "controller" package which contains the following for each class:
-
An API interface "I{className}Api.java" that describes API endpoints.
-
An API implementation "{className}ApiController.java" to call internal service logic.
-
-
The "model" package which contains the following for each class:
-
A POJO "{className}.java" that holds the class's attributes.
-
An enum list of reference attributes "{className}RefAttributes.java", used when querying the data model's reference endpoints.
-
An enum list of static data attributes name "{className}StaticDataAttributes.java", used when querying the data model's static data endpoints.
-
-
The "service" package which contains the following for each class :
-
A Feign client "{className}ApiClient.java" that calls the corresponding Yambas endpoints when a data model's CRUD operations are executed.
-
An API abstract service "Abstract{className}ApiService.java" that provides default implementations of service methods.
-
An API service implementation "{className}ApiServiceImpl.java" that extends the abstract implementation, where the developer can make their own implementations of service methods by overriding the default abstract provided ones.
-
The resources folder contains:
-
The "application.yml" Spring configuration file, with specific values described below in the Service Configuration - Spring related configuration section.
-
A "logback.xml" logging configuration file, see Logging and Debugging for details on this
-
You can place your own logo for the service here. For details see section Add logo for marketplace
This was only a quick overview of the classes that are generated within your Spring Boot service project. Please go to the Service architecture guide for more details on the global logic and architecture.
Versioning
ApiOmat 21.03 gives you the possibility to version your service projects independently from the "API" version (the version of your service in Yambas). That way, your service project may have a version that reflects the version of your project or business logic, while the API version stays same. This means, that you may have a project/artifact version "1.1.15", while your "API" or service version that is shown in the dashboard and attached to the is still "1.1.0"
To achieve that, there's a new property in the application.yml with the key apiomat.service.version. By default, this property has a placeholder as value. The placeholder comes from the pom.xml's property section with the key apiomat.service.version which is replaced during the maven build. Therefore, we recommend changing the property within the pom.xml, as the placeholder may be contained in the application.yml several times. Services that are generated with an ApiOmat 21.03 version automatically contain this structure.
During the artifact processing, Yambas scans at first for the property in the application.yml. If it isn't present or contains the placeholder, it will try to find the respective value in the properties section of the pom.xml. If the property doesn't exist as well, it will fall back to the version that is specified in the pom.xml. This value is used as service version in Yambas (and it's respective API endpoints).
The "used service" dependency libraries will use the service version and not the project version as well, as these libraries contain the clients and models that are bound to the API version. The same applies for the executor endpoints.
Maven dependencies
In this section, we'll list the dependencies that are defined in the pom.xml of your generated service and explain what each of them is for. Links to related documentation will be provided when relevant.
Parent
Each generated service is a child of our spring-microservice-base parent project . It provides the general dependencies and global dependency management used by every ApiOmat service. The goal of this parent project is to manage the versions used in the ApiOmat ecosystem for compliance purposes.
ApiOmat libraries
Some dependencies are custom artifacts we provide to make it easier to integrate services within the ApiOmat ecosystem:
Name |
Description |
brewer-base |
Contains the basic POJOs and interfaces used in all ApiOmat microservices, and provides the global logic applied to your microservice's service classes. This library is the service equivalent of the nativemodule-base library, which you may be familiar with if you have worked with native modules. Most of the features provided by the brewer-base library are described in the service architecture documentation . |
apiomat-service-config-starter |
Provides features to enhance the usage of ApiOmat configuration parameters in Spring Boot microservices. Features provided by this library, and the apiomat-service-config library, are described in the Configuration Parameters documentation . |
Others
Name |
Description |
logback-gelf |
Provides a log appender implementation for Graylog. The appender is defined in your logback.xml file. More information about Graylog can be found in our Graylog documentation. |
Maven plugins
The pom.xml of your generated service will have the following Maven plugins:
Name |
Description |
spring-boot-maven-plugin |
Provides several Maven goals to work with a Spring Boot application. See usage documentation. |
dockerfile-maven-plugin |
Provides features to create a docker image of your service. See the plugin's GitHub page. |
license-maven-plugin |
Generate license information about used dependencies. |
maven-war-plugin |
Plugin to package your service as a Web Application Resource (WAR). |
maven-source-plugin |
Plugin to package the sources of your application. The sources are deployed to Innkeeper so files can be merged. Also used in code-first approach to update your service's metadata. |
brewer-maven-plugin |
Our custom maven plugin to support service development. See the plugin's public documentation. |
Application main class
The entry point of your service is its application class {ServiceName}Application.java. It contains a main method and is annotated with @SpringBootApplication which is explained in more detail in the Spring Boot documentation .
An important feature to be aware of when using @SpringBootAnnotation is the @ComponentScan annotation. By default, a bean will be created and added to your service's application context for all classes annotated with @Component (or its child annotations such as @Service or @Controller) from the package where your @SpringBootAnnotation annotated class is located, and from all sub package s.
With the default behaviour of @ComponentScan , putting a class annotated with @SpringBootApplication in a top level package may result in a lot of unwanted components being added to your application context. For example, an annotation on the "com" package level will add all components from "com.*" to your application context, including dependency classes that are annotated with @Component and located in the "com.*" package of their dependency, which is definitely not wanted behavior. Try to keep your package names as specific to your application as possible.
Service Configuration
Configuration via properties is a key part of Spring. Typically, you can define your application configuration in a YAML or properties file (e.g. in your generated service, there will be an application.yml file) .
ApiOmat application configuration
It is possible to define ApiOmat application- and system-related configurations for your service, where values can be dynamically accessed and changed within your service logic at runtime. To dive deeper into this topic, please refer to Configuration Parameters .
Service discovery, health checks and load balancing
In a Cloud context, services need to communicate with each other, so they need to be able to find each other. The principle of service discovery is that a single discovery client holds information about all services in the cloud. When a service starts up, it registers itself to the discovery client, with some additional configuration if necessary. When a service wants to communicate with another service, it can retrieve the address from the discovery client.
For service discovery, we are using the Consul discovery client from HashiCorp. An additional useful feature of Consul is health checking: Each service registers itself with an endpoint for health checks, which is queried by Consul to assert the service's healthiness. Please refer to Service health checks for further information.
The picture below describes our discovery use case with the different features provided by Consul:
Another useful principle when working with services is load balancing. Imagine that you start two or more instances of the same services in order to scale your application - how can you make sure that the workload is efficiently distributed between all instances?
Load balancing will solve this for you. We use the default implementation from Spring Cloud, which is also supported by Feign.
The Spring Cloud load balancer includes several implementations to distribute the workload over multiple instances. For more information, you can have a look at the Spring Cloud documentation .
Logging and Debugging
To learn about the logging and debugging features, please refer to Service Logging and Debugging .
Data model classes
When you generate your service, a corresponding Java class will be created for each of your service's classes. This class will contain any attributes that you defined in the Dashboard. As mentioned above, these data model classes will be placed in the package com.apiomat.microservice.<servicename>.model.
Attribute Annotations
There are several attribute annotations for various attribute-specific information. They are applied automatically during service generation, and can be added manually when creating new attributes by editing the source code.
EmbeddedObject
References can be annotated
with EmbeddedObject to mark them as
embedded objects
.
For example:
@com
.apiomat.service.base.model.EmbeddedObject
private
Address address =
null
;
Mandatory
Attributes can be annotated
with Mandatory to mark them as mandatory attributes.
For example:
@com
.apiomat.service.base.model.Mandatory
private
String mandatoryStr =
null
;
Next steps
-
If you are now familiar with the different concepts of Service development in ApiOmat, but you want to practice before creating your own, please follow our Introduction tutorial .
-
You now feel ready to create your own service? Please have a look at the services we provide in the ApiOmat cloud, as they may be helpful for your future development.