Skip to main content
Phase4BDEWSender sends AS4 messages conforming to the BDEW (Bundesverband der Energie- und Wasserwirtschaft) AS4 profile used in the German energy market.

Maven dependency

<dependency>
  <groupId>com.helger.phase4</groupId>
  <artifactId>phase4-bdew-client</artifactId>
  <version>x.y.z</version>
</dependency>

Basic example

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.io.File;

import com.helger.phase4.attachment.AS4OutgoingAttachment;
import com.helger.phase4.bdew.Phase4BDEWSender;
import com.helger.phase4.bdew.Phase4BDEWSender.BDEWPayloadParams;
import com.helger.phase4.crypto.ECryptoKeyIdentifierType;
import com.helger.phase4.sender.EAS4UserMessageSendResult;

final byte[] aPayloadBytes =
    Files.readAllBytes(new File("myDocument.xml").toPath());

// Optional BDEW-specific payload parameters
final BDEWPayloadParams aPayloadParams = new BDEWPayloadParams()
    .setDocumentType("MSCONS")
    .setDocumentDate(LocalDate.now())
    .setDocumentNumber("1234")
    .setFulfillmentDate(LocalDate.now().minusDays(1))
    .setSubjectPartyId("9900123000002")
    .setSubjectPartyRole("MSB")
    .setApplicationReference("myApp");

final EAS4UserMessageSendResult eResult =
    Phase4BDEWSender.builder()
        // Party identifiers
        .fromPartyID("AS4-Sender")
        .fromRole("http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/initiator")
        .toPartyID("AS4-Receiver")
        .toRole("http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/responder")
        // AS4 endpoint URL (BDEW uses static configuration, not SMP)
        .endpointURL("https://receiver.example.org/bdew/as4")
        .receiverCertificate(aReceiverX509Cert)
        // Service and action
        .service("urn:example:bdew:service")
        .action("urn:example:bdew:action")
        // Payload with BDEW-specific parameters
        // GZip compression is enforced automatically
        .payload(AS4OutgoingAttachment.builder()
                                      .data(aPayloadBytes)
                                      .mimeTypeXML()
                                      .charset(StandardCharsets.UTF_8),
                 aPayloadParams)
        .sendMessageAndCheckForReceipt();

if (eResult.isSuccess())
    LOGGER.info("BDEW message delivered");

BDEW profile specifics

PropertyDefault value
AS4 profile IDAS4BDEWProfileRegistarSPI.AS4_PROFILE_ID
Agreement referenceBDEWPMode.DEFAULT_AGREEMENT_ID
Conversation ID"" (empty — must not be changed)
MIME messageAlways forced (forceMimeMessage(true))
Signing key identifier typeBST_DIRECT_REFERENCE
Encryption key identifier typeX509_SKI_KEY_IDENTIFIER
Key encryption algorithmECDH_ES_KEYWRAP_AES_128
C14N algorithmC14N_EXCL_OMIT_COMMENTS
Payload compressionGZip enforced by payload(Builder, BDEWPayloadParams)
The conversationID field is fixed to an empty string per BDEW specification. Do not call conversationID(String) with a non-empty value or isEveryRequiredFieldSet() will return false.

BDEWPayloadParams

BDEW requires additional metadata to be embedded in the MIME attachment’s part properties. Use BDEWPayloadParams to supply them:
MethodAttachment propertyDescription
setDocumentType(String)BDEWDocumentTypeBDEW document type code (e.g. MSCONS)
setDocumentDate(LocalDate)BDEWDocumentDateDocument creation date
setDocumentNumber(String)BDEWDocumentNoDocument number (also accepts int)
setFulfillmentDate(LocalDate)BDEWFulfillmentDateDate the data applies to
setSubjectPartyId(String)BDEWSubjectPartyIDParty ID of the subject
setSubjectPartyRole(String)BDEWSubjectPartyRoleRole of the subject party
setApplicationReference(String)BDEWApplicationReferenceApplication reference string
BDEWPayloadParams is optional. If null is passed as the second argument to payload(), no extra part properties are added.

Crypto key identifier types

Override the defaults if your trading partner requires different settings:
import com.helger.phase4.crypto.ECryptoKeyIdentifierType;

Phase4BDEWSender.builder()
    .encryptionKeyIdentifierType(ECryptoKeyIdentifierType.X509_KEY_IDENTIFIER)
    .signingKeyIdentifierType(ECryptoKeyIdentifierType.BST_DIRECT_REFERENCE)
    ...

Actions without payload

The BDEW profile defines two special actions that do not require a payload:
  • BDEWPMode.ACTION_REQUEST_SWITCH
  • BDEWPMode.ACTION_CONFIRM_SWITCH
When using these actions, omit the payload() call and phase4 will skip the payload validation:
Phase4BDEWSender.builder()
    .action(BDEWPMode.ACTION_REQUEST_SWITCH)
    .fromPartyID(...)
    ...
    // No .payload() call needed
    .sendMessageAndCheckForReceipt();

Capturing the signal message

import com.helger.base.wrapper.Wrapper;
import com.helger.phase4.ebms3header.Ebms3SignalMessage;

final Wrapper<Ebms3SignalMessage> aSignalMsgHolder = new Wrapper<>();

Phase4BDEWSender.builder()
    ...
    .signalMsgConsumer((aSignalMsg, aMetadata, aState) ->
        aSignalMsgHolder.set(aSignalMsg))
    .sendMessageAndCheckForReceipt();

// Inspect receipt
if (aSignalMsgHolder.isSet() && aSignalMsgHolder.get().getReceipt() != null)
    LOGGER.info("Receipt received");

Build docs developers (and LLMs) love