JCache use ServiceLoader to get a Provider then you get a Manager and finally a Cache. It is mainly to ensure you can "bulk" close what you created I think. I'm not convinced we need it - maybe 1 level but no more since we'll just kill "watcher" threads at the end of the Configuration usage (AutoCloseable?).
About key conflict I saw isSameKey() or something like that in the API but I really guess all this logic should be extracted in its own interface (why I though starting with default methods were not a good idea), maybe MergePolicy (with a good default doing nothing or failing, not yet sure ;)). Romain Manni-Bucau @rmannibucau http://www.tomitribe.com http://rmannibucau.wordpress.com https://github.com/rmannibucau 2014-12-01 19:15 GMT+01:00 Werner Keil <[email protected]>: > Haven't looked into it in so much detail, but what I saw from the JCache > JSR it also defines just a single service interface in SPI which then gets > applied via the usual Java Service Provider mechanism. > > JSR 363 leaves it a bit more flexible (as ME 8 knows a slight variation of > that via LIBlets and some implementations may prefer OSGi over JDK Service > Loaders;-) but in essence the SPI package defines some similar interfaces. > > Werner > > On Mon, Dec 1, 2014 at 7:09 PM, Oliver B. Fischer <[email protected]> > wrote: > >> I like the idea of builders. >> >> If we have default providers via SPI how do we handle the a case there two >> providers offer a value for the same key? >> >> Furthermore I would like to have the posibillty to decide which providers >> are automatically choosen by providing a -Dproviders=org.apache.tamaya. >> ProviderA,org.apache.tamaya.ProviderB >> >> Oliver >> >> Am 01.12.14 18:53, schrieb Romain Manni-Bucau: >> >> Markdown4j has something pretty nice (specific but I guess the idea is >>> reusable for us): >>> >>> Configuration.builder().forceExtentedProfile().registerPlugins(new >>> YumlPlugin(), new WebSequencePlugin(), new >>> IncludePlugin()).convertNewline2Br().setDecorator(decorator). >>> setCodeBlockEmitter(new >>> CodeBlockEmitter()).build(). >>> >>> What I like: >>> 1) builder (so can be read-only once built + API is auto-documented >>> and here it is fluent) >>> 2) manual registration of plugins (loaders for us) >>> >>> So we could get: >>> >>> Configuration c = new Configuration.Builder().propertyProviders(new >>> MyProviders1(), new MyProviders2()).build() >>> >>> Not that we can easily write a PropertyProviders using a SPI and I >>> would wire it as a default one if propertyProviders is not called (ie >>> set of providers is empty. >>> >>> This would also allow us to add other features later like property >>> post processors (to change properties loaded from providers etc...) >>> pretty easily and clean-ly. >>> >>> wdyt? >>> >>> >>> >>> Romain Manni-Bucau >>> @rmannibucau >>> http://www.tomitribe.com >>> http://rmannibucau.wordpress.com >>> https://github.com/rmannibucau >>> >>> >>> 2014-12-01 18:31 GMT+01:00 Oliver B. Fischer <[email protected]>: >>> >>>> Hi, >>>> >>>> for me the most simple use case is >>>> >>>> Configuration conf = new Configuration(); >>>> String value = conf.get("key") >>>> >>>> And this use case is already very complex under the hood. >>>> >>>> Before discussing other details we have to decide how PropertyProviders >>>> are >>>> activated. >>>> >>>> I would like to have the following possibilites: >>>> >>>> 1. Tamaya activates all PropertyProviders found in the classpath and >>>> activated via SPI. >>>> 2. Tamaya activates only a explicitly named list of Property providers >>>> 3. I have the ability to control the order in which the property solution >>>> will be performed >>>> >>>> Bye, >>>> >>>> Oliver >>>> >>>> >>>> Am 01.12.14 17:54, schrieb Romain Manni-Bucau: >>>> >>>> Configuration.current() sounds easier to understand first time you see >>>>> it. I like Configuration.newInstance() if that's really what it does >>>>> (ie no caching by classloader or anything else). >>>>> >>>>> >>>>> Romain Manni-Bucau >>>>> @rmannibucau >>>>> http://www.tomitribe.com >>>>> http://rmannibucau.wordpress.com >>>>> https://github.com/rmannibucau >>>>> >>>>> >>>>> 2014-12-01 17:42 GMT+01:00 Anatole Tresch <[email protected]>: >>>>> >>>>>> There is a naming concept from Stephen Colebourne when to use of, from, >>>>>> with. I try to lookup the link later, see also jsr 310 and 354. >>>>>> getInstance, valueOf are considered to be outdated for modern api >>>>>> design. >>>>>> >>>>>> Adding a helper, why? Another artifact a user must know, makes sense, >>>>>> where >>>>>> you have a huge acces api IMO (see PropertyProviders where the factory >>>>>> methods are not part of the PropertyProvider interface. For >>>>>> Configuration >>>>>> I >>>>>> prefer having sn intuitive simple/single access... >>>>>> >>>>>> Nevertheless I would like to encourage you to make a concrete proposal >>>>>> how >>>>>> would name things, so we can compare what your idea of fluent is ;) >>>>>> >>>>>> -anatole >>>>>> Gerhard Petracek <[email protected]> schrieb am Mo., 1. Dez. >>>>>> 2014 >>>>>> um 17:24: >>>>>> >>>>>> hi anatole, >>>>>>> >>>>>>> again - yes and no. >>>>>>> no - it wasn't similar before, because you haven't started with the >>>>>>> most >>>>>>> trivial usage (supported by tamaya right now). >>>>>>> however, now we are talking about a "different part" of the api which >>>>>>> is >>>>>>> very similar -> yes >>>>>>> >>>>>>> -> let's discuss >>>>>>> String myValue = Configuration.of().get("myKey").orElse(null); >>>>>>> >>>>>>> maybe we can get something better than ".of().get" or we provide a >>>>>>> static >>>>>>> helper for it. >>>>>>> currently this first part doesn't read fluently. a lot of users might >>>>>>> not >>>>>>> need more than that (at least in the beginning) and therefore it >>>>>>> should >>>>>>> be >>>>>>> nice. >>>>>>> >>>>>>> regards, >>>>>>> gerhard >>>>>>> >>>>>>> >>>>>>> >>>>>>> 2014-12-01 16:07 GMT+01:00 Tresch, Anatole >>>>>>> <anatole.tresch@credit-suisse. >>>>>>> com >>>>>>> >>>>>>>> : >>>>>>>> Hi Gerhard >>>>>>>> >>>>>>>> as I said granularity is not matching in your example. Comparing >>>>>>>> concepts >>>>>>>> on the same granularity level it would be: >>>>>>>> >>>>>>>> String myValue = ConfigResolver.getPropertyValue("myKey"); >>>>>>>> // >>>>>>>> Deltaspike >>>>>>>> >>>>>>>> compared to: >>>>>>>> >>>>>>>> String myValue = Configuration.of().get("myKey").orElse(null); >>>>>>>> // >>>>>>>> Tamaya >>>>>>>> >>>>>>>> So that looks more or less similar (I did not count the characters) >>>>>>>> ;) >>>>>>>> >>>>>>>> It will be interesting to see how it feels, when defining the model >>>>>>>> >>>>>>> behind >>>>>>> >>>>>>>> this facades. Tamaya can support dynamic property providers (aka >>>>>>>> PropertySource) managed by CDI for app config as well. But on top of >>>>>>>> them >>>>>>>> also will probably be capable to configure CDI and other aspects. >>>>>>>> Already >>>>>>>> in place is a Properties implementation that can be applied to >>>>>>>> System.setProperties(Properties), which adds dynamic >>>>>>>> >>>>>>> (configurable)system >>>>>>> >>>>>>>> properties as a minimal shared level of API already available as of >>>>>>>> now >>>>>>>> >>>>>>> on >>>>>>> >>>>>>>> SE level. >>>>>>>> >>>>>>>> -Anatole >>>>>>>> >>>>>>>> >>>>>>>> -----Original Message----- >>>>>>>> From: Gerhard Petracek [mailto:[email protected]] >>>>>>>> Sent: Montag, 1. Dezember 2014 14:30 >>>>>>>> To: [email protected] >>>>>>>> Subject: Re: Use Case 1: Read simple properties and get values. >>>>>>>> >>>>>>>> hi anatole, >>>>>>>> >>>>>>>> yes and no - the part i talked about mainly is: >>>>>>>> String myValue = ConfigResolver.getPropertyValue("myKey"); >>>>>>>> >>>>>>>> compared to: >>>>>>>> Configuration config = PropertyProviders.fromPaths(/*...*/); >>>>>>>> String myValue = config.get("myKey", String.class); >>>>>>>> >>>>>>>> regards, >>>>>>>> gerhard >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> 2014-12-01 14:22 GMT+01:00 Anatole Tresch <[email protected]>: >>>>>>>> >>>>>>>> Hi Gerhard >>>>>>>>> What you describe is use case that will follow later. You asked me >>>>>>>>> to >>>>>>>>> >>>>>>>> start >>>>>>>> >>>>>>>>> with a simple one, so this is the most simple one. Next use cases >>>>>>>>> will >>>>>>>>> >>>>>>>> add >>>>>>>> >>>>>>>>> aadditional sources, then we will combine things (aka complex >>>>>>>>> >>>>>>>> overridings). >>>>>>>> >>>>>>>>> After that we will emphasize on the environment model, because this >>>>>>>>> >>>>>>>> defines >>>>>>>> >>>>>>>>> the context, which determines which config is appropriate. The user >>>>>>>>> in >>>>>>>>> >>>>>>>> most >>>>>>>> >>>>>>>>> cases will call Configuration.of() to access.the current >>>>>>>>> configuration. >>>>>>>>> This method then is backed by a config provider. This provider >>>>>>>>> decides >>>>>>>>> >>>>>>>> how >>>>>>>> >>>>>>>>> the current environment is determining the config to be returned >>>>>>>>> (aka >>>>>>>>> defines implements the config metamodel). >>>>>>>>> This metamodel can be defined rather differently depending your >>>>>>>>> target >>>>>>>>> runtime and require config solutions. And for this we require the >>>>>>>>> >>>>>>>> basics >>>>>>> >>>>>>>> (where I started). >>>>>>>>> >>>>>>>>> What is in Deltaspike as of now is only a subset of what I see >>>>>>>>> >>>>>>>> necessary >>>>>>> >>>>>>>> to >>>>>>>> >>>>>>>>> build a compelling config system. We will be able to cover that >>>>>>>>> functionality easily and it will be easy to use. >>>>>>>>> >>>>>>>>> So please have some patience and let me post the use cases and >>>>>>>>> >>>>>>>> solutions >>>>>>> >>>>>>>> one by one and focus on these. I try to post them if possible on a >>>>>>>>> >>>>>>>> daily >>>>>>> >>>>>>>> basis. Hopefully we will have then a common terminology and >>>>>>>>> >>>>>>>> architectural >>>>>>> >>>>>>>> view on the whole topic that helps us discuss things efficiently ;) >>>>>>>>> >>>>>>>>> Cheers >>>>>>>>> Anatole >>>>>>>>> >>>>>>>>> Gerhard Petracek <[email protected]> schrieb am Mo., 1. >>>>>>>>> Dez. >>>>>>>>> >>>>>>>> 2014 >>>>>>>> >>>>>>>>> um 13:58: >>>>>>>>> >>>>>>>>> hi @ all, >>>>>>>>>> >>>>>>>>>> @anatole: thx for starting this thread. >>>>>>>>>> >>>>>>>>>> let's start/continue with the first part - the equivalent in >>>>>>>>>> >>>>>>>>> deltaspike >>>>>>> >>>>>>>> is: >>>>>>>>> >>>>>>>>>> String myValue = ConfigResolver.getPropertyValue("myKey"); >>>>>>>>>> >>>>>>>>>> as a precondition for this call, you need 1-n registered >>>>>>>>>> >>>>>>>>> config-source(s) >>>>>>>> >>>>>>>>> (= std. spi config -> in this case in: >>>>>>>>>> META-INF/services/org.apache.deltaspike.core.spi.config. >>>>>>>>>> >>>>>>>>> ConfigSource). >>>>>>> >>>>>>>> this approach is nice for >applications<, because everything is done >>>>>>>>>> automatically based on the "visible" configs. >>>>>>>>>> furthermore, it's very flexible, because a config-source >>>>>>>>>> encapsulates >>>>>>>>>> >>>>>>>>> the >>>>>>>> >>>>>>>>> logic for different config-locations (files, jndi, db,...). >>>>>>>>>> >>>>>>>>>> mark wrote that part -> he might add some details which are >>>>>>>>>> important >>>>>>>>>> >>>>>>>>> to >>>>>>>> >>>>>>>>> him (for the >current< use-case): >>>>>>>>>> >>>>>>>>>> regards, >>>>>>>>>> gerhard >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> 2014-12-01 11:30 GMT+01:00 Romain Manni-Bucau < >>>>>>>>>> [email protected] >>>>>>>>>> >>>>>>>>> : >>>>>>>> >>>>>>>>> Looks like a good entry point, I like the "prefixing" to switch of >>>>>>>>>>> "reader". However I don't like to be forced to use an Optional. In >>>>>>>>>>> several cases I prefer to stick to properties API ie get something >>>>>>>>>>> >>>>>>>>>> or >>>>>>> >>>>>>>> a default, default being null if not set when queried. Optional is >>>>>>>>>>> >>>>>>>>>> not >>>>>>>> >>>>>>>>> bad but makes code very verbose for pretty much nothing is several >>>>>>>>>>> cases (of config). >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> wdyt? >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Romain Manni-Bucau >>>>>>>>>>> @rmannibucau >>>>>>>>>>> http://www.tomitribe.com >>>>>>>>>>> http://rmannibucau.wordpress.com >>>>>>>>>>> https://github.com/rmannibucau >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> 2014-12-01 11:15 GMT+01:00 Anatole Tresch <[email protected]>: >>>>>>>>>>> >>>>>>>>>>>> Hi all >>>>>>>>>>>> >>>>>>>>>>>> I have put together a first couple of simple use cases. It is >>>>>>>>>>>> >>>>>>>>>>> targeting >>>>>>>>> >>>>>>>>>> SE >>>>>>>>>>> >>>>>>>>>>>> level only (as many use cases will do, especially the basic >>>>>>>>>>>> >>>>>>>>>>> ones). >>>>>>> >>>>>>>> *Basic use case 1:* >>>>>>>>>>>> We want to write some properties file and read it from a file or >>>>>>>>>>>> >>>>>>>>>>> the >>>>>>>> >>>>>>>>> classpath into a Configuration instance. This is done by >>>>>>>>>>>> >>>>>>>>>>>> Configuration config = PropertyProviders.fromPaths( >>>>>>>>>>>> >>>>>>>>>>>> "classpath:ucs/UC1ReadProperties/UC1ReadPropertiesTest. >>>>>>>>> properties") >>>>>>>>> >>>>>>>>>> .toConfiguration(); >>>>>>>>>>>> >>>>>>>>>>>> The PropertyProvider which is created here by >>>>>>>>>>>> PropertyProviders.fromPaths hereby >>>>>>>>>>>> is a simplified version that can be easily aggregated (for >>>>>>>>>>>> >>>>>>>>>>> composites) >>>>>>>>> >>>>>>>>>> and >>>>>>>>>>> >>>>>>>>>>>> only provides String values (no type support yet). Nevertheless >>>>>>>>>>>> mapping to Configuration >>>>>>>>>>>> is trivial. >>>>>>>>>>>> >>>>>>>>>>>> Given that we then can access different values. Since we return >>>>>>>>>>>> >>>>>>>>>>> Optional >>>>>>>>>> >>>>>>>>>>> as >>>>>>>>>>> >>>>>>>>>>>> a result type the values returned are never null. For showing the >>>>>>>>>>>> capabilities I added multiple examples of types: >>>>>>>>>>>> >>>>>>>>>>>> String name = config.get("name").orElse("Anatole"); >>>>>>>>>>>> BigDecimal bigNum = config.get("num.BD", BigDecimal.class) >>>>>>>>>>>> .orElseThrow(() -> new >>>>>>>>>>>> IllegalStateException("Sorry")); >>>>>>>>>>>> double anotherNum = config.getDouble("num.Double") >>>>>>>>>>>> >>>>>>>>>>> .getAsDouble(); >>>>>>> >>>>>>>> long longNum = config.getLong("num.Long").orElse(288900L); >>>>>>>>>>>> >>>>>>>>>>>> Finally plugins or modules often only want a view on their subset >>>>>>>>>>>> >>>>>>>>>>> of >>>>>>>> >>>>>>>>> entries. This can be achieved easily by using >>>>>>>>>>>> >>>>>>>>>>>> Configuration areaConfig2 = >>>>>>>>>>>> >>>>>>>>>>> config.with(ConfigFunctions.selectArea("num")); >>>>>>>>>>> >>>>>>>>>>>> This will return a Configuration subset, which will only contain >>>>>>>>>>>> >>>>>>>>>>> the >>>>>>>> >>>>>>>>> child >>>>>>>>>>> >>>>>>>>>>>> values of the num area, which are BD, double, ... ConfigFunctions >>>>>>>>>>>> >>>>>>>>>>> BTW >>>>>>>> >>>>>>>>> is >>>>>>>>>> >>>>>>>>>>> a >>>>>>>>>>> >>>>>>>>>>>> dingleton accessot, which serves >>>>>>>>>>>> ConfigOperator functional extensions (there is also a >>>>>>>>>>>> >>>>>>>>>>> ConfigQuery), >>>>>>> >>>>>>>> so >>>>>>>>> >>>>>>>>>> this >>>>>>>>>>> >>>>>>>>>>>> is a common pattern for adding whatever extension needed to >>>>>>>>>>>> Configuration instances >>>>>>>>>>>> without having them to directly implement/provide on >>>>>>>>>>>> >>>>>>>>>>> Configuration >>>>>>> >>>>>>>> itself. >>>>>>>>>>> >>>>>>>>>>>> All the features are reflected in the test class (in the core >>>>>>>>>>>> >>>>>>>>>>> module): >>>>>>>>> >>>>>>>>>> org.apache.tamaya.uc.UC1ReadProperties.UC1ReadPropertiesTest (we >>>>>>>>>>>> >>>>>>>>>>> should >>>>>>>>>> >>>>>>>>>>> lower case the package name ;) ). >>>>>>>>>>>> >>>>>>>>>>>> This test also contains additional features/use cases... >>>>>>>>>>>> >>>>>>>>>>>> *Extended use case 1.1: multiple formats* >>>>>>>>>>>> It is possible to read multiple file formats, by default the >>>>>>>>>>>> >>>>>>>>>>> following >>>>>>>>> >>>>>>>>>> formats are supported >>>>>>>>>>>> >>>>>>>>>>>> - .properties (as defined by java.util.Properties) >>>>>>>>>>>> - .xml properties (as defined by java.util.Properties) >>>>>>>>>>>> - .ini format >>>>>>>>>>>> >>>>>>>>>>>> Configuration config = PropertyProviders.fromPaths( >>>>>>>>>>>> >>>>>>>>>>>> "classpath:ucs/UC1ReadProperties/UC1ReadPropertiesTest. >>>>>>>>> properties", >>>>>>>>> >>>>>>>>>> "classpath:ucs/UC1ReadProperties/UC1ReadPropertiesTest.xml", >>>>>>>>>>>> "file:c:/temp/myProps.properties") >>>>>>>>>>>> .toConfiguration(); >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> In the back format resolution is handled by an SPI, which is >>>>>>>>>>>> extendable/pluggable. >>>>>>>>>>>> The basic component here ist the ConfigurationFormats singleton >>>>>>>>>>>> >>>>>>>>>>> and >>>>>>> >>>>>>>> the ConfigurationFormat >>>>>>>>>>>> interfaCE. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> *Extended use case 1.2: multiple sources* >>>>>>>>>>>> It is possible to read multiple files, by adding >>>>>>>>>>>> >>>>>>>>>>>> - additional paths (see above) >>>>>>>>>>>> - ant styled expressions >>>>>>>>>>>> >>>>>>>>>>>> Configuration config = PropertyProviders.fromPaths( >>>>>>>>>>>> "classpath:ucs/UC1ReadProperties/UC1ReadPropertiesTest.*", >>>>>>>>>>>> "classpath*:ucs/UC1ReadProperties/**/*.properties") >>>>>>>>>>>> .toConfiguration(); >>>>>>>>>>>> >>>>>>>>>>>> In the back resource resolution is handled by an SPI, which is >>>>>>>>>>>> extendable/pluggable as well. file,file*,classpath,classpath* >>>>>>>>>>>> >>>>>>>>>>> are >>>>>>> >>>>>>>> the >>>>>>>> >>>>>>>>> locator ids which are implemented based on a subset of the >>>>>>>>>>>> >>>>>>>>>>> Spring >>>>>>> >>>>>>>> resource >>>>>>>>>>> >>>>>>>>>>>> loader is working. Additional resource location mechanism could >>>>>>>>>>>> >>>>>>>>>>> be >>>>>>> >>>>>>>> easily added by implementing the >>>>>>>>>>>> org.apache.tamaya.core.internal.resources.PathResolver >>>>>>>>>>>> >>>>>>>>>>> interface. >>>>>>> >>>>>>>> If >>>>>>>> >>>>>>>>> one >>>>>>>>>> >>>>>>>>>>> implements and registers (using the Bootstrap component, by >>>>>>>>>>>> >>>>>>>>>>> default >>>>>>> >>>>>>>> using >>>>>>>>>> >>>>>>>>>>> ServiceLoader), e.g. a resolver called "foo", the expression >>>>>>>>>>>> >>>>>>>>>>> would >>>>>>> >>>>>>>> look >>>>>>>>> >>>>>>>>>> like: >>>>>>>>>>>> >>>>>>>>>>>> Configuration config = PropertyProviders.fromPaths( >>>>>>>>>>>> "foo:myResourceExpression"); >>>>>>>>>>>> >>>>>>>>>>>> Next variants would be reading properties from other resources. >>>>>>>>>>>> >>>>>>>>>>> We >>>>>>> >>>>>>>> could >>>>>>>>>> >>>>>>>>>>> e.g. create a programmatic random resource and also use a >>>>>>>>>>>> >>>>>>>>>>> database, >>>>>>> >>>>>>>> or >>>>>>>>> >>>>>>>>>> remote resource. >>>>>>>>>>>> >>>>>>>>>>>> Cheers, >>>>>>>>>>>> Anatole >>>>>>>>>>>> >>>>>>>>>>>> -- >>>> N Oliver B. Fischer >>>> A Schönhauser Allee 64, 10437 Berlin, Deutschland/Germany >>>> P +49 30 44793251 >>>> M +49 178 7903538 >>>> E [email protected] >>>> S oliver.b.fischer >>>> J [email protected] >>>> X http://xing.to/obf >>>> >>>> >> -- >> N Oliver B. Fischer >> A Schönhauser Allee 64, 10437 Berlin, Deutschland/Germany >> P +49 30 44793251 >> M +49 178 7903538 >> E [email protected] >> S oliver.b.fischer >> J [email protected] >> X http://xing.to/obf >> >>
