-
Notifications
You must be signed in to change notification settings - Fork 18
Migrating from phase4 peppol standalone
This guide is for users who have a working phase4-peppol-standalone deployment and want to migrate to phoss-ap. It covers the key differences and the steps required.
phase4-peppol-standalone is a lightweight template for getting started with Peppol AS4. It stores nothing in a database, has no retry logic, no forwarding, and requires you to implement inbound message handling yourself. phoss-ap is a production-ready AP that provides all of this out of the box:
| Capability | phase4-peppol-standalone | phoss-ap |
|---|---|---|
| Inbound message handling | Custom SPI with TODOs | Complete: DB storage, forwarding, duplicate detection |
| Outbound sending | Fire-and-forget | Persistent queue with retry and circuit breaker |
| Data persistence | File-based only | PostgreSQL or MySQL with Flyway migrations |
| Document forwarding | Not included | HTTP POST, S3, SFTP |
| Duplicate detection | Not included | AS4 Message ID + SBDH Instance ID |
| MLS (Message Level Status) | Not included | Full support |
| Document verification | Not included | Pluggable SPI (Phorm integration out of the box) |
| Peppol Reporting | Default in-memory backend | Database-backed |
| Error monitoring | Logging only | Logging + Sentry integration |
| AS4 message dumping | Direction-based only | Direction-based or grouped by exchange |
See Architecture Overview for the full picture of phoss-ap's components.
Before starting the migration you need:
- Java 21 (same as phase4-peppol-standalone)
- PostgreSQL 14+ or MySQL 8.0+ (new requirement)
- Maven 3.9+ (same)
See Running phoss AP for detailed build and deployment instructions.
phoss-ap requires PostgreSQL or MySQL. Flyway creates the schema automatically on first startup. Make sure to use more secure usernames and passwords as provided in below example.
psql -U postgres -c "CREATE DATABASE \"phoss-ap\";"
psql -U postgres -c "CREATE USER peppol WITH PASSWORD 'peppol';"
psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE \"phoss-ap\" TO peppol;"See Database Design Notes for schema details.
Most configuration properties carry over directly. The table below shows the mapping:
| phase4-peppol-standalone | phoss-ap | Notes |
|---|---|---|
peppol.stage |
peppol.stage |
Unchanged |
peppol.seatid |
peppol.owner.seatid |
Renamed |
peppol.owner.countrycode |
peppol.owner.countrycode |
Unchanged |
phase4.endpoint.address |
phase4.endpoint.address |
Unchanged |
phase4.api.requiredtoken |
phase4.api.requiredtoken |
Unchanged |
phase4.dump.path |
phase4.dump.path |
Unchanged. Additionally phase4.dump.mode can be set to grouped
|
smp.url |
peppol.smp.url |
Renamed |
peppol.reporting.senderid |
(derived from Seat ID) | No longer a separate property; the SP ID is derived from peppol.owner.seatid
|
peppol.reporting.scheduled |
peppol.reporting.schedule.enabled |
Renamed |
peppol.reporting.schedule.* |
peppol.reporting.schedule.* |
Unchanged |
global.debug |
(removed) | Debug mode is always off |
global.production |
(removed) | Production mode is always on |
global.datapath |
global.datapath |
Unchanged |
http.proxy.* |
http.proxy.* |
Unchanged |
Keystore/truststore (org.apache.wss4j.crypto.merlin.*) |
Same | Unchanged |
SMP client truststore (smpclient.truststore.*) |
Same | Unchanged |
New properties that must be configured (see Configuration Properties for the full list):
# Database (required)
phossap.jdbc.database-type=postgresql
phossap.jdbc.driver=org.postgresql.Driver
phossap.jdbc.url=jdbc:postgresql://localhost:5432/phoss-ap
phossap.jdbc.user=peppol
phossap.jdbc.password=peppol
phossap.jdbc.schema=ap
# Document storage (required)
storage.inbound.path=/var/phoss-ap/inbound
storage.outbound.path=/var/phoss-ap/outbound
# Forwarding — choose one (required for inbound processing)
forwarding.mode=http_post_async
forwarding.http.endpoint=http://your-backend:8888/forwardingIn phase4-peppol-standalone you implemented IPhase4PeppolIncomingSBDHandlerSPI in a class like CustomPeppolIncomingSBDHandlerSPI and registered it in META-INF/services/. phoss-ap ships its own production implementation (Phase4InboundMessageProcessorSPI) that handles:
- Database storage of the inbound transaction
- Document payload persistence
- Duplicate detection (AS4 + SBDH level)
- Optional document verification
- Forwarding to your backend system
- Peppol Reporting item creation
- MLS response generation
Action: Delete your CustomPeppolIncomingSBDHandlerSPI class and its META-INF/services/ registration. phoss-ap's SPI is registered automatically.
If you had custom business logic in your SPI (beyond the TODOs), the equivalent integration point in phoss-ap is the forwarding layer — configure it to POST inbound documents to your backend system. See Receiving Process for the full flow.
In phase4-peppol-standalone the ServletConfig class (~280 lines) manually configures:
- AS4 server initialization
- Crypto factory setup
- AS4 message dumping
- SMP receiver checks
- Peppol Reporting backend
- CRL downloader
Action: Delete your ServletConfig class. phoss-ap handles all of this in APServletInit which is invoked automatically by the AS4ServletRegistration Spring bean.
The standalone project has an APConfig class that reads configuration via AS4Configuration.getConfig(). phoss-ap uses its own configuration stack:
-
APConfigProvider— central config access backed by ph-config -
APCoreConfig— typed accessors for all configuration properties - Spring profile support —
application-{profile}.propertiesfiles are automatically loaded
Action: Delete your APConfig class. Use APCoreConfig static methods instead.
The REST API paths have changed:
| phase4-peppol-standalone | phoss-ap | Notes |
|---|---|---|
POST /sendas4/{s}/{r}/{d}/{p}/{c} |
POST /api/outbound/submit/{s}/{r}/{d}/{p}/{c} |
Same path parameters. Response format changed (see below) |
POST /sendsbdh |
POST /api/outbound/submit-sbd |
|
POST /sendas4-facturx/{s}/{r}/{c} |
(use submit with payloadMimeType param) | Factur-X is handled via the payloadMimeType query parameter |
GET /phase4ping |
(use actuator health) | GET /actuator/health |
GET /create-tsr/{y}/{m} |
GET /api/reporting/create-tsr/{y}/{m} |
Moved under /api/reporting prefix |
GET /create-eusr/{y}/{m} |
GET /api/reporting/create-eusr/{y}/{m} |
Moved under /api/reporting prefix |
GET /do-peppol-reporting/{y}/{m} |
GET /api/reporting/do-peppol-reporting/{y}/{m} |
Moved under /api/reporting prefix |
New APIs in phoss-ap:
| Endpoint | Purpose |
|---|---|
GET /api/outbound/status/{sbdhInstanceID} |
Query outbound transaction status |
GET /api/outbound/in-transmission |
List transactions currently being sent |
GET /api/inbound/status/{sbdhInstanceID} |
Query inbound transaction status |
GET /api/inbound/in-processing |
List transactions currently being processed |
POST /api/inbound/report |
Inbound transaction report (forwarding status) |
GET /api/mls/missing |
List transactions with missing MLS responses |
See API Specification for full details.
Response format change: In phase4-peppol-standalone, sending is synchronous — the API blocks until the AS4 message is sent (or fails) and returns the result directly. In phoss-ap, sending is asynchronous — the API queues the message and returns immediately with status: queued and the sbdhInstanceID. Use the status API to poll for the result.
This is the main new concept. In phase4-peppol-standalone, your CustomPeppolIncomingSBDHandlerSPI was the integration point — you wrote custom code to handle each inbound document. In phoss-ap, the AP receives and stores the document, then forwards it to your backend system using a configurable transport.
Choose one of:
-
HTTP POST (
http_post_syncorhttp_post_async) — posts the SBD to an HTTP endpoint -
S3 (
s3_link) — writes to an S3 bucket -
SFTP (
sftp) — uploads via SFTP -
Filesystem (
filesystem) — writes to a local directory
Example for HTTP POST:
forwarding.mode=http_post_async
forwarding.http.endpoint=http://your-backend:8888/receiveSee Configuration Properties for all forwarding options.
Once migrated, consider enabling these features that were not available in phase4-peppol-standalone:
- Retry with exponential backoff — automatic for both sending and forwarding. See Retry and Resilience Patterns.
-
Duplicate detection — rejects or flags duplicate messages. Configure with
duplicate.detection.as4.modeandduplicate.detection.sbdh.mode. -
Document verification — validates inbound/outbound documents against Peppol BIS rules. Enable with
verification.inbound.enabled=true. -
Sentry error tracking — set
sentry.dsnto enable. See Configuration Properties. -
MLS support — configure with
mls.type. See Peppol Specifics. -
Grouped AS4 dumps — set
phase4.dump.mode=groupedto correlate request/response messages in the same directory.
Use the built-in test modules:
-
phoss-ap-testbackend— a mock forwarding backend that accepts HTTP POST forwarding -
phoss-ap-testsender— a command-line tool for sending test documents
"Failed to init Peppol Reporting Backend Service": The Peppol Reporting tables are created by Flyway. Make sure the peppol.reporting.jdbc.* and peppol.report.jdbc.* properties point to a reachable database instance (PostgreSQL or MySQL) and the user has CREATE permissions.
"No Storage Inbound/Outbound Path provided": Set storage.inbound.path and storage.outbound.path in your configuration. These directories are created automatically but the parent path must exist.
"The configured Peppol Seat ID does not match the syntactical requirements": The Seat ID format is POP followed by exactly 6 digits (e.g. POP000306). In phase4-peppol-standalone, the validation was less strict.
API returns 401: All API endpoints require the X-Token header. Set phase4.api.requiredtoken in your configuration, same as in phase4-peppol-standalone.
It is appreciated if you star the GitHub project if you like it.
Donation link: https://paypal.me/PhilipHelger
- Home
- News and noteworthy
- Running phoss AP
- Architecture Overview
- API Specification
- Configuration Properties
- Code Lists
- Database Design Notes
- Maven Module Structure
- Runtime Extensions
- OpenTelemetry Integration
- Security Considerations
- Peppol Specifics
- Testing Without Peppol Network
- Known Users
- Migrating from phase4-peppol-standalone
- Contributing