MP-Config 1.2.1: conversion questions from implementor's/spec-reader's perspective

24 views
Skip to first unread message

Laird Nelson

unread,
Mar 28, 2018, 7:31:42 PM3/28/18
to Eclipse MicroProfile
Hello; I'd like to verify the following in the MicroProfile-Config 1.2.1 specification.  My understanding is that each of these statements is correct:
  • It is possible to ask MicroProfile-Config to convert any configuration value's raw String value to an array of a given type, e.g. by doing something like config.getValue("productionUrl", URL[].class).  That conversion may succeed or fail.
    • If array conversion is successful, it is because conversion to the array's component type of each String scalar value separated from others by an un-backslash-escaped comma has succeeded, either because:
      • A Converter for the relevant scalar type was found using the ServiceLoader mechanism or its equivalent and was used successfully
      • A default Converter was used successfully
      • Something like a valueOf(String) method or single-String constructor was used successfully
    • If array conversion fails, it is because of only one of the two following reasons:
      • A Converter for the relevant array component type couldn't be found and there was no default Converter for that type and the type itself had no valueOf(String) method or constructor etc.
      • A Converter was found, or a valueOf(String) method or constructor etc. was used, but due to formatting or IO or whatever couldn't parse one of the scalar String values in the String representation of the array.
    • The length of the array returned in a successful array conversion case—regardless of array component type—is equal to one more than the number of un-backslash-escaped commas in the String representation of the configuration value.  Example: If there are no unescaped commas, then the length is 1; if there is one unescaped comma, then the length is 2, and so on.
    • Whether or not whitespace around scalar String values that result from "splitting" a raw String configuration value in this way is significant is unspecified.
  • There is a grammar—a very, very simple grammar, but a grammar nonetheless—for all raw String configuration values.  Roughly, its tokens are commas, backslashes (used only to escape commas) and everything else.
  • Given a configuration entry named "foo" with a raw String configuration value of "bar\, baz", the value of config.getValue("foo", String.class) must be equal to "bar\, baz", not "bar, baz".
  • Given a configuration entry named "foo" with a raw String configuration value of "bar, baz", the value, v, returned by config.getValue("foo", String[].class) must satisfy all of the following assertions: assert v.length == 2; assert "bar".equals(v[0]); assert " baz".equals(v[1]); (note the whitespace in the last one).
  • It is implied, but never stated explicitly in the specification, that a MicroProfile-Config implementation's implementation of the Config#getValue(String, Class) method must use Converters.
  • Whitespace handling in general in the conversion of (or simple retrieval of) raw String configuration values is unspecified, so it is legal (but probably quite stupid :-)) for a Converter to consider leading and trailing whitespace around a scalar value to be significant (I didn't find "whitespace" in the specification).
  • As a user, it is not possible to determine through the MicroProfile-Config framework itself all the types a given raw String configuration value may be converted to in a given environment.
  • One MicroProfile-Config implementation may convert raw String configuration values into a given target type using a different Converter from that used by another MicroProfile-Config implementation for the same type conversion.
    • Therefore, in certain cases a defensive configuration value author should ideally know what Converters and possibly what ConfigSources will be in effect in the MicroProfile-Config implementation her configuration values may find themselves being loaded into and converted by if she wants to ensure portable type conversion is a possibility.
      • Example: if Alice writes a configuration value named "productionUrl" with a raw String value of (making this up) "url:<http://example.com:1234>", in any format loadable by any given ConfigSource implementation, then Alice has to make sure that whatever MicroProfile implementation uses it has a Converter registered that will understand that URL format if her users are supposed to do config.getValue("productionUrl", URL.class).  Or, conversely, if Alice is relying on the behavior of the default URL Converter (priority 1), and so her productionUrl raw String configuration value is simply "http://example.com:1234" (now parseable by the default URL Converter) then she has to make sure that there is no higher-Priority URL Converter registered in the implementation that might try to parse her value differently.)
And one perhaps very stupid question:
  • Is @Priority(0) "higher priority" than @Priority(1), or vice versa?  (In English, "your first priority" is semantically equal to "your highest priority", even though 1 is not greater than 2.)  I see that default Converters are implicitly at @Priority(1), so that makes me think they're the fallback ones, so that means if my, say, String Converter is @Priority(2) I'm thinking it should be used, and if it is @Priority(0) it would not.
Thanks in advance for the overall MicroProfile effort, this group and your time!

Best,
Laird

Mark Struberg

