com.laamella:parameter-source

Parameter Source

Лицензия

Лицензия

Группа

Группа

com.laamella
Идентификатор

Идентификатор

parameter-source
Последняя версия

Последняя версия

1.0
Дата

Дата

Тип

Тип

jar
Описание

Описание

com.laamella:parameter-source
Parameter Source
Ссылка на сайт

Ссылка на сайт

https://github.com/laamella-gad/parameter-source
Система контроля версий

Система контроля версий

https://github.com/laamella-gad/parameter-source.git

Скачать parameter-source

Как подключить последнюю версию

<!-- https://jarcasting.com/artifacts/com.laamella/parameter-source/ -->
<dependency>
    <groupId>com.laamella</groupId>
    <artifactId>parameter-source</artifactId>
    <version>1.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.laamella/parameter-source/
implementation 'com.laamella:parameter-source:1.0'
// https://jarcasting.com/artifacts/com.laamella/parameter-source/
implementation ("com.laamella:parameter-source:1.0")
'com.laamella:parameter-source:jar:1.0'
<dependency org="com.laamella" name="parameter-source" rev="1.0">
  <artifact name="parameter-source" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.laamella', module='parameter-source', version='1.0')
)
libraryDependencies += "com.laamella" % "parameter-source" % "1.0"
[com.laamella/parameter-source "1.0"]

Зависимости

compile (1)

Идентификатор библиотеки Тип Версия
org.slf4j : slf4j-api jar 1.7.22

test (4)

Идентификатор библиотеки Тип Версия
org.slf4j : slf4j-simple jar 1.7.22
org.mockito : mockito-core jar 2.7.5
junit : junit jar 4.12
com.h2database : h2 jar 1.4.193

Модули Проекта

Данный проект не имеет модулей.

parameter-source

A ¡Laamella Gad! production.

What problem does this solve?

Reading configuration parameters during application startup is often a little messy, leading to unnecessary long debugging times. This tiny library wants to make it a solid experience.

Perceived problems are:

  • sloppy null handling leading to confusing null pointer exceptions down the road
  • sloppy type conversions (string to int, for example) leading to undescriptive errors
  • sloppy file handling when we are dealing with a configuration file leading to undescriptive errors
  • messy API's, different for every source of parameters
  • arcane implementations making unit testing difficult

Offered solutions are:

  • an API that has methods that will either fail hard when a required parameter is missing, or will deliver a Java 8 Optional when the parameter is not required
  • file handling and type conversion work as tight as possible. If a parameter is correct, it will be delivered, otherwise it will throw an exception so that an application does not start in an undefined state.
  • tight support for the kind of values that are often seen as application parameters: strings, durations, urls...
  • one approach to API naming and much reuse, so that parameter sources will look alike as much as possible. Extending a class to define your own source is easy.
  • extensive logging that will show every action.

Adding the dependency

Put this in your pom.xml:

<dependency>
	<groupId>com.laamella</groupId>
	<artifactId>parameter-source</artifactId>
	<version>1.0</version>
</dependency>

Using a properties file as the source

This is the simplest way to start using a properties file as a source of parameters.

PropertiesParameterSource source = new PropertiesParameterSource("application.properties");

Other constructor offer more flexibility.

Using a database as the source

This is the simplest way to start using a database table as a source of parameters, specifying the JDBC database properties and the significant properties of your parameter table.

JdbcDatabaseParameterSource source = new JdbcDatabaseParameterSource("jdbc:h2:mem:db", "user", "passwd", "CONFIGURATION", "KEY", "VALUE");

Other constructor offer more flexibility.

Using Java's Preferences API as the source

This is the simplest way to get access to the Preferences API.

PreferencesParameterSource source = new PreferencesParameterSource();

Please read the Javadoc for some limitations on this implementation.

Using JNDI as the source

This is the simplest way to start using JNDI as a source of parameters.

JndiParameterSource source = new JndiParameterSource();

You may want to pass an InitialContext to the constructor instead.

Using a static parameter source

This stores the key-value pairs in memory and can be used as a fallback for other sources, or for testing.

InMemoryParameterSource source = new InMemoryParameterSource()
    .put("abc", "def")
    .put("ghi", "jkl");

Getting an optional string value

Getters that mention "Optional" in their name are optional. This is implemented with Java 8's Optional class. You can use it to supply a default value.

Optional<String> value = source.getOptionalString("abc");
String value = source.getOptionalString("abc").orElse("myDefaultVal");

