Starting point in general extending
See Conformance
All implementations called after micronaut request is accepted and before any work on resource is started. May be used for authentication, logging, etc.
interface KefhirRequestFilter {
Integer getOrder();
void handleRequest(KefhirRequest request);
}
Implementations are called in order according to getOrder
method.
You can do any changes to request
object, containg HTTP request data.
Throwing exception is also allowed.
Example
All implementations called before response is flushed, but after all transactions are commited and work is done. Useful for logging or contexts cleanup
interface KefhirResponseFilter {
Integer getOrder();
handleResponse(KefhirResponse response, KefhirRequest request);
void handleException(Throwable ex, KefhirRequest request);
}
Implementations are called in order according to getOrder
method.
You can do any changes to response
object if you would like to modify response.
Example
This interface is almost the same as KefhirRequestFilter
, however it has a major difference.
In case of a /transaction
request, a single http method is called, which means that KefhirRequestFilter
will be called once. But in some cases (like SMART Authorization you need to run filters for every resource and before the Interceptors
. In this case KefhirRequestExecutionInterceptor
come in handy, being called for every resource interaction (single in case of resource interaction, and for every resource in a transaction)
interface KefhirRequestExecutionInterceptor {
void beforeExecute(request);
}
Main REST logic class. Default implementation is provided and should not be required to change. However, in some cases you need to change some specific Resource behaviour on the REST level. In this case you can provide your own implementation.
For example, Binary resources should behave differently.
interface FhirResourceServer {
String getTargetType();
KefhirResponse read(KefhirRequest req);
KefhirResponse vread(KefhirRequest req);
KefhirResponse create(KefhirRequest req);
KefhirResponse update(KefhirRequest req);
KefhirResponse conditionalUpdate(KefhirRequest req);
KefhirResponse delete(KefhirRequest req);
KefhirResponse history(KefhirRequest req);
KefhirResponse historyType(KefhirRequest req);
KefhirResponse search(KefhirRequest req);
KefhirResponse searchCompartment(KefhirRequest req);
KefhirResponse instanceOperation(KefhirRequest req);
KefhirResponse typeOperation(KefhirRequest req);
}
If you need only partial customization, you can extend default implementation DefaultFhirResourceServer or BaseFhirResourceServer.
Binary resource example
Main interface for building custom logic. At this point request is accepted and service started working on this resource.
Consist of several phases, all called in corresponding phase groups.
INPUT_VALIDATION
- structural and profile validation. Content is given as-is, not modified. Needed to make sure content is structurally correct before any other work is done. See ValidationNORMALIZATION
- for some resource modification, metadata, reference id replacements etc.BUSINESS_VALIDATION
- Given resource is now correct and prepared with all data, business validations can be performed. See ValidationTRANSACTION
- Any other actions you need to within database transaction.abstract class ResourceBeforeSaveInterceptor {
String phase;
void handle(id, content, interaction);
}
Example:
public class ProvenanceSavePlugin extends ResourceBeforeSaveInterceptor {
@Inject
private ResourceFormatService formatService;
public ProvenanceSavePlugin() {
super(ResourceBeforeSaveInterceptor.NORMALIZATION);
}
@Override
public void handle(ResourceId id, ResourceContent content, String interaction) {
if (id.getResourceType().equals(ResourceType.Provenance.name())) {
Provenance provenance = formatService.parse(content.getValue());
provenance.setRecorded(new Date());
content.setValue(formatService.compose(provenance, "json").getValue());
}
}
}
Actions after resource is stored.
Consist of several phases, all called in corresponding phase groups.
TRANSACTION
- Before transaction is commited. Throwing exception from here will result in transaction rollback.FINALIZATION
- After transactions are commited.abstract class ResourceAfterSaveInterceptor {
String phase;
void handle(version);
Called everytime after resource is deleted.
interface ResourceAfterDeleteInterceptor {
void delete(id);
}
In some cases you would like to validate or modify search request.
abstract class ResourceBeforeSearchInterceptor {
void handle(criteria);
}
See example in Validation
Main interface for implementing database storage. Has default postgresql implementation. See Storage
Main interface for implementing search. See Search
Operations seems to be a big topic in FHIR, all operations need custom logic implementations. Attaching a new operations, however, is as easy as providing opeartion name, resource type for operation, and logic itself:
Patient/$everything
example
interface InstanceOperationDefinition {
String getResourceType();
String getOperationName();
ResourceContent run(id, parameters);
}
interface TypeOperationDefinition {
String getResourceType();
String getOperationName();
ResourceContent run(parameters);
}
Same as resources, operations also need to be handled in some cases (Parameters is also a Resource and need to be validated, for example). Given interface implementation are called same way as resource every time an operation is called.
interface OperationInterceptor {
void handle(level, operation, parameters);
}
ResourceRepresentation
is an interface for supporting different formats, such as JSON and XML (both are provided by default).
By implementing this, you can add additional formats.
Given default search implementation is used, an interface PgResourceFilter
is also provided. This interface can be used to add some conditions to the resulting generated SQL. May be useful for authorization.
public class CustomAccessFilter implements PgResourceFilter {
@Override
public SqlBuilder filter(SqlBuilder builder, String alias) {
String currentUser = "x";
return builder.append(" and exists (select 1 from my_custom_auth mca where mca.resource_id = " + alias + ".id and mca.user = ?", currentUser);
}
}
@Gen provide description.
@Gen provide description.