Uploaded image for project: 'Apache Fineract'
  1. Apache Fineract
  2. FINERACT-2021

Type-safe REST API layer

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Open
    • Major
    • Resolution: Unresolved
    • None
    • 1.10.0
    • None

    Description

      Background and Motivation

      Fineract initial planning and code architecture predates some of the frameworks and current best practices. That and the fact that we have some not so easy to parse data structures led to the decision to use Google's GSON library and parse incoming API requests manually and to capture all request bodies in String variables. The downside of doing this decision are:

      • by capturing all incoming request bodies in Strings we lose all type information
      • we need to manually reintroduce types by creating dummy classes that are solely there to create an OpenAPI descriptor
      • it is easy to introduce bugs while refactoring, because non of the refactoring tools in any of the IDEs can help
      • we have to maintain a lot of "magic" Strings to poke into the JSON data structures (again, no type-safety)
      • we have a lot of boilerplate code for manual JSON parsing that we have to maintain (rough estimate 10-15% of the entire code base)
      • because the JSON parsing is so tedious and time consuming a couple of developers decided to skip the layered architecture rules; and with that they tied the REST API layer to the business logic/service layer (not a good practice); the business logic should not contain any information about how and in which format we exchange API requests

      Target Personas

      • developers
      • integrators
      • BaaS

      Goals

      • migrate current JAX-RS REST resource classes to Spring's Web MVC
      • use Spring Boot's first class integration of Jackson for JSON parsing
      • get rid of entire manual JSON code base (including the use of GSON)
      • handle difficult/non-standard data structures with Jackson Serializer and Deserializer implementations
      • all incoming and outgoing API requests need to be mapped to proper Java classes in packages "data"
      • all business logic services need to have "data" classes as input and output parameters
      • remove all JSON related input and output parameters from business logic services
      • remove all dummy/helper classes related to OpenAPI descriptor generation
      • clear separation between data and domain/entity classes
      • domain classes should be only used internal to respective business logic service and not leak outside of its package/feature/module
      • use MapStruct (https://mapstruct.org/) to generate as much mapping code as possible without manual intervention (mappers should only be used internal to business logic services)
      • use validation annotations on data classes to delegate as much as possible to Java validation framework instead of doing our own boilerplate "if-then-else" code
      • keep REST API backwards compatibility with version 1.9.0

      Non-Goals

      • change/improve REST API structure
      • move all current RESTeasy based integration tests to Spring MVC's JUnit test support (separate project/pull request/ticket)

      Proposed API Changes

      JAX-RS REST resource classes

      Move all JAX-RS REST resource classes to Spring Web MVC controllers (with all annotations etc.). It might be possible to use OpenRewrite to automate part of this work (there is a module for refactoring JAX-RS to Spring Web MVC. This allows us to take advantage of first class support for JUnit like testing in Spring (replacing our unmaintainable integration tests... which lack themselves type safety).

      REST controller input and output parameters

      Make sure all endpoint receive and generate type safe data. All input/output parameter related data structures should reside in "data" packages.

      Business logic services

      All input and output parameters in the business logic layer need to be mapped to "data" classes. Internal domain/entity classes should not leak outside of the business logic classes.

      Data/DTO to domain/entity mapping

      All mapping between data and domain classes should be mapped with MapStruct. The developers only have to provide annotations (if necessary) and automate the mapping code generation with MapStruct.

      Risks

      Migrating from JAX-RS to Spring Web MVC and re-introduce type-safety will be an ongoing effort over a couple of weeks/months. During that time we'll have 2 different frameworks handling the API requests. There might be subtle changes in the behavior.

      ETA

      We have roughly 50 feature packages/modules with REST API resource classes. Some are larger than others; first migrations could take a bit longer before we establish a routine. A rough calculation would be 3-4 days per feature/module which results in 150-200 development days or about 6 months to finish this task.

      Diagrams

      TBD

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              aleks Aleksandar Vidakovic
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated: