Controllers

The CoreWallet exposes a RESTful API, both for public and Admin APIs. Typically, every public API call is available as an Admin API call as well, but then requiring the proper Admin authentication.

Typically used HTTP methods are HEAD, GET and POST. The input parameters are typically sent via either the URI, query-string or as form-urlencoded post-body.

The response is typically unformatted JSON.

The following diagram shows typical elements for an API controller.

It contains the following elements:

  • ApiController contains the public API methods. The controller has a @RequestMapping annotation that defines the URI of the requests that it will handle, and each controller-method has a @RequestMapping annotation that defines the URI relative to the controller-URI. All controller-URIs are defined as constants in the interface WalletApi_1_0_0 to ensure consistency.
  • ApiAdminController contains the Admin API methods
  • ServiceInterface is the internal-service that the API call delegates to (via HttpInvoker to the internal-webapp)
  • Entity is the internal representation of the entity that the API call operates on. It is not the database entity, but the internal-service representation, e.g. containing the publicIds.
  • EntityInfo is the external API representation of the entity, which may expose a subset of fields from the Entity. The purpose is to remain consistent even when the Entity structure changes.
  • The EntityConverter converts an Entity (or a list of Entities) to an EntityInfo.

What happens during an API call

The following happens when an API call is made, meaning an HTTP request arrives at the application server and is delegated to the external-webapp.

  1. Spring finds the appropriate ApiController to delegate the call to, based on the controllers registered in the context, and the @RequestMapping annotations on the controller classes and methods
  2. The RequestIdHandlerInterceptor generates a RequestId and assigns it to the RequestIdHolder, the MDC and the HttpRequest as attribute. It also assigns the IP-address to the MDC.
  3. The MonitoringHandlerInterceptor generates a call-statistics 'enter'-event and starts the time-measurement for the call
  4. The ApiController method is called
    1. The ApiController method should create an ApiRequestInfo based on the request data using BaseController.createApiRequestInfo(). It creates the ApiRequestInfo and prepares the request-data in a TokenValidationData object. This means the request is not authenticated yet, as this will take place in the internal-webapp. It is ensured that a tokenId/token or bearerToken are present, unless the method createApiRequestInfoNoTokenValidation() is used for anonymous public API calls. The Admin API always requires a tokenId/token.
    2. The ApiController calls the internal-service-method.
      1. The MonitoringHttpInvokerProxyFactoryBean generates a call-statistics 'enter'-event and starts the time-measurement for the HttpInvoker-call
      2. The ApacheHttpInvokerRequestExecutor executes the HTTP-request, including HTTP-headers for service-method name, original IP-address and RequestId
      3. (HTTP request between external-webapp and internal-webapp)
      4. Spring finds the appropriate HttpInvokerExporter-bean to delegate the HTTP request to
      5. The CustomHttpInvokerServiceExporter extracts the RequestId HTTP header, and assigns it to the RequestIdHolder, and extracts the original IP-address and assigns it to the MDC
      6. The AuthenticatingRemoteInvocationExecutor ensures that the service-interface implements ExportedService, to prevent accidental exposure of interfaces. It replaces the ApiRequestInfo with a new ApiRequestInfo after validating the token using the TokenValidator service. It configures the SpringSecurity context with an appropriate authentication object, including all roles returned by the TokenValidator.
      7. The following annotations are processed for entry, if applicable
        1. @Cacheable for caching responses for specific input
        2. @Monitor for call-statistics
        3. @Retry for retry-policies when exceptions occur
        4. @Log for entry/exit logging
        5. @Transaction for Spring-managed transactions
        6. @TimestampSynchronized for consistent timestamps
      8. The service-implementation is called
      9. The annotations are processed in reverse order for exit, if applicable
      10. The AuthenticatingRemoteInvocationExecutor clears the security context
      11. The CustomHttpInvokerServiceExporter clears the RequestIdHolder and MDC
      12. (HTTP response back to external-webapp)
      13. The ApacheHttpInvokerRequestExecutor translates the response
      14. The MonitoringHttpInvokerProxyFactoryBean generates a call-statistics 'exit'-event and stops the time-measurement for the HttpInvoker-call
    3. The ApiController composes the result-model using the BaseController.createResponse() method and returns it
  5. The ErrorLoggingHandlerInterceptor logs the exception if applicable, and generates a JSON-event for it, with details such as controller-method, tokenId, requestId and exception details.
  6. The MonitoringHandlerInterceptor generates a call-statistics 'exit'-event and stops the time-measurement for the call
  7. The RequestIdHandlerInterceptor clears the RequestIdHolder, and removes the RequestId and IP-address from the MDC 
  8. Spring composes the HTTP-response based on the requested content-type and the controller-method-result.
    1. JSON responses are generated by default using the JsonViewResolver class
    2. JSPs are resolved using CustomInternalResourceViewResolver, if applicable, which ensures that a requested resource exists, otherwise it is ignored (to prevent HTTP 404 for non-existing JSPs, which should be rendered as JSON-responses instead)

Keep in mind that the HttpInvoker part of the service invocation is not applicable when a single deployment model is used, where the service implementation is wired directly into the controller, including any interceptors for the service method annotations.