You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tamaya.apache.org by Anatole Tresch <an...@apache.org> on 2014/12/16 13:04:56 UTC

Environment and Stage

Dear all

I want to take up the next topic: the *Environment*. The *Environment
*basically
provides an abstraction to determine the current runtime context. It can
contain data from different *EnvironmentProviderSpi *implementations. In
former versions of Tamaya the environment is additionally also
hierarchical. I personally think, we can omit this complexity. So basically
an *Environment *is a read-only property map:

*public interface* Environment *extends *StageSupplier{

    Optional<String> get(String key);
    *boolean *containsKey(String key);
    Set<String> keySet();
    Map<String,String> toMap();
    *public static *Environment current(){... }
    *public static* Environment root(){... }

}

By default System.getenv() will be mapped into it. Additional
*EnvironmentProviderSpi *providers can add additional context information,
such as:

request.id=23273-864632-834679-546546
ear.id=myEar
application.id=/root/any
tenant.id=companyXY
user_id=companyXYUser
deployment.node.ref=Hsdddsjdsd5673.1
network.zone=DMZ
blueprint=default.pt
...

This SPI (part of core) is defined as follows:

*public interface *EnvironmentProvider {
    *boolean *isActive();
    Map<String,String> getEnvironmentData();
}

Precedence is done by the precedence handling of the *ServiceContext*.

But what are the use cases, where such information is used/necessary

   - 1) the *ConfigProvider *instances needs this information to determine
   the right configuration. E.g. ear.id, application.id, tenant.id can be
   used as key to lookup the target ear/application/tenant specific
   configuration, either locally or remotedly.
   - 2) when config issues occurr the additional info can be added to the
   logging to add more details on the context, where the event/exception
   occurred, especially to know which parts of a system may be affected by
   configuration issues.
   - ...

For simple SE scenarios this might be not needed at all: just read some
config resources from CP and an optional file location and you are done).
But in complex scenarios this abstraction ha proven to be very useful,
since it separates concerns of runtime context detection and configuration
assembly and delivery.
Additionally the *Environment *provides a *Stage *instance (implements
*StageSupplier*), which defines the current stage. But *Stage *could also
be modelled as

   - enum Stage, hereby substages can be modelled by adding additional
   properties to the Environment
   - class Stage
   - or a simple property in the current Environment

Modelling it as interface IMO adds flexibility we don't need.

Additionally to any general feedback, I am especially interested in two
aspects:

1) Should we render *Environment *into a class (and optionally a builder).
I don't see any advantages to model it as interface, because multiple
implementations are not to be expected.
2) How should we model the *Stage*:
  a) not at all, just add an additional property to the environment
  b) add a method returning a String, e.g. in *Environment*, we would
add *String
getStage()*
  c) as an enum, this would allows other components to provide defaults for
all the given
      defaults (similar to JSF stages), but for configuration additional
details for fainer
      granularity can still be added to the Environment.
  d) as an interface (really not recommended)
  e) as an immutable class, e.g. *Stage stg = Stage.of("MyStage"); *and
providing defaults
      like *Stage.DEVELOPMENT*.

WDYT?

-Anatole


​PS: Sideremark: the current code still has the more complicated design. I
wanted to discuss things first before committing this change/simplification
;)​

Re: Environment and Stage

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi

answered inline

2014-12-16 13:04 GMT+01:00 Anatole Tresch <an...@apache.org>:
> Dear all
>
> I want to take up the next topic: the *Environment*. The *Environment
> *basically
> provides an abstraction to determine the current runtime context. It can
> contain data from different *EnvironmentProviderSpi *implementations. In
> former versions of Tamaya the environment is additionally also
> hierarchical. I personally think, we can omit this complexity. So basically
> an *Environment *is a read-only property map:
>
> *public interface* Environment *extends *StageSupplier{
>
>     Optional<String> get(String key);
>     *boolean *containsKey(String key);
>     Set<String> keySet();
>     Map<String,String> toMap();
>     *public static *Environment current(){... }
>     *public static* Environment root(){... }
>
> }
>
> By default System.getenv() will be mapped into it. Additional
> *EnvironmentProviderSpi *providers can add additional context information,
> such as:
>
> request.id=23273-864632-834679-546546
> ear.id=myEar
> application.id=/root/any
> tenant.id=companyXY
> user_id=companyXYUser
> deployment.node.ref=Hsdddsjdsd5673.1
> network.zone=DMZ
> blueprint=default.pt
> ...
>
> This SPI (part of core) is defined as follows:
>
> *public interface *EnvironmentProvider {
>     *boolean *isActive();
>     Map<String,String> getEnvironmentData();
> }
>
> Precedence is done by the precedence handling of the *ServiceContext*.
>
> But what are the use cases, where such information is used/necessary
>
>    - 1) the *ConfigProvider *instances needs this information to determine
>    the right configuration. E.g. ear.id, application.id, tenant.id can be
>    used as key to lookup the target ear/application/tenant specific
>    configuration, either locally or remotedly.
>    - 2) when config issues occurr the additional info can be added to the
>    logging to add more details on the context, where the event/exception
>    occurred, especially to know which parts of a system may be affected by
>    configuration issues.
>    - ...
>
> For simple SE scenarios this might be not needed at all: just read some
> config resources from CP and an optional file location and you are done).
> But in complex scenarios this abstraction ha proven to be very useful,
> since it separates concerns of runtime context detection and configuration
> assembly and delivery.
> Additionally the *Environment *provides a *Stage *instance (implements
> *StageSupplier*), which defines the current stage. But *Stage *could also
> be modelled as
>
>    - enum Stage, hereby substages can be modelled by adding additional
>    properties to the Environment
>    - class Stage
>    - or a simple property in the current Environment
>
> Modelling it as interface IMO adds flexibility we don't need.
>
> Additionally to any general feedback, I am especially interested in two
> aspects:
>
> 1) Should we render *Environment *into a class (and optionally a builder).
> I don't see any advantages to model it as interface, because multiple
> implementations are not to be expected.

You shortcut a bit few things here from my point of view. You say
environment is here to be able to configure the configuration (more or
less) so from my understanding it can be as complicated as all we but
behing a "standard" configuration - even if maybe not recommanded by
default. So interface would make sense to me.

> 2) How should we model the *Stage*:
>   a) not at all, just add an additional property to the environment

+1, if Environment is "abstract" and configuraton locations provided
by the user no need to handle it at all IMO

>   b) add a method returning a String, e.g. in *Environment*, we would
> add *String
> getStage()*
>   c) as an enum, this would allows other components to provide defaults for
> all the given
>       defaults (similar to JSF stages), but for configuration additional
> details for fainer
>       granularity can still be added to the Environment.
>   d) as an interface (really not recommended)
>   e) as an immutable class, e.g. *Stage stg = Stage.of("MyStage"); *and
> providing defaults
>       like *Stage.DEVELOPMENT*.
>
> WDYT?
>
> -Anatole
>
>
> PS: Sideremark: the current code still has the more complicated design. I
> wanted to discuss things first before committing this change/simplification
> ;)