How to Build a Document Automation Service from Three Languages: A Practical Breakdown
A practical look at a polyglot service architecture for Excel validation, XML generation, and Docker-based deployment.
Modern server-side systems are increasingly designed not as a single application but as a set of small, independent services written in different languages and tied together by a common protocol. Using a service that automates diploma supplements as an example, this breakdown looks at the engineering decisions behind such a “polyglot” architecture and why it is justified for an applied task.
The problem
The underlying work is routine: take an Excel grade sheet with subjects, hours, and grades, check it for errors, and export it into a strict XML format. Manual processing is slow and error-prone, so the process is worth automating.
The task splits into two scenarios:
- assembling a pivot table with highlighted problematic cells;
- generating an XML document from a given template.
Architecture: why three modules instead of one
The system is deliberately split into three independent services rather than a single monolithic application.
- java-api — the entry gateway. It accepts HTTP requests and routes tasks. It is built on the lightweight Takes framework: a minimalist layer is sufficient for a gateway, whereas full-weight Spring would be excessive.
- python-engine — the table-processing module, built on FastAPI together with pandas and openpyxl. It reads the Excel file, detects inconsistencies, and marks problematic cells with color.
- python-xml-engine — an XML generator that works from a template, also on FastAPI.
This separation has a practical payoff: each module can be developed and restarted independently. Python is used where it is strong at data processing, Java in the role of a reliable API layer. Each language is applied to its intended purpose.
Example: highlighting errors in Excel
The most illustrative fragment is the cell-validation logic. Using openpyxl, the service walks through the file and fills suspicious values with color: empty cells and the ! and ? symbols.
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
fill = PatternFill(start_color="FFC7CE",
end_color="FFC7CE",
fill_type="solid")
for row in ws.iter_rows():
for cell in row:
if cell.value in (None, "", "!", "?"):
cell.fill = fill # highlighted the problem
The technique is simple, but it is exactly what saves hours of manual checking: the reviewer only needs to inspect the highlighted cells rather than the whole file.
Docker: launch with a single command
Three services mean three potential points of failure when setting up the environment. Docker Compose removes that complexity: all modules are described in docker-compose.yml, run on a shared network, and start with a single command.
docker-compose up --build
This eliminates the “works only on my machine” situation and the manual installation of Java and Python. Here, a reproducible environment is not a convenience but a requirement for an applied service.
Takeaways
- A large task is best split into independent services.
- Languages can be combined, choosing the right tool for each sub-task.
- The pandas and openpyxl pairing is effective for working with Excel.
- Docker Compose turns a heterogeneous stack into one reproducible project.
Availability
The project is open source under the MIT license and available without registration or restrictions: you can run the live demo, deploy the service locally, or study the source code.
- Demo: пгту-ртф.рф
- Source code: github.com/nikita-konkin/diploma_supplement_service
Tags
More project updates
An Open Replacement for CyberDiploma: An Architecture Shaped by Windows 7
A draft architecture for an open system that prepares, checks and prints diplomas. Why the platform requirements ruled out nearly every technology, how one build runs both on an...
The Diploma Service: 27 Defects From a Review, and Why the Worst Were Silent
A code review and a reconciliation against real input data produced 27 defects. The worst class was silent: a student dropped out of the XML with no error. How silent gaps becam...