*A: Basically you can name it builder or whatever. I try to summarize a few
things again*:
1) Previously I could already add additional PropertySource instances
programmatically (on the ConfigurationContext).
2) I stated that, if I get a mechanism to be able to basically configure
the whole ConfigurationContext, I would be able to implement an updater for
changed configurations, since I then can adapt the property sources that
have changed, were removed, or provide additional ones. Now given a clear
requirement for doing this in a thread-safe manner, I proposed to add an
additional ConfigurationContextUpdater, which we agreed, can be a simple
ConfigurationContextBuilder, which creates a new (adapoted) instance of a
ConfigurationContext.
3) Given that new ConfigurationContext, I must be able to apply it, so I
have a control about synchronization that never a inconsistent state
(inconsistgent because of intermediate state within a configuration update
only) is created.
*B: *Alternatively I could also add an more *event-styled update mechanism
to the API, e.g. to the ConfigurationProvider:*
1) The ConfigurationContextChange "event" then must have the following
features at least:
- additional PropertySources (e.g. for new configuration resources
detected)
- PropertySources that were updated (e.g. for changed files detected).
- names of the PropertySources to be removed (e.g. for removed config
files).
We can discuss if we also need the possibility to change filters and the
combination policy during runtime. IMO not necessarily.
Given that all the rest of the event update and config update feature can
be implemented as extension (I already have it running, but still I am
waiting with the commit, so we have enough time to discuss the API part
first).
I wil leave now for some sports and be curious if you guys prefer A or B or
if you see better ways solving this problem...
Cheers,
Anatole
2015-02-26 20:18 GMT+01:00 Mark Struberg <[email protected]>:
> Yes but the builder originally was intentionally left out at all…
>
> LieGrue,
> strub
>
> > Am 26.02.2015 um 11:58 schrieb Anatole Tresch <[email protected]>:
> >
> > Basically only an interface for the ConfigurationContextBuilder. Nothing
> more...
> >
> > -
> > Anatole Tresch
> > Glärnischweg 10
> > 8620 Wetzikon
> > Tel +41 (43) 317 05 30
> > -
> > Send from Mobile
> >
> >> Am 26.02.2015 um 11:07 schrieb Mark Struberg <[email protected]>:
> >>
> >> I smell some kind of overcomplicating things?
> >>
> >> How many classes would that add to our API?
> >> And what is the benefit?
> >>
> >> LieGrue,
> >> strub
> >>
> >>
> >>> Am 24.02.2015 um 14:19 schrieb Anatole Tresch <[email protected]>:
> >>>
> >>> Yes, makes sense, so I would refine my proposal to:
> >>>
> >>> - Create a ConfigurationContextBuilder.
> >>> - We could hereby access a new ConfigurationContextBuilder from the
> >>> ConfigurationProvider.
> >>> - Extend the ConfigurationProvider with the
> switch(ConfigurationContext)
> >>> method.
> >>>
> >>>
> >>>
> >>> 2015-02-24 14:11 GMT+01:00 Romain Manni-Bucau <[email protected]>:
> >>>
> >>>> Hmm
> >>>>
> >>>> Personally I'd prefer a builder (+ a clear lifecycle of the app build
> >>>> phase) and a switch(ConfigContext) method to mutate it at runtime
> >>>> build behing handled by the builder. switch would just be responsible
> >>>> to 1) check the new config if needed, 2) fire the event(s) of the
> >>>> update 3) do the real mutation
> >>>>
> >>>> said otherwise builder extracts the config of the config in its own
> >>>> part and decorelate it from runtime
> >>>>
> >>>> wdyt?
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> Romain Manni-Bucau
> >>>> @rmannibucau
> >>>> http://www.tomitribe.com
> >>>> http://rmannibucau.wordpress.com
> >>>> https://github.com/rmannibucau
> >>>>
> >>>>
> >>>> 2015-02-24 14:01 GMT+01:00 Anatole Tresch <[email protected]>:
> >>>>> See inline...
> >>>>>
> >>>>> 2015-02-24 13:39 GMT+01:00 Romain Manni-Bucau <[email protected]
> >:
> >>>>>
> >>>>>> Ok so ConfigurationContextUpdates is "part of the SPI" thanks to
> >>>>>> ConfigurationContext itself, am I right?
> >>>>> Yep. Also adding property sources already was there...
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>> That said seeing it I really think we should just use a builder
> where
> >>>>>> custom extensions (ServiceLoader in SE, events in CDI, getBeanOfType
> >>>>>> in Spring) can add/remove components during "build" phase.
> >>>>>
> >>>>> The problem is that configuration changes during runtime exactly
> change
> >>>>> these things. E.g.
> >>>>>
> >>>>> - 1)
> >>>>> a file could be removed -> the according propertysource
> >>>>> (
> >>>>> s
> >>>>> )
> >>>>> must be removed.
> >>>>> - 2) a file could be added -> additional property source(s) must be
> >>>>> registered.
> >>>>>
> >>>>> - 3) a file was updated -> coud simply be an update of the
> >>>>> propertysource, but it could also mean that the ordinal has been
> >>>> changed,
> >>>>> so the whole chain must be reordered. In case a file produces entries
> >>>> with
> >>>>> different ordinals, multiple propertysources may be affected,
> mappping
> >>>>> logically to 1 and 2 again.
> >>>>>
> >>>>> So if we agree (and many people want that) that configuration can
> change
> >>>>> during runtime, we must allow this.
> >>>>> If we want to prevent that we can simply never return a
> >>>>> ConfigurationContextUpdate instance, everything will stay read-only.
> >>>>> Breaking things basically is still a question of adding good default
> >>>>> entries. Of course, if someone also removes the defaults, things may
> get
> >>>>> out of order, but I assume this is not a common case...
> >>>>>
> >>>>> Doing everything with a bulder is possible. We would then add
> according
> >>>>> methods
> >>>>>
> >>>>> ConfigurationContextBuilder getBuilder();
> >>>>> void apply(ConfigurationContext context);
> >>>>>
> >>>>> to the ConfigurationContext. WDYT?
> >>>>>
> >>>>>
> >>>>>
> >>>>>> Why I worry about it is this kind of thing:
> >>>>>>
> >>>>>> 1) start a context
> >>>>>> 2) start to use the config
> >>>>>> 3) wow this is awesome
> >>>>>> 4) a part of the app modify it
> >>>>>> 5) oops 2 and 3 are broken
> >>>>>>
> >>>>>> builder creating immutable objects sounds far better to me (by
> itself,
> >>>>>> then you can still mutate sources/converters if that's what you want
> >>>>>> but that's not what we provide)
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> Romain Manni-Bucau
> >>>>>> @rmannibucau
> >>>>>> http://www.tomitribe.com
> >>>>>> http://rmannibucau.wordpress.com
> >>>>>> https://github.com/rmannibucau
> >>>>>>
> >>>>>>
> >>>>>> 2015-02-24 13:24 GMT+01:00 Anatole Tresch <[email protected]>:
> >>>>>>> Hi Roamin
> >>>>>>>
> >>>>>>> not sure, if I get your concerns:
> >>>>>>>
> >>>>>>> - the ConfigurationContext already is part of the current SPI.
> >>>>>>>
> >>>>>>> - the only change is that I extracted the methods for changing the
> >>>>>> context
> >>>>>>> into a separate process step/artifact with a fluent API style to
> have
> >>>>>> more
> >>>>>>> control on changes applied. And I added additional functions, so I
> >>>> also
> >>>>>> can
> >>>>>>> remove PropertySources, and have similar mechanisms for filters and
> >>>> the
> >>>>>>> other aspects. From what I wanted to achieve, currently only
> >>>>>> PropertySource
> >>>>>>> management per se, would be enough. But for me it would look
> somehow
> >>>>>>> weired, if I can change PropertySources, but not the rest...
> >>>>>>>
> >>>>>>> Anatole
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> 2015-02-24 11:57 GMT+01:00 Romain Manni-Bucau <
> [email protected]
> >>>>> :
> >>>>>>>
> >>>>>>>> Hmm
> >>>>>>>>
> >>>>>>>> I have to admit I'm a bit lost, is the SPI useful then? Do we need
> >>>>>>>> another spi? Maybe to start we shouldnt use any spi then move to
> spi
> >>>>>>>> once API is finished
> >>>>>>>>
> >>>>>>>> That said this update new class looks like a builder to get
> context
> >>>>>>>> immutable which sounds more common and easier to understand to me
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> Romain Manni-Bucau
> >>>>>>>> @rmannibucau
> >>>>>>>> http://www.tomitribe.com
> >>>>>>>> http://rmannibucau.wordpress.com
> >>>>>>>> https://github.com/rmannibucau
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> 2015-02-24 10:30 GMT+01:00 Anatole Tresch <[email protected]>:
> >>>>>>>>> Hi all
> >>>>>>>>>
> >>>>>>>>> I would like to propose a small but effective change in the
> >>>>>>>>> ConfigurationContext SPI (the explanation why comes later in this
> >>>>>> email).
> >>>>>>>>> Currently
> >>>>>>>>> it is defined as:
> >>>>>>>>>
> >>>>>>>>> *public interface *ConfigurationContext {
> >>>>>>>>>
> >>>>>>>>> *void *addPropertySources(PropertySource...
> propertySourcesToAdd);
> >>>>>>>>> List<PropertySource> getPropertySources();
> >>>>>>>>> <T> *void *addPropertyConverter(TypeLiteral<T> typeToConvert,
> >>>>>>>>> PropertyConverter<T> propertyConverter);
> >>>>>>>>> <T> List<PropertyConverter<T>>
> getPropertyConverters(TypeLiteral<T>
> >>>>>>>> type);
> >>>>>>>>> List<PropertyFilter> getPropertyFilters();
> >>>>>>>>> PropertyValueCombinationPolicy
> getPropertyValueCombinationPolicy();
> >>>>>>>>>
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> My proposal is add an additional ConfigurationContextUpdates
> >>>>>> interface,
> >>>>>>>>> that allows to apply multiple changes to a ConfigurationContext
> and
> >>>>>>>> finally
> >>>>>>>>> apply the changes, once they are done. So the interface would be
> >>>>>> changed
> >>>>>>>> as
> >>>>>>>>> follows:
> >>>>>>>>>
> >>>>>>>>> *public interface *ConfigurationContext {
> >>>>>>>>>
> >>>>>>>>> List<PropertySource> getPropertySources();
> >>>>>>>>> <T> List<PropertyConverter<T>>
> getPropertyConverters(TypeLiteral<T>
> >>>>>>>> type);
> >>>>>>>>> List<PropertyFilter> getPropertyFilters();
> >>>>>>>>> PropertyValueCombinationPolicy
> getPropertyValueCombinationPolicy();
> >>>>>>>>>
> >>>>>>>>> // moved methods:
> >>>>>>>>> *// void *addPropertySources(PropertySource...
> >>>> propertySourcesToAdd);
> >>>>>>>>> // <T> *void *addPropertyConverter(TypeLiteral<T> typeToConvert,
> >>>>>>>>> // PropertyConverter<T>
> >>>>>> propertyConverter);
> >>>>>>>>> *ConfigurationContextUpdates startUpdate(); // new*
> >>>>>>>>>
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> ConfigurationContextUpdates would be defined as follows:
> >>>>>>>>>
> >>>>>>>>> *public interface *ConfigurationContextUpdates {
> >>>>>>>>>
> >>>>>>>>> ConfigurationContext getContext();
> >>>>>>>>>
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> addPropertySources(PropertySource... propertySourcesToAdd);
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> addPropertySources(Collection<PropertySource>
> >>>> propertySourcesToAdd);
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> removePropertySources(PropertySource... propertySourcesToRemove);
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> removePropertySources(Collection<PropertySource>
> >>>>>>>> propertySourcesToRemove);
> >>>>>>>>> * default *ConfigurationContextUpdates
> >>>>>>>>> removePropertySources(Predicate<PropertySource> selector);
> >>>>>>>>>
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> addPropertyFilters(PropertyFilter... filters);
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> addPropertyFilters(Collection<PropertyFilter> filters);
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> removePropertyFilters(PropertyFilter... filters);
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> removePropertyFilters(Predicate<PropertyFilter> selector);
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> removePropertyFilters(Collection<PropertyFilter> filters);
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> <T> ConfigurationContextUpdates
> >>>>>> addPropertyConverter(TypeLiteral<T>
> >>>>>>>>> typeToConvert,
> >>>>>>>>>
> >>>>>>>>> PropertyConverter<T> propertyConverter);
> >>>>>>>>> *default *ConfigurationContextUpdates
> >>>>>>>>> removePropertyConverters(PropertyConverter<?>... converters);
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> removePropertyConverters(Collection<PropertyConverter<?>>
> >>>> converters);
> >>>>>>>>>
> >>>>>>>>> ConfigurationContextUpdates
> >>>>>>>>> setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy
> >>>>>> policy);
> >>>>>>>>>
> >>>>>>>>> /**
> >>>>>>>>> * Apply all the changes to the underlying context.
> >>>>>>>>> * @throws java.lang.IllegalStateException if the operation is
> >>>>>> called
> >>>>>>>>> multiple times, or another update was already
> >>>>>>>>> * applied before.
> >>>>>>>>> */
> >>>>>>>>> *void *apply();
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> Now here are the reasons, why I think this makes sense:
> >>>>>>>>>
> >>>>>>>>> - it is much more easy to lock/synchronize the current state of
> >>>> a
> >>>>>>>>> ConfigurationContext, since only for the time where the apply()
> >>>> is
> >>>>>>>>> running special synchronization logi
> >>>>>>>>> - a configuration context can not support being mutable at all
> >>>> by
> >>>>>>>> simply
> >>>>>>>>> throwing a UnsupportedMethodException, when startUpdate() is
> >>>>>> called.
> >>>>>>>>> - Changing a ConfigurationContext, e.g. for testing can now be
> >>>> as
> >>>>>>>>> flexible as using CDIUnit for CDI. The regarding test support
> >>>>>>>> flexibility
> >>>>>>>>> is easy to achieve.
> >>>>>>>>> - *But most of all (and that was the reason, why I started to
> >>>>>> think on
> >>>>>>>>> this enhancements), we can implement automatic configuration
> >>>>>> updates,
> >>>>>>>> e.g.
> >>>>>>>>> based on new files added to a configuration directory or added
> >>>> to a
> >>>>>>>>> database table, by implementing the mechanism as part of an
> >>>> "event"
> >>>>>>>> module.
> >>>>>>>>> The event listener can determine from the change event the
> >>>> affected
> >>>>>>>>> PropertySource, compare with the PropertySource already
> >>>> registered
> >>>>>> in
> >>>>>>>> the
> >>>>>>>>> context(s) and remove/add/update new PropertySources as needed
> >>>> for
> >>>>>> the
> >>>>>>>>> affected contexts. *This module currently is in development,
> >>>> and as
> >>>>>>>> soon
> >>>>>>>>> as we would agree on this proposal I can add (and test it
> >>>> before),
> >>>>>> so
> >>>>>>>> we
> >>>>>>>>> have an initial version for supporting configuration updates.
> >>>>>>>>>
> >>>>>>>>> WDYT?
> >>>>>>>>>
> >>>>>>>>> Anatole
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> --
> >>>>>>> *Anatole Tresch*
> >>>>>>> Java Engineer & Architect, JSR Spec Lead
> >>>>>>> Glärnischweg 10
> >>>>>>> CH - 8620 Wetzikon
> >>>>>>>
> >>>>>>> *Switzerland, Europe Zurich, GMT+1*
> >>>>>>> *Twitter: @atsticks*
> >>>>>>> *Blogs: **http://javaremarkables.blogspot.ch/
> >>>>>>> <http://javaremarkables.blogspot.ch/>*
> >>>>>>>
> >>>>>>> *Google: atsticksMobile +41-76 344 62 79*
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> *Anatole Tresch*
> >>>>> Java Engineer & Architect, JSR Spec Lead
> >>>>> Glärnischweg 10
> >>>>> CH - 8620 Wetzikon
> >>>>>
> >>>>> *Switzerland, Europe Zurich, GMT+1*
> >>>>> *Twitter: @atsticks*
> >>>>> *Blogs: **http://javaremarkables.blogspot.ch/
> >>>>> <http://javaremarkables.blogspot.ch/>*
> >>>>>
> >>>>> *Google: atsticksMobile +41-76 344 62 79*
> >>>
> >>>
> >>>
> >>> --
> >>> *Anatole Tresch*
> >>> Java Engineer & Architect, JSR Spec Lead
> >>> Glärnischweg 10
> >>> CH - 8620 Wetzikon
> >>>
> >>> *Switzerland, Europe Zurich, GMT+1*
> >>> *Twitter: @atsticks*
> >>> *Blogs: **http://javaremarkables.blogspot.ch/
> >>> <http://javaremarkables.blogspot.ch/>*
> >>>
> >>> *Google: atsticksMobile +41-76 344 62 79*
> >>
>
>
--
*Anatole Tresch*
Java Engineer & Architect, JSR Spec Lead
Glärnischweg 10
CH - 8620 Wetzikon
*Switzerland, Europe Zurich, GMT+1*
*Twitter: @atsticks*
*Blogs: **http://javaremarkables.blogspot.ch/
<http://javaremarkables.blogspot.ch/>*
*Google: atsticksMobile +41-76 344 62 79*