Skip to content

Connecting an existing microservices

In this example, we're considering the scenario where we need to integrate with an existing microservice responsible for data operations.

Architecture existing microservice

Let's outline the inputs our microservice accepts:

GitHub

microservice_swagger.png

Parameters get /myentity3900: exmicrocerviceparameters.png

swagger

The interface that will emerge will resemble the following:

Live Sample

exmicrocervicescreen.png

Steps for developing on cxbox

Developing a straightforward interaction with the existing microservice architecture.

Step1 Create DTO for integrating with microservice

Create DTO for integrating with microservices through which data will be sent to the microservice

Example
@Getter
@Setter
@NoArgsConstructor
public class MyEntityOutServiceDTO implements Serializable {

    private String id;
    private String customField;
    private String customField;
}

Step 2 Create DAO

Create DAO extends AbstractAnySourceBaseDAO implements AnySourceBaseDAO

Override methods:

  • Create : method create
Example
        public MyEntityOutServiceDTO create(BusinessComponent bc, MyEntityOutServiceDTO entity) {
            entity.setId(null);
            return restTemplate.exchange(
                    fromUriString(integrationConfig.getMyentityExistingMicroservicesDataServerUrl()).build().normalize().encode().toUriString(),
                    POST, new HttpEntity<>(entity), MyEntityOutServiceDTO.class
            ).getBody();
        }
  • Deletion: method delete
Example
    public void delete(BusinessComponent bc) {
        restTemplate.exchange(
                fromUriString(integrationConfig.getMyentityExistingMicroservicesDataServerUrl() + "/{id}").build().expand(bc.getIdAsLong()).normalize().encode()
                        .toUriString(),
                DELETE, null, Void.class
        );
    }
  • Update of existing entries: method update
Example
    public MyEntityOutServiceDTO update(BusinessComponent bc, MyEntityOutServiceDTO entity) {
        return restTemplate.exchange(
                fromUriString(integrationConfig.getMyentityExistingMicroservicesDataServerUrl()).build().normalize().encode().toUriString(),
                PUT, new HttpEntity<>(entity), MyEntityOutServiceDTO.class
        ).getBody();
    }
  • Getting all data: method getList

    Page size:

    String page = bc.getParameters().getParameter("_page");
    

    Limit:

    String limit = bc.getParameters().getParameter("_limit");
    

    Sorting for field CustomField:

        List<String> sortCustomField = getSortFieldName(queryParameters, "customField");
        Optional<String> sort = sortCustomField.isEmpty() ? Optional.empty() : Optional.of(sortCustomField.get(0));
    

    Filter for field CustomField:

     List<String> filterCustomField = getFilterFieldName(queryParameters, "customField", "contains");
     Optional<String> filter = filterCustomField.isEmpty() ? Optional.empty() : Optional.of(filterCustomField.get(0));
    

Example
    @Override
    public Page<MyEntityOutServiceDTO> getList(final BusinessComponent bc, final QueryParameters queryParameters) {

        //Page size
        String page = bc.getParameters().getParameter("_page");

        //Limit
        String limit = bc.getParameters().getParameter("_limit");

        //Filter
        List<String> filterCustomField = getFilterFieldName(queryParameters, "customField", "contains");
        Optional<String> filter = filterCustomField.isEmpty() ? Optional.empty() : Optional.of(filterCustomField.get(0));

        //Sorting
        List<String> sortCustomField = getSortFieldName(queryParameters, "customField");
        Optional<String> sort = sortCustomField.isEmpty() ? Optional.empty() : Optional.of(sortCustomField.get(0));

        String urlTemplate = UriComponentsBuilder.fromHttpUrl(integrationConfig.getMyentityExistingMicroservicesDataServerUrl())
                .queryParam("number", page)
                .queryParam("size", limit)
                .queryParamIfPresent("filterCustomField", filter)
                .queryParamIfPresent("sortCustomField", sort)
                .encode()
                .toUriString();

        ResponseEntity<RestResponsePage<MyEntityOutServiceDTO>> responseEntity = restTemplate.exchange(
                urlTemplate,
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<>() {
                },
                filter
        );


        return responseEntity.getBody();
    }


    private List<String> getSortFieldName(QueryParameters queryParameters, String fieldName) {
        return queryParameters.getParameters().entrySet().stream()
                .filter(f -> f.getKey().contains("_sort"))
                .filter(f -> f.getValue().contains(fieldName))
                .map(m -> {
                            String[] splitOperation = m.getKey().split("\\.");
                            return splitOperation[splitOperation.length - 1];
                        }
                ).toList();
    }

    private List<String> getFilterFieldName(QueryParameters queryParameters, String fieldName, String searchSpec) {
        return queryParameters.getParameters().entrySet().stream()
                .filter(f -> f.getKey().contains(fieldName + "." + searchSpec))
                .map(Map.Entry::getValue)
                .toList();
    }
  • Getting data by ID: method getByIdIgnoringFirstLevelCache