unread,
Mar 31, 2018, 3:50:49 PM3/31/18
to Eclipse MicroProfile
>  Given a configuration entry named "foo" with a raw String configuration value of "bar\, baz", 
> the value of config.getValue("foo", String.class) must be equal to "bar\, baz", not "bar, baz"

Yes, but config.getValue("foo", String[].class) will result in {"bar, baz"} ;)

" baz".equals(v[1]); (note the whitespace in the last one).
Well, it's actually not really defined. An impl might decide to trim() those values without violating the spec.
From a user perspective the safest bet is to not include whitespaces I'd say.


> If array conversion fails, it is because of only one of the two following reasons:...
yes

> Whitespace handling in general in the conversion of (or simple retrieval of) raw String configuration values is unspecified, 
> so it is legal (but probably quite stupid :-)) for a Converter to consider leading and trailing whitespace around a scalar
>  value to be significant (I didn't find "whitespace" in the specification).
Yes it's undefined thus vendor specific. A user should simply not include a whitespace if he wants to be portable.
Happy to improve/clarify whitespace handling!

> As a user, it is not possible to determine through the MicroProfile-Config framework itself all the types a given raw String configuration value may be converted to in a given environment.
Exactly. Do you need that? What is the use case for it?

> One MicroProfile-Config implementation may convert raw String configuration values into a given target type 
> using a different Converter from that used by another MicroProfile-Config implementation for the same type conversion.

How so? There must only be one effective Converter for a specific Type. Otherwise this will be treated as deployment error.
But I see that our wording is probably not as specific as I thought ("If multiple Converters are registered for the same type, the one with the highest priority will be used.").
Can you plz create a ticket for it? Txs!


> Is @Priority(0) "higher priority" than @Priority(1), or vice versa?
A very good question indeed. We had the same discussion with @Interceptor and @Alternative sort order. 
And btw that's also the reason why I named that property 'ordinal' instead of 'priority' for the ConfigSources back in 2008/9 ;)
In our case a higher value means a higher ordinal.


> Thanks in advance for the overall MicroProfile effort, this group and your time!
Good feedback is always highly appreciated. And you deliver on spot with your questions - so thanks to you as well!

LieGrue,
strub

Laird Nelson

unread,
Apr 2, 2018, 3:25:08 PM4/2/18
to Eclipse MicroProfile
On Saturday, March 31, 2018 at 7:50:49 PM UTC, Mark Struberg wrote:
Yes it's undefined thus vendor specific. A user should simply not include a whitespace if he wants to be portable.

Thanks.
 
> As a user, it is not possible to determine through the MicroProfile-Config framework itself all the types a given raw String configuration value may be converted to in a given environment.
Exactly. Do you need that? What is the use case for it?

Don't know yet; just trying to implement the specification and making sure I'm not missing anything.
 
> One MicroProfile-Config implementation may convert raw String configuration values into a given target type 
> using a different Converter from that used by another MicroProfile-Config implementation for the same type conversion.

How so? There must only be one effective Converter for a specific Type. Otherwise this will be treated as deployment error.

Here is the scenario I am seeking specification clarification on:

Suppose I have a properties file (it doesn't really matter whether it's a properties file or an XML file or a database record or what) that contains an entry like this:

productionUrl=url:<http://example.com>

And now suppose I have an Open Liberty server over here (arbitrary MicroProfile implementation selection) that has a MySpecialURLConverter on its classpath and registered as a service provider of type Converter<java.net.URL>.  Let us further suppose that:
  1. MySpecialURLConverter instances know how to convert a String of the form url:<http://example.com> into a java.net.URL instance
  2. "higher priority" in the specification means that a Converter with a @Priority of 2 must be preferred over a Converter with a @Priority of 1 (this is currently ambiguous at best)
  3. MySpecialURLConverter is annotated with @Priority(Integer.MAX_VALUE) so that it is guaranteed it will be preferred over all other Converter<java.net.URL> instances with any priority less than Integer.MAX_VALUE
Clearly if I deploy my ConfigSource representing this properties file to this environment it will work.  That is, if the caller invokes config.getValue("productionUrl", URL.class), a MySpecialURLConverter instance will have its convert(String) method invoked with "url:<http://example.com>" and will return a URL instance representing it.

Now let us suppose that you have a Wildfly server (I'm arbitrarily choosing these different MicroProfile implementations) without a MySpecialURLConverter instance registered.  Let us further suppose that I now register my ConfigSource, unchanged, in your environment, and deploy the same application.

My configuration will not work, since (let us say) there is no Converter<java.net.URL> registered that can understand a String of the form url:<http://example.com>.  As a configuration author, how was I to know this?

Best,
Laird
Reply all
Reply to author
Forward
0 new messages