Java code duplication

Currently we have about 10 core services and based on sonar all of them have some code duplication. To avoid this we could move duplication parts to separate libraries. Currently we could divide them by purpose of usage. Each library has been shortly described in this document.

Repository structure

The first thing is to set repository structure for new created libraries. Independents on that each library will use Gradle as a build tool. The first version will be 1.0.0 for all libraries (exclude service communication libraries). 

  • single repository 
    • easier to maintain
    • single CI job
    • harder to release a new version of single library - we would like to avoid releasing library that does not have changes
  • each library has it own repository
    • harder to maintain
    • each repository has its own CI jobs
    • easier to release a new version

The openlmis-base library

The library will contain all necessary classes to run a new service. A developer should be able to run the service when this library is present in dependencies and there is no additional code in the service repository. To achieve that we probably need to add some configuration classes to set properties like service name but still without configuration library should use some default values (currently we use template as a default name for new services). The following classes should be in this library:

  • i18n
    • Message
    • BaseMessageException
    • ExposedMessageSourceImpl
    • ValidationMessageException
  • web
    • RequestHelper
    • WebErrorHandling
    • AbstractErrorHandling
    • GlobalErrorhandling (it would be good to have single error handler for all common exceptions)
    • BaseController
    • VersionController (the endpoint path should be taken from the configuration class)
  • config
    • ResourceServerSecurityConfiguration
    • CustomWebMvcConfigurerAdapter
    • UserNameProvider (not sure if this class is needed)
  • base package (org.openlmis)
    • Application (beans from this class should be moved to separate configuration classes in related libraries, for example flyway bean should be moved to openlmis-sql library)
    • Resource2Db

The openlmis-csv library

If service supports CSV files like for upload or download purpose, the service should use this library. For the beginning it will contains CSV reader and writer. There should be at least two CSV parsers: one to manage rows sequentially, second to use chunks (similar to spring batch). The following classes should be in this library:

  • ModelClass
  • ModelField
  • CsvBeanReader
  • CsvCellProcessors
  • CsvParser (divide into two: sequential and parallel)
  • ItemProcessor (interface)
  • ItemWriter (interface)

The openlmis-sql library

Classes used to help a service handle database layer. It will also have support for JaVers. The following classes should be in this library:

  • PageImplRepresentation
  • Pagination
  • AuditLogInitializer
  • JaVersDateProvider

The openlmis-base-client library

The library will help a developer to create service client library (more in section below). The following classes should be in this library:

  • all *ParameterizedTypeReference classes
  • RequestParameters
  • DataRetrievalException
  • BaseCommunicationService
  • AuthService (only to retrieve token)
  • AuthenticationHelper

Client libraries

Each core service will create a client library with DTOs, communication services and configuration class (services should be created only if required and there is no custom implementations). This should be done in the service repository and client library should have the same version as service. For instance: Requisition 5.0.0 will create openlmis-requisition-client 5.0.0 library. Other services should use the library to communication. Also we could simplefly service names: org.openlmis.fulfillment.service.referencedata.FacilityReferenceDataService could be changed to org.openlmis.referencedata.client.FacilityClient.

related tickets:
OLMIS-1733 - Getting issue details... STATUS

OpenLMIS Service Util

This is a good opportunity to remove/close the current openlmis-service-util. Classes from this repository should be moved to new libraries:

  • classes in converter package → openlmis-sql,
  • classes in money package → openlmis-base,
  • ErrorResponse should be removed because currently we have Message class in all services,
  • NotificationRequest → openlmis-notification-communication
  • PasswordChangeRequest → openlmis-auth-communication
  • PasswordResetRequest → openlmis-auth-communication
  • Version → openlmis-base
  • View → openlmis-base (do we actually need this class?)

Future changes

In the future it would be good to create a gradle plugin to create a new OpenLMIS service with all needed files like docker compose, consul files, etc. It would be great to have ability to create a new service by those two steps.

  1. Create a build.gradle file with the following statement:

    build.gradle
    apply plugin 'openlmis'
  2. Execute OpenLMIS gradle plugin:

    bash
    gradle openlmis:init
  3. After this step all necessary files should be retrieved/created and a developer should be able to run a new service:

    bash
    docker-compose run --service-ports {service_name}
    gradle clean bootRun

OpenLMIS: the global initiative for powerful LMIS software