Native Spring Integration (warning: LONG)
Rod Widdowson
rdw at steadingsoftware.com
Thu May 1 06:57:42 EDT 2014
> I probably need an overview of the topic in general.
I agree; it would be a good idea generally to take a step back. I find that
writing stuff like this out can often help clear up the issues – or at least
allow us to focus on the important ones. So here goes.
What follows is written in terms of the ProfileConfiguration objects, but is
equally true of other parts of the V2 legacy configuration.
The general problem statement is that the V3 objects have significantly
greater nuance than allowed by the V2 syntax. To that end we want to allow
the embedding of <spring:beans> statements at suitable places in the V2
configuration files so as to allow easy and open ended break out to the
richer syntax.
Two questions arise from this: How does one link from the old syntax to the
new and in what context does one parse the embedded <beans> statement.
The second is the more technical but it motivates much of what follows, so
I’ll start there
Roughly speaking parsing is done within the context an application context.
When we parse the embedded <beans> statement, we only have two choices for
the application context. We can parse within an entirely disconnected
application context or we can parse within the current application context.
The preferred third option of parsing within a separate application context
which is parented by the current one is physically not possible – roughly
speaking an application context cannot be a parent until it has been
refreshed and by definition the current application context has not been
refreshed.
Using a separate application context has the advantage that it can be
refreshed and thus we can look up beans by name and type. The latter is
exploited heavily in the DataConnector callouts (even when the file is
external) as the mechanism by which we link from the V2 syntax to the
embedded beans. For each setter we enquire of the (parsed) <beans>
statement whether it has a bean of that type and if so we set it. The
disadvantage of course is that the <bean> statements can have no external
references. Again this is not a big issue for the DataConnectors where we
need to share beans is minimal.
Using the same application context has the advantages of bean visibility,
but two major disadvantages. Firstly we cannot lookup beans by name and,
critically, by type (although we can plant references to them by name).
Secondly the namespace isolation one might expect between two <beans>
statements (on say, different ProfileConfiguration objects) is not there.
So the deployer needs to take some care to avoid name duplication. On the
other hand all beans are available everywhere. The effect is as if all the
<beans> statements were in a separate file and that file was parsed as a
peer to relying-party.xml. The proximity to a specific configuration
element is purely syntactic, not semantic.
With that out of the way we come to the issue of linking the V2
configuration syntax to the native beans. There are several options here
some of which we can dismiss out of hand.
We can use the type required to lookup the bean. This only works for
disconnected contexts and only works if we need exactly one type. As
mentioned above the DataConnectors use it and we currently use it for the
SecurityConfiguration of a profile, but we cannot make use of it in other
cases since everything we want to plug in is a Predicate. Move on.
We could use fixed names to lookup the bean (so for instance
“Shibboleth.saml1.Artifact.signAssertionsPredicate”). We currently use
fixed names only to define system defaults; in the specific case of the
profile objects there are fixed names for the default Artifact parameters.
Any utility of this approach for linking between V2 syntax and V3 profiles
is massively diminished if we do not have fully detached application
contexts because at that stage we need specific names for each profile in
each relying party definition. Scott hates any use of this beyond (and
probably including) system wide defaults, my mild preference was probably
motivated by the need to type less code. Move on.
This basically leaves us with specifying the bean’s name in the custom
syntax. This then punts any name uniqueness issues to the person doing
config – further it allows for bean re-use when we are sharing the context.
So then we get to deciding how to specify the bean name. And now we need to
get into the specific details of the profile configuration. My current
guess is that for each profile configuration (in each relying party
statement) we need to allow the user to define one SecurityConfiguration
object and up to seven different Predicates (3 to control signing, 3 for
encryption, plus one new one for SSOS); we will probably chose to add 2 or 3
Functions for context navigation.
The new Predicate and the Functions will require specific attributes be
added at appropriate points of the schema. We have already added some new
attributes so this is no big deal beyond documentation.
For SecurityConfiguration, in V2 there is an attribute "securityPolicyRef"
in the schema. This refers to redundant configuration and we have
deprecated. We should leave it deprecated and instead use a new attribute
"securityConfigurationRef". Here I am dismissing the use of type matching
even if there is but one object – too confusing to mix modes within one file
(although this may ask difficult questions when we come to the attribute
resolver).
This leaves the 6 crypto predicates. In V2 attributes exist for each of
these and they are bound to one of three strings “always”, “never”,
“conditional”. Whilst we could define new attributes for these 6 predicates
(and make each mutually exclusive with the old style config), Scott made a
proposal to overload the existing attributes such if they were not “always”,
“never” or “conditional” that would be taken as a bean name. My concern
here was that the comparison would happen before property replacement and so
we might end up making the wrong choice. On further thought this need not
be an issue we could make the decision based on the name being “always”,
“never”, “conditions” or not matching “*{*}*” (turned into a regexp of
course).
Before I list my current (but ever changing) preference I should note two
other options open to us
We could stop polishing this parsing and say “you get what you get for
legacy or you use beans”. I’d sooner avoid this since as Scott says “I just
know the ease of use will go way down” and we are within a whisker of
nailing this. Further it does not solve the issue for the attribute
resolver (which also needs predicates).
Another slightly mind-bending option for dealing with new attributes is to
teach the parsers to understand the “p:” syntax and be done with it. This
would be limited in its function (since sometimes one XML element summons up
a hierarchy of beans) but it would fix this problem. My instinct is that
this is a step too weird for the end users.
Anyway my preference right now is to go for the “same context” parsing
(opposite to the data connectors) and to overload the currents attributes
where relevant, but adding some simple tests against property replacement.
Thanks to those who have got this far.
More information about the dev
mailing list