Getting a required string value

Getters that do NOT mention "Optional" in their name are required. These will throw a ParameterSourceException when the key is not found.

String value = source.getString("abc");

Getting other values

The pattern described above for string is the same for other types.

The duration format

When requesting a duration, we get the string value for the key, then attempt to parse it as follows:

ISO 8601 inspired:

1D2H3M4S5MS6NS       -> 1 day + 2 hours + 3 minutes + 4 seconds + 5 milliseconds + 6 nanoseconds
1d2h3m4s5ms6ns       -> the same
1d 2h 3m 4s 5ms 6ns  -> the same
1d                   -> 1 day
1 day                -> 1 day
1000ms               -> 1000 milliseconds
3m 10s               -> 3 minutes + 10 seconds
3 minutes 10 seconds -> 3 minutes + 10 seconds

Traditional time format inspired:

12:14:16.1234  -> 12 hours + 14 minutes + 16 seconds + 123.4 milliseconds
14:16          -> 14 minutes + 16 seconds
16             -> 16 seconds

The byte size format

When requesting a size in bytes, we get the string value for the key, then attempt to parse it as follows:

0 -> 0 bytes
10 -> 10 bytes
10 bytes -> 10 bytes
10B -> 10 bytes
10KB -> 10 kilobytes
1 kilobyte 512B -> 1536 bytes

Supported sizes are:

eb exabyte(s)
pb petabyte(s)
tb terabyte(s)
gb gigabyte(s)
mb megabyte(s)
kb kilobyte(s)
b byte(s)

The host and port format

192.168.1.1:8080
192.168.1.1
bla.com:1234
bla.com

The only check is that the value following : is a number.

The enum format

Enums values are case insensitive, and underscores, whitespace, and quotations marks are ignored.

Type conversions in general

The general pattern is:

  1. get the value of the key
  2. is the type of the value of the type that was requested? Return it.
  3. is the type of the value related to the type that was requested? Convert it and return it.
  4. is the type of the value String? Try to parse it, and construct and return the requested type.
  5. fail with a ParameterSourceException

Some requested types may skip step 2 because they have no commonly used type.

So in general, the pattern is to do maximum effort to return a value, but without causing unexpected behaviour.

Reducing repetition in keys

Often keys are (or emulate) a path. For example: properties files use dots as separators, JNDI uses slashes. To avoid having to specify the same paths over and over again, we can make SubParameterSources.

Here is an example for dealing with a good old log4j.properties file:

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
PropertiesParameterSource source = new PropertiesParameterSource("log4j.properties");
SubParameterSource log4j = source.subSource("log4j");
log4j.getString("rootLogger"); // INFO, stdout

SubParameterSource stdoutAppender = log4j.subSource("appender.stdout");
stdoutAppender.getString(""); // org.apache.log4j.ConsoleAppender
stdoutAppender.getString("Target"); // System.out

Chaining sources

Sources can be chained so that parameters that come from different places can be hidden behind a single ParameterSource.

JndiParameterSource jndiParameterSource = new JndiParameterSource();
PropertiesParameterSource propertiesParameterSource = new PropertiesParameterSource("...");

FallbackParameterSource source = jndiParameterSource.withFallback(propertiesParameterSource);

Now source will look in jndiParameterSource first, and if that does not contain the requested key it will look in propertiesParameterSource.

Fallbacks can be chained as much as required.

If you have trouble with different types of keys in these sources, it might help to use "subSource" to set the path so tight that the keys do not need path separators anymore.

Stubbing a source for unit testing

StubParameterSource are meant for testing. These return the contained stub value for every key. Note that conversions will still happen, so storing a string stub value and requesting an integer will try to convert the string to an integer.

Writing your own parameter source

First, extend ParameterSource. Now you will have to choose between overriding getOptionalObject or getOptionalString. If your source is a true object store, meaning that it can store values of any type, override getOptionalObject. If your source is a string store, meaning that it stores only strings, override getOptionalString.

Try to catch any exceptions and wrap them in ParameterSourceExceptions.

If you want to override the handling of a certain type, always override the optional version of the method since the required version always calls the optional one. Consider opening an issue on the github project if you disagree with the default behaviour. Keep to the pattern indicated in "type conversions in general."

The project

As this library is focused on scratching one small itch, it should reach maturity pretty quickly and not require a lot of releases. Issues and PR's are welcome.

com.laamella

Laamella Gad

Версии библиотеки

Версия
1.0
0.4
0.3