Transformers in WildFly allows replication of configuration from newer domain controller in a WildFly servers domain to an older (non-upgraded yet) slave server.
This article describes basic examples of creating transformers and their testing.
Transformers for one subsystem can look like following example. They should be defined in class implementing ExtensionTransformerRegistration.
The first few lines defines ModelVersion object for individual versions of model.
This should correlate with version of XSD for XML configuration files.
The registering method defines individual transformers for individual transitions.
No need to define transformers from version 3 to version 1 - it is sufficient to have defined transitions from 3 to 2 and from 2 to 1.
Transformations do always downgrading only - using newer slave server with older domain controller is not supported by WildFly.
In this example the transition from 2.0.0 to 1.2.0 is blank - no changes requiring transformers was done in the model.
In the version 3.0.0 was on the other had defined new attribute “flushed”. This attribute, when set, change behavior of file-audit-log by way, which cannot be archieved in older version. (Or it would be too complicated to ensure it using transformer.) This meand we need to set two transformations:
When the attribute is undefined, it should be discarded
When the attribute is used, the transformation has to be rejected
How to archieve it you can see in the example above.
Testing
WildFly core provides testing framework for testing proper behavior of transformers. It is part of wildfly-subsystem-test-framework.
Simple transformers testing test
To create simple transformers test case you need to extend AbstractSubsystemBaseTest:
Now you can add transformation test. The test will load a testing XML file into latest subsystem and will try to initialize legacy subsystem from it.
At first, lets specify target version of transformation. The frameworks requires to specify version of the controller using ModelTestControllerVersion enum and version of the model of the tested subsystem (ModelVersion as specified in the transformers). In following example we will transform to the subsystem model version default to the given controller version:
The AbstractSubsystemBaseTest provides a method to obtain KernelServicesBuilder allowing to boot up controller for latest version of the subsystem:
The builder will be used to boot up the old version of controller too. Take a note the old subsystem is downloaded from Maven repository:
Now you can finish the builder and verify that both controllers has booted up successfully:
The model parsed by latest controller from XML provided by is now already transformed and used by the legacy controller. The framework provides method to check that both models are the same and valid:
Testing of rejecting rules
Part of the transformers are also rejecting rules, which needs to be tested too. Lets image we have a new attribute flushed which cannot be part of the legacy model. To test it will be rejected, we need to write and XML configuration containing it, to parse it and to try to transform it:
Util of testing subsystem will check that ALL listed attributes (and nothing else) will be rejected.
Be aware the test framework use FailedOperationTransformationConfig to fix the model to continue checking following failures.
The NewAttributesConfig will ensure the attribute flushed will be undefined after its failing.
If you are checking rejecting subattribute of complex attribute, the whole attribute will be undefined after its rejecting to continue evaluation. But that can cause operation failure if the complex attribute was required. You need to use REJECTED_RESOURCE config in such case - the whole resource adding operation will be removed before continuing the evaluation.