Develop a Basic Preprocessor
You will need to produce a Docker container that implements a specific HTTP REST interface. See the OpenAPI specification for complete details.
There are several alternatives to accomplish this:
- Fork an existing template - Start with a project similar to your needs (language, frameworks, process, etc.)
- Use a code generator - Create a new project with almost everything ready to run the server
- Build from scratch - Create your project from the ground up, as long as it follows the OpenAPI specification
Select the development path that best fits your needs and expertise.
Forking a Template
JavaScript
📦 Repository: preprocessing-service-example
This is a simple preprocessor written in TypeScript/JavaScript.
You can write the business logic in src/controllers/preprocessing.ts. The template is ready with Dockerfile and even Kubernetes YAML definitions.
Key Features:
- Pre-configured TypeScript environment
- Docker and Kubernetes deployment files included
- Ready-to-use project structure
Getting Started:
- Fork the repository
- Add your dependencies
- Write your code
Python
📦 Repository: preprocessing-service-example-python
This is another simple preprocessor written in Python.
It's ready to fork and develop your own preprocessor from it. Start at preprocessor\controllers\preprocess_controller.py — the function is _apply_preprocess.
Key Features:
- Components to access common ePI elements such as the composition
- Built-in support for managing
HtmlElementLinkExtension - Tools to extract and manipulate HTML content
- Embedded ePI examples for testing
Getting Started:
- Fork the repository
- Add your dependencies
- Write your code
- Test it with the embedded ePI examples
Generic Approach using OpenAPI Generator
You can opt to use an API server generator, for example OpenAPI Generator, which will be explained in detail.
📋 Preprocessor OpenAPI Spec:
https://raw.githubusercontent.com/Gravitate-Health/preprocessing-service-example/refs/heads/main/openapi.yaml
You can create servers with stubs in any of the supported languages.
You may need to create a Dockerfile for the Preprocessor service. Remember to expose the port where the API is published.
Using the official Docker image avoids installing Java or OpenAPI Generator locally. You will need Docker installed.
1. Generate a server stub
Use the dockerized generator:
docker run --rm \
-v ${PWD}:/local --user $(id -u):$(id -g) \
openapitools/openapi-generator-cli generate \
-i https://raw.githubusercontent.com/Gravitate-Health/preprocessing-service-example/refs/heads/main/openapi.yaml \
-g <language> \
-o /local/out/<language-server>
Where <language> can be:
| Language | Generator |
|---|---|
| Java Spring | spring |
| Python Flask | python-flask |
| Node/JavaScript Express | nodejs-express-server |
| Go Gin | go-gin-server |
| Rust Hyper/Tower | rust-server |
Checkout the full list of supported languages (+ frameworks) in openapi-generator's list of SERVER Generators
2. Implement business logic
After generation:
- Each endpoint will have a handler stub.
- Implement your logic inside those functions.
- Avoid modifying generated models or interfaces (regenerate at any time).
3. Build & run Docker image
Ensure the docker image can be built, if there isn't any Dockerfile create one for your project.
docker build -t my-service .
docker run -p 8080:8080 my-service
Concrete Examples by Popular Languages
Python – Flask Server
Generate
docker run --rm \
-v ${PWD}:/local --user $(id -u):$(id -g) \
openapitools/openapi-generator-cli generate \
-i https://raw.githubusercontent.com/Gravitate-Health/preprocessing-service-example/refs/heads/main/openapi.yaml \
-g python-flask \
-o /local/generated/python-flask \
--additional-properties=packageName=preprocessor
Project Structure
generated/python-flask/
├── __main__.py # Flask root
├── openapi_server
| ├── controllers/ # handlers
| ├── models/
| ├── api/
| ├── ...
├── Dockerfile
├── requirements.txt
├── ...
Implement your code in:
openapi_server/controllers/preprocess_controller.py
You may use FHIR Python Helper modules like fhir.resources (Pydantic-based models).
Dockerfile (Flask)
Generator already provides a working Dockerfile.
If there is an issue, try changing FROM python:3-alpine in the dockerfile to FROM python:3.11-alpine.
Java – Spring Boot Server
Generate
docker run --rm \
-v ${PWD}:/local --user $(id -u):$(id -g)\
openapitools/openapi-generator-cli generate \
-i https://raw.githubusercontent.com/Gravitate-Health/preprocessing-service-example/refs/heads/main/openapi.yaml \
-g spring \
--additional-properties=java8=true \
-o /local/generated/spring
The generated project already includes Maven or Gradle support.
Project Structure (Spring)
generated/spring/
├── pom.xml
├── src/main/java/org/openapitools/api/... # handlers
├── src/main/java/org/openapitools/model/... # models
├── ...
Write your logic inside classes under:
src/main/java/org/openapitools/api/PreprocessApiController.java
You may use FHIR Helper packages like HAPI FHIR, hapi-fhir-base provides parsing and manipulation.
Example Dockerfile (Java Spring)
generated/spring/Dockerfile
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /workspace
# copy pom / mvnw first to leverage Docker layer cache if sources change often
COPY pom.xml ./
COPY src ./src
# build the project (skip tests for faster builds by default)
RUN mvn -B -DskipTests package
# normalize produced jar name for the next stage
RUN cp target/*.jar app.jar
FROM eclipse-temurin:17-jre AS runtime
WORKDIR /app
# copy the assembled jar from the build stage
COPY --from=build /workspace/app.jar ./app.jar
# default Spring Boot port
EXPOSE 8080
# allow passing JVM options with JAVA_OPTS
ENV JAVA_OPTS=""
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]