Extending it

The extension model

Your document types live in your model, keyed to your own enum values. The module finds them by name, and nothing of ours has to change.

Sooner or later a partner asks for a document nobody else uses, or a format that is theirs alone. The answer is not a support ticket. You extend two enums, write a handler class, and add the Electronic Reporting configurations that turn records into a file and back.

Nothing is forked, nothing of ours is edited, and an upgrade of the module does not touch what you wrote.

The three bases

The extension surface is three abstract classes. That is the contract; everything else is implementation and may change.

BaseWhat it is for
LunoLakeEDIDocumentTypeHandlerA document type. What format it belongs to, which business process it sits at, and what to do with one that arrives
LunoLakeEDIOutboundDocumentTypeHandlerThe same, for a type you also send. Adds the one method that builds the report contract
LunoLakeEDIAckTypeHandlerWhat an acknowledgement looks like in your format, per layer

Extend the outbound base when the document is sent under an outbound agreement. Extend the plain base when it is only received, or when it is an acknowledgement, because an acknowledgement builds no contract.

How yours is found

By the name of your enum element. You extend LunoLakeEDIDocumentType with a value of your own, and you name that same value in an attribute on the handler.

[LunoLakeEDIDocumentTypeAttribute(enumLiteralStr(LunoLakeEDIDocumentType, SIMPLEDI_GRN))]
public final class LunoLakeEDIExampleGrnHandler extends LunoLakeEDIOutboundDocumentTypeHandler
{
}
The attribute is the registration. There is no list to add yourself to.

The element name is the key at both ends. The compiler produces the string in your attribute; the module produces the identical string at run time from the enum value it is holding. They meet on a name, not on a number, which is why nothing breaks when enum values are renumbered by a deployment.

Built-in types do not go through this

The shipped types are not decorated with attributes, and asking the registry for one returns nothing. That is by design: the lookup is only reached when a type is not one of ours. Your handler cannot accidentally take over EDIFACT INVOIC by registering for it.

Acknowledgements are the one exception, and deliberately so. An acknowledgement handler is consulted before the built-in mapping, so you can override what a receipt looks like in a format the module already knows, if a partner insists on a variant.

One handler per key

Two classes registering for the same document type is a mistake the platform reports loudly, and it will do so at the worst moment if the first time it happens is a live message. The module ships a diagnostic that finds duplicate registrations before that, and it is worth running after any model is added.

The example model

LunoLakeEDIExample is a complete worked example: an invented format called SIMPLEDI with a goods received note, two acknowledgement types, a compare engine, triggers and tests. It is a separate model which is deliberately not a friend of the module, so it compiles against the published surface only.

That is the point of it. If the example builds, the surface is enough, and anything you need that it cannot reach is a gap in the surface rather than a thing to work around.

Adding a document type walks through it from an empty model.