On 5 Mar 2013, at 14:23, Jaikiran Pai wrote:
I've been trying to implement a new feature which requires the
addition
of a new model attribute for the EJB3 subsystem root resource. This
model attribute is supposed to be "mandatory" (i.e. non-nullable at
model level and "required" at xml level). All works fine without
bringing into picture older versions of the model. Now while testing
with older versions of the model and compatibility, things start failing
for obvious reasons- the older model handlers, parsers etc... have no
clue about this new attribute. I'm aware that that's where the
The old
parsers should make it possible to construct the current model. Is the new attribute
something which is now configurable, so you have two choices whereas previously one of
those choices was assumed? In that case I think the old parser should create the resulting
operation with the assumed default.
transformers come into picture and I've setup an appropriate
transformer
that is supposed to handle this scenario. But, the transformers tests in
EJB3SubsystemUnitTestCase fails for different test methods. I had to dig
a bit into the code to figure out that one of the failures had to do
with the test case itself rather than the new code.
One part of the problem and the main reason why I decided to ask this
via a mail instead of over IRC is because, I've been having a difficult
time with the transformer APIs and its usage. On a higher level I
(think) I do understand what the transformers are supposed to do and how
to deal with individual attribute/resource changes when multiple
versions of the model come into picture. But when it comes to wiring the
right transformers at the right place in the code or figuring out what
such places are or even debugging failing tests, I find it not so
straightforward to understand what's going on. Perhaps it's just that I
am not yet used to those APIs. To be honest, with whatever transformer
code I've added, although it seems to work to a certain extent, I'm not
confident about the code I'm adding - I've been just looking at other
places and copying over the code wherever appropriate.
So back to the original issue and the related question - would it be
possible to "automate" this process of plugging in these transformers?
In this specific case, for example, I think almost all (there maybe be
exceptions) subsystems and resources introducing a new attribute in the
higher model would expect that that attribute to be ignored (I'm not
using the term discarded or rejected because I am not 100% sure I
understand the difference yet :) ) by lower versions of the model.
discard =
silently discard the attribute
reject = if the attribute is used/does not have some value/is defined/other conditions the
transformation should fail
Normally we prefer reject. So for your case, again assuming that the added attribute has
some assumed value in the old version, you should fail transformation if the current model
does not have that assumed value. From what you say it will always be defined, so
you'd need something like
static void registerTransformers(final SubsystemRegistration subsystem) {
final ModelVersion version = ModelVersion.create(1, 3); //The old model version
final ResourceTransformationDescriptionBuilder subsystemBuilder =
TransformationDescriptionBuilder.Factory.createSubsystemInstance();
//Get the child you want to add the attribute to
final ResourceTransformationDescriptionBuilder childBuilder1 =
subsystemBuilder.addChildResource(CHILD_PATH);
final ResourceTransformationDescriptionBuilder childBuilder2 =
childBuilder1.addChildResource(CHILD_PATH);
childBuilder2.getAttributeBuilder()
//Reject expressions since if used we cannot check the value and have no idea what they
will be on the slave once resolved
.addRejectCheck(RejectAttributeChecker.SIMPLE_EXPRESSIONS, "new-attribute")
//Check that the attribute has the allowed value
.addRejectCheck(new RejectAttributeChecker.DefaultRejectAttributeChecker() {
@Override public String getRejectionLogMessage(Map<String, ModelNode> attributes)
{
return "The attribute 'new-attribute' must have the value
'assumed-behaviour-in-old'";
}
@Override protected boolean rejectAttribute(PathAddress address, String attributeName,
ModelNode attributeValue, TransformationContext context) {
return !attributeValue.asString().equals("assumed-behaviour-in-old"); }
}, "new-attribute");
}
Or a less verbose way to define the checker:
childBuilder2.getAttributeBuilder()
//Discard if it is not an expression, and equals the assumed value
.setDiscard(new DiscardAttributeChecker.DiscardAttributeValueChecker(new
ModelNode("assumed-behaviour-in-old")),"new-attribute")
//Reject if the attribute was not discarded (discard happens before the
rejections are checked, see the attributebuilder javadoc)
.addRejectCheck(RejectAttributeChecker.DEFINED, "new-attribute");
So
instead of me trying to figure out where to plugin these transformers,
would it be possible to *dynamically* generate these transformers for
some of these cases? That way I wouldn't have to deal with these for
every new attribute and instead be assured that this would be handled
centrally at some place?
Currently I don't see that happening. For AS.next from
what David says that should be possible.
P.S: If someone wants to take a look at the (failing WIP) code that I'm
talking about, then let me know, I can push my code to github. I wanted
to keep this mail to be broader than just this specific failing case.
-Jaikiran
_______________________________________________
jboss-as7-dev mailing list
jboss-as7-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-as7-dev
---------------------------------------
Kabir Khan
Prinicipal Software Engineer
JBoss by Red Hat