Core interfaces
IAS4Profile
Defines a profile’s ID, name, validator, and PMode provider
IAS4ProfileRegistrarSPI
SPI interface for registering one or more profiles
IAS4ProfileValidator
Validates PModes and messages against profile rules
IAS4ProfilePModeProvider
Creates or retrieves a PMode for given party identifiers
IAS4Profile
IAS4Profile is the main descriptor interface. The default implementation is AS4Profile.
IAS4ProfilePModeProvider
A functional interface that either retrieves an existing PMode or creates a new one:IAS4ProfileValidator
ImplementIAS4ProfileValidator to enforce profile-specific rules at runtime:
IAS4ProfileRegistrarSPI
Implementation walkthrough
@Immutable
public final class MyProfilePMode {
public static final String DEFAULT_AGREEMENT_ID = "https://example.com/as4/agreement";
public static PMode createMyProfilePMode(
@NonNull @Nonempty final String sInitiatorID,
@NonNull @Nonempty final String sResponderID,
@Nullable final String sAddress,
@NonNull final IPModeIDProvider aPModeIDProvider,
final boolean bPersist) {
final PModeParty aInitiator = PModeParty.createSimple(
sInitiatorID, CAS4.DEFAULT_INITIATOR_URL);
final PModeParty aResponder = PModeParty.createSimple(
sResponderID, CAS4.DEFAULT_RESPONDER_URL);
// Build the security leg
final PModeLegSecurity aSecurity = new PModeLegSecurity();
aSecurity.setWSSVersion(EWSSVersion.WSS_111);
aSecurity.setX509SignatureAlgorithm(ECryptoAlgorithmSign.RSA_SHA_256);
aSecurity.setX509SignatureHashFunction(ECryptoAlgorithmSignDigest.DIGEST_SHA_256);
aSecurity.setX509EncryptionAlgorithm(ECryptoAlgorithmCrypt.AES_128_GCM);
aSecurity.setPModeAuthorize(false);
aSecurity.setSendReceipt(true);
aSecurity.setSendReceiptNonRepudiation(true);
aSecurity.setSendReceiptReplyPattern(EPModeSendReceiptReplyPattern.RESPONSE);
final PModeLeg aLeg = new PModeLeg(
PModeLegProtocol.createForDefaultSoapVersion(sAddress),
PModeLegBusinessInformation.create(null, null, null, CAS4.DEFAULT_MPC_ID),
new PModeLegErrorHandling(null, null,
ETriState.TRUE, ETriState.TRUE, ETriState.TRUE, ETriState.TRUE),
null,
aSecurity
);
final PMode aPMode = new PMode(
aPModeIDProvider.getPModeID(aInitiator, aResponder),
aInitiator, aResponder,
DEFAULT_AGREEMENT_ID,
EMEP.ONE_WAY, EMEPBinding.PUSH,
aLeg, null, null,
new PModeReceptionAwareness(
ETriState.TRUE, ETriState.TRUE, 1, 10_000, ETriState.TRUE)
);
if (bPersist)
MetaAS4Manager.getPModeMgr().createOrUpdatePMode(aPMode);
return aPMode;
}
}
public class MyProfileCompatibilityValidator implements IAS4ProfileValidator {
@Override
public void validatePMode(
@NonNull final IPMode aPMode,
@NonNull final ErrorList aErrorList,
@NonNull final EAS4ProfileValidationMode eValidationMode) {
// Enforce one-way/push only
if (aPMode.getMEP() != EMEP.ONE_WAY || aPMode.getMEPBinding() != EMEPBinding.PUSH) {
aErrorList.add(SingleError.builderError()
.errorText("Only one-way/push is valid for MyProfile")
.build());
}
final PModeLeg leg1 = aPMode.getLeg1();
if (leg1 == null) {
aErrorList.add(SingleError.builderError()
.errorText("PMode.Leg[1] is missing")
.build());
} else {
// Validate security settings ...
}
}
@Override
public void validateUserMessage(
@NonNull final Ebms3UserMessage aUserMsg,
@NonNull final ErrorList aErrorList) {
// Validate message properties, party info, etc.
}
}
@IsSPIImplementation
public final class AS4MyProfileRegistrarSPI implements IAS4ProfileRegistrarSPI {
public static final String AS4_PROFILE_ID = "my-profile";
public static final String AS4_PROFILE_NAME = "My Custom Profile";
public static final IPModeIDProvider PMODE_ID_PROVIDER =
IPModeIDProvider.DEFAULT_DYNAMIC;
@Override
public void registerAS4Profile(@NonNull final IAS4ProfileRegistrar aRegistrar) {
final IAS4ProfilePModeProvider aDefaultPModeProvider =
(initiatorID, responderID, address) ->
MyProfilePMode.createMyProfilePMode(
initiatorID, responderID, address,
PMODE_ID_PROVIDER, true);
final AS4Profile aProfile = new AS4Profile(
AS4_PROFILE_ID,
AS4_PROFILE_NAME,
MyProfileCompatibilityValidator::new, // validator supplier
aDefaultPModeProvider,
PMODE_ID_PROVIDER,
false, // not deprecated
false // do not invoke SPI for ping messages
);
aRegistrar.registerProfile(aProfile);
}
}
Create the file
src/main/resources/META-INF/services/com.helger.phase4.profile.IAS4ProfileRegistrarSPI with the fully qualified class name of your SPI implementation:Once the artifact is on the classpath, phase4 discovers and registers the profile automatically at startup via
java.util.ServiceLoader. No further configuration is required.