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 interfaceWalletApi_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.
- 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 - The
RequestIdHandlerInterceptor
generates a RequestId and assigns it to theRequestIdHolder
, theMDC
and the HttpRequest as attribute. It also assigns the IP-address to theMDC
. - The
MonitoringHandlerInterceptor
generates a call-statistics 'enter'-event and starts the time-measurement for the call - The ApiController method is called
- 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 aTokenValidationData
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 methodcreateApiRequestInfoNoTokenValidation()
is used for anonymous public API calls. The Admin API always requires a tokenId/token. - The ApiController calls the internal-service-method.
- The
MonitoringHttpInvokerProxyFactoryBean
generates a call-statistics 'enter'-event and starts the time-measurement for the HttpInvoker-call - The
ApacheHttpInvokerRequestExecutor
executes the HTTP-request, including HTTP-headers for service-method name, original IP-address and RequestId - (HTTP request between external-webapp and internal-webapp)
- Spring finds the appropriate HttpInvokerExporter-bean to delegate the HTTP request to
- 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 - The
AuthenticatingRemoteInvocationExecutor
ensures that the service-interface implementsExportedService
, to prevent accidental exposure of interfaces. It replaces theApiRequestInfo
with a newApiRequestInfo
after validating the token using theTokenValidator
service. It configures the SpringSecurity context with an appropriate authentication object, including all roles returned by the TokenValidator. - The following annotations are processed for entry, if applicable
@Cacheable
for caching responses for specific input@Monitor
for call-statistics@Retry
for retry-policies when exceptions occur@Log
for entry/exit logging@Transaction
for Spring-managed transactions@TimestampSynchronized
for consistent timestamps
- The service-implementation is called
- The annotations are processed in reverse order for exit, if applicable
- The
AuthenticatingRemoteInvocationExecutor
clears the security context - The
CustomHttpInvokerServiceExporter
clears the RequestIdHolder and MDC - (HTTP response back to external-webapp)
- The
ApacheHttpInvokerRequestExecutor
translates the response - The
MonitoringHttpInvokerProxyFactoryBean
generates a call-statistics 'exit'-event and stops the time-measurement for the HttpInvoker-call
- The
- The ApiController composes the result-model using the
BaseController.createResponse()
method and returns it
- The ApiController method should create an ApiRequestInfo based on the request data using
- 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. - The
MonitoringHandlerInterceptor
generates a call-statistics 'exit'-event and stops the time-measurement for the call - The
RequestIdHandlerInterceptor
clears theRequestIdHolder
, and removes the RequestId and IP-address from theMDC
- Spring composes the HTTP-response based on the requested content-type and the controller-method-result.
- JSON responses are generated by default using the
JsonViewResolver
class - 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)
- JSON responses are generated by default using the
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.