Skip to content

Multi Profile Handling

Philip Helger edited this page Aug 23, 2024 · 7 revisions

This page describes the best practices for dealing with multi AS4 profiles (like Peppol and CEF) in parallel.

Generally it makes a difference if you are sending or receiving. Additionally, not all profiles can easily be combined out of the box (e.g. BDEW has specific requirements).

General considerations

The following aspects need to be considered when dealing with multi AS4 profiles and may be different:

  • Key material (key store and trust store)
  • AS4 profile ID
  • PMode parameters and requirements
  • http/https settings (TLS, timeouts etc.)
  • Validations on the message integrity
  • Validations based on the chosen AS4 profile (e.g. Peppol-specifics)

Sending considerations

Most AS4 profile come with its own special sender builder (via the phase4-{profile}-client module). As the sending of the document can usually be triggered without additional context, all required parameters may simply be provided to the builder directly and will apply to sending exactly that instance:

  • .cryptoFactory(...), .cryptoFactorySign(...) and .cryptoFactoryCrypt (...) to define key store and trust store for signing and/or encryption
  • .pmode(...) or .pmodeResolver(...) to set the PMode parameters/templates
  • .as4Profile(...) to set the AS4 profile ID (since v2.8.2) - please note: implicitly uses the IPModeResolver to do the job. So if you use a custom IPModeResolver, please make sure to use the correct AS4 profile there.
  • .httpClientFactory(...), .httpRetrySettings(...)and .customHttpPoster(...) to define HTTP specific settings

Receiving considerations

For receiving, the setup is a bit more tricky. The following aspects need to be considered on top of the general aspects mentioned above:

  • Verify that the receiver is really handled by the receiving AP (e.g. in Peppol)

There are some general decisions to be made to handle multiple profiles on reception:

  • Use a different host name/path (aka Request URL) for each profile (e.g. https://example.org/as4/peppol and https://example.org/as4/cef)
    • This is the recommended way to handle multiple different AS4 profiles
    • Handle each Request URL by a different Servlet (or comparable) - that's the easiest way, because it just means configuring each Servlet once statically for each profile
      • This does not to be described explicitly, it should be straight forward
    • Handle each Request URL by the same Servlet (or comparable) - than some kind of differentiation is needed per reception, based on the request URL (or the proxied request URL)
      • This is described below in more detail
  • Use the same request URL for each profile and differentiate based on the message content
    • This is not recommended because it becomes more difficult, especially if not just UserMessages are exchanged but also PullRequests. Also the different requirements on signing and encryption may further complicate the correct determination of the profile to be used.
    • Also some AS4 profiles mandate the usage of specific HTTP/TLS settings, which is easiest to configure per domain name
    • This option is not described further

Different URL and Same Servlet

In this scenario each AS4 profile is required to have it's own public URL but is handled by the same servlet.

Note: the description in this section refers to the Servlet based implementation as used when run as a Spring Boot application or inside a common Java Application server. This section does not apply to other deployment scenarios like AWS Lambdas.

Solution in v2:

The expected way to handle this scenario, is to provide an implementation of class AS4XServletHandler.IHandlerCustomizer and pass it via setHandlerCustomizer into the instance of AS4XServletHandler that's running the AS4 Servlet. This allows you to call the setters in the AS4RequestHandler. However to customize the CryptoFactory based on the request URL you need to overwrite AS4XServletHandler.handleRequest(IRequestWebScopeWithoutResponse, UnifiedResponse) and make the call to the other handleRequest method manually.

This process will be simplified in the upcoming v3 implementation.