NextGen APIs

Development tips

This page aims to help the customization development phase, proposing guidelines, or simple tips, which allow external customizations to be included in the Integration API’s development mode.

Let's look at the following topics:


Customizations' packages

Whether you have developed the customization of an existing API or have created a new custom API, remember to include the development in a package that is as clear as possible.

  • First of all, use the base package integration

  • Then, based on the URL of the API you are customizing, complete the package name


For example, if you have customized the GET assets/r1/assets API, the complete package will be integration.api.assets.r1.assets.get; while if you are modifying the POST, the complete package will be integration.api.assets.r1.assets.post (get or post are optional if there is a single customization, but it is important to distinguish the package if customizations for both get and post are present)

Screenshot 2025-03-12 alle 14.53.01.png
💡

Remember
If you create a new custom API or update an existing one, for example PUT domain/r1/subdomain, the package will be integration.domain.r1.subdomain (*.put is mandatory only if an other customization is needed, for example the customization of GET domain/r1/subdomain, so you will have: integration.domain.r1.subdomain.put and integration.domain.r1.subdomain.get).


Validations

Validations must be separated from any other post or patch logic, as they must be done BEFORE the custom/legacy logic. Therefore, let's imagine that an existing API must be customized, adding a custom logic that must be executed before the legacy one: customization is possible but, please, pay attention to add needed validations.

The existing API has an exposed validation interface, with the name *Validation inside the validation package (if *Validation interface does not exist, report it to the IntAPI development team): if the custom development requires a new validation, it is essential that it is added by creating a new custom class that implements the *Validation interface.


So, if you need to customize an API by adding custom validation:

  • Create the validation package inside the main package (as we have seen in Customizations' packages) and the NewCustomValidation class

Screenshot 2025-03-12 alle 16.49.33.png
  • The NewCustomValidation class MUST implement the legacy interface AssetCreationValidation and execute the custom validation logic

Screenshot 2025-03-12 alle 17.30.13.png

Do you need to add a custom field inside extension?

DTOs of the APIs exposed on Integration API project extend a DynO class which provides an extension field: extension is nothing more than a string-object map, which allows new fields to be added to the basic request; fields added, after having been validated, can actually be saved to the db.

So, how is possible to add a custom field?

Let’s see an example:

Screenshot 2025-03-03 alle 15.15.22.png
  1. Identify on SWAGGER the API involved that manage the call on private api​

Screenshot 2025-03-03 alle 15.18.46.png
  1. With the two APIs extracted in step 1, search in the classes the methods that handles the rest call, and identify the DTO involved​

Screenshot 2025-03-03 alle 15.21.01.png
  1. Customize and add in custom code the extension field

Screenshot 2025-03-03 alle 15.22.18.png


💡

Remember
👉 Validations must be carried out before any other logic

👉 If you are trying to save a new custom field to db, you MUST validate it before save


Exceptions

Are you customizing an existing API, or are you creating a completely new custom one in Integration API project, and need to handle an exception?
If answer is yes, Integration API provides the method ofBadRequest(APIError apiError, Serializable... errorParams) inside the APIException class, let's see it in detail how to use it:

Inside the Integration API project you will find many *Error enum classes that implement the APIError interface, which exposes the getErrorCode() and getErrorDescription() methods; errors recorded within the enum classes have an errorCode and an errorDescription which must be recorded (therefore maintaining a standard structure) also on the Error Codes Integration API page.

  1. Create a new package exceptions inside the customization one

Screenshot 2025-03-12 alle 17.33.35.png
  1. Create a new enum class that implements the ApiError interface

    1. using Error Codes Integration API as example page, create a new custom error, maintaining the domain number indicated on the previous page.

For example, if the customization concerns the asset domain and the project is called

Xxx Yyy the new error will be XY004_001, where:

XY = project name’s initials

004 = uniquely identifies the asset domain

_001 = sequential number which indicates, in this case, that it is the first error recorded

Screenshot 2025-03-12 alle 17.37.55.png
  1. Use the new custom exception created inside the ofBadRequest(APIError apiError, Serializable... errorParams), as we have seen in the Validations code example:

Screenshot 2025-03-12 alle 17.30.13.png


💡

Remember
If it's necessary to throw an exception in custom implementation, please use method ofBadRequest(APIError apiError, Serializable... errorParams) available in IntegrationApi project: so that is possible to maintain a centralized and consistent implementation with the project you are customizing.


How to call Private API

To understand how communication with PrivateAPIs occurs within IntegrationAPI project and how to make customizations, see https://overit-spa.atlassian.net/wiki/x/TgFzPxg page.

Useful tips

Annotations

You can find all the annotation below used in the customizations' examples

Add step before or after default elaboration

Remove default step

Make a field optional

  1. @RequiredArgsConstructor

Is a Lombok annotation that generates constructors for all final and non-null fields; using Lombok simplifies Constructor Injection.

Can i use it?

Yes, if you have Lombok dependency in pom.xml file.

How can I replace it, if i don’t have Lombok dependency?

a. Field Injection with @Autowired

Screenshot 2025-03-04 alle 11.58.14.png

UserRepository dependency is injected into the UserService class using @Autowired on the field.

b. Constructor Injection

Screenshot 2025-03-04 alle 12.01.27.png

UserRepository dependency is injected via the constructor, and the userRepository field is marked as final, indicating that it cannot be changed after the object is constructed.

  1. @Component

Is an annotation that allows Spring to detect our custom beans automatically.

Without having to write any explicit code, Spring will:

a. Scan our application for classes annotated with @Component

b. Instantiate them and inject any specified dependencies into them

c. Inject them wherever needed

  1. @Controller, @Service and @Repository

These specialized annotations all act the same because they are all composed annotations with @Component as a meta-annotation for each of them. They are like @Component aliases with specialized uses and meaning outside Spring auto-detection or dependency injection.

  1. @Primary

Use this annotation to give higher preference to a bean when there are multiple beans of the same type: in other words, use it to be sure that the custom logic will be executed before the default one.

Reactive

  1. Mono.flatMap()

Used to ‘capture and use' the body of the previous Mono and it activate itself only if the previous Mono actually terminate

  1. Mono.just()

Creates a Mono of the object passed in input

  1. Mono.thenReturn()

Used to ‘create and return’ a new Mono with the object passed in input

  1. Mono.defer()

Used to conditionally subscribe to a publisher: in simple words, when you want to be sure that execution order is maintained.

As we have seen in Add step before or after default elaboration

Screenshot 2025-03-04 alle 12.37.31.png

It is crucial that what is requested to be executed within the .then() is actually executed AFTER the execution of the doSomethingBefore() method is completed.