Example
    @Override
    public MyEntityOutServiceDTO getByIdIgnoringFirstLevelCache(final BusinessComponent bc) {
        return restTemplate.exchange(
                fromUriString(integrationConfig.getMyentityExistingMicroservicesDataServerUrl() + "/{id}").build()
                        .expand(bc.getIdAsLong()).normalize().encode()
                        .toUriString(),
                GET, null, MyEntityOutServiceDTO.class
        ).getBody();
    }

Step 3 Create DTO

Create DTO extends DataResponseDTO

Example
@Getter
@Setter
@NoArgsConstructor
public class MyExampleDTO extends DataResponseDTO {

    @SearchParameter(name = "customField", provider = StringValueProvider.class)
    private String customField;

    public MyExampleDTO(MyEntityOutServiceDTO entity) {
        this.id = entity.getId();
        this.customField = entity.getCustomField();
    }
}

Step4 Create MetaBuilder

Create MetaBuilder extends AnySourceFieldMetaBuilder

Example
@Service
public class MyExampleMeta extends AnySourceFieldMetaBuilder<MyExampleDTO> {

    @Override
    public void buildRowDependentMeta(RowDependentFieldsMeta<MyExampleDTO> fields, BcDescription bc,
                                      String id, String parentId) {
        fields.setEnabled(MyExampleDTO_.customField);
    }

    @Override
    public void buildIndependentMeta(FieldsMeta<MyExampleDTO> fields, BcDescription bcDescription,
                                     String parentId) {
        fields.enableFilter(MyExampleDTO_.customField);
    }

}

Step5 Create Service

Create Service extends AnySourceVersionAwareResponseService

Example
@Service
public class MyExampleService extends AnySourceVersionAwareResponseService<MyExampleDTO, MyEntityOutServiceDTO> {

    public MyExampleService() {
        super(MyExampleDTO.class, MyEntityOutServiceDTO.class, MyExampleMeta.class, MyEntityDao.class);
    }

    @Override
    protected CreateResult<MyExampleDTO> doCreateEntity(MyEntityOutServiceDTO entity, BusinessComponent bc) {

        return new CreateResult<>(entityToDto(bc, entity));
    }

    @Override
    protected ActionResultDTO<MyExampleDTO> doUpdateEntity(MyEntityOutServiceDTO entity, MyExampleDTO data, BusinessComponent bc) {
        if (data.isFieldChanged(MyExampleDTO_.customField)) {
            entity.setCustomField(data.getCustomField());
        }
        return new ActionResultDTO<>(entityToDto(bc, entity));
    }

    @Override
    public Actions<MyExampleDTO> getActions() {
        return Actions.<MyExampleDTO>builder()
                .create().text("Add").add()
                .addGroup(
                        "actions",
                        "Actions",
                        0,
                        Actions.<MyExampleDTO>builder()
                                .newAction()
                                .action("delete", "delete")
                                .add()
                                .newAction()
                                .action("save", "save")
                                .add()
                                .build()).
                build();
    }

}

Step6 Create Controller

Create Controller implements EnumBcIdentifier

Example
 @Getter
 public enum PlatformMyExampleController implements EnumBcIdentifier {

     // @formatter:on
     myExampleBc(MyExampleService.class);

     // @formatter:on

     public static final EnumBcIdentifier.Holder<PlatformMyExampleController> Holder = new Holder<>(
             PlatformMyExampleController.class);

     private final BcDescription bcDescription;

     PlatformMyExampleController(String parentName, Class<?> serviceClass, boolean refresh) {
         this.bcDescription = buildDescription(parentName, serviceClass, refresh);
     }

     PlatformMyExampleController(Class<?> serviceClass) {
         this((String) null, serviceClass, false);
     }

     @Component
     public static class BcSupplier extends AbstractEnumBcSupplier<PlatformMyExampleController> {

         public BcSupplier() {
             super(PlatformMyExampleController.Holder);
         }

     }

 }

Step7 Create widget.json

Example
{
  "name": "MyExampleList",
  "title": "List title",
  "type": "List",
  "bc": "myExampleBc",
  "fields": [
    {
      "title": "Custom Field",
      "key": "customField",
      "type": "input"
    }
  ]
}

Step8 Create view.json

Example
{
  "name": "myexamplelist",
  "title": "My example List",
  "url": "/screen/myexample/view/myexamplelist",
  "template": "DashboardView",
  "widgets": [
    {
      "widgetName": "SecondLevelMenu",
      "position": 0,
      "gridWidth": 24
    },
    {
      "widgetName": "MyExampleList",
      "position": 20,
      "gridWidth": 24
    }
  ],
  "rolesAllowed": [
    "CXBOX_USER"
  ]
}

Step9 Create screen.json

Example
{
  "name": "myexample",
  "icon": "calendar",
  "order": 3800,
  "title": "Existing microsevice",
  "navigation": {
    "menu": [
      {
        "title": "List",
        "child": [
          {
            "viewName": "myexamplelist"
          }
        ]
      },
      {
        "title": "Info",
        "child": [
          {
            "viewName": "myexampleinfo"
          }
        ]
      },
      {
        "title": "Form",
        "child": [
          {
            "viewName": "myexampleform"
          }
        ]
      }
    ]
  }
}