Skip to content
logoBack to home screen

Property Lookups

Property lookups are a normalized way to access named string values as you find them in simple property accessors like

Using such lookups directly implies the following cross cutting concerns:

  • referential integrity
  • mandatory checks
  • defaulting
  • validation
  • type-safe parsing
  • decryption

To cover those cross cutting concerns, property lookups provide a generic implementation that enhances the actual lookup by generating implementations based on the Java Proxy Feature and a declaration of properties - provided by the user - with the following Java principles:

Property Access Interfaces

Property access interfaces define accessible type-safe properties by method declarations.

The signatures of those methods are very restricted to be for property access. The name of the method defines the name of the property, while its return type defines the type to which an automatic conversion from the given string value happens.

Optionally, a method can be parameterized with a single parameter whose type must be equal to the method's return type. This parameter serves as a user defined default value. Furthermore, the method can be annotated to control additional features of property access.

As property access interfaces have no method bodies they serve as inventories of property expectations of some software component as they act as a central place to define properties. You can also get an overview of all the properties and document them in the same place.

The following example shows different cases:

public interface XyzProperties extends PropertyLookupContract {

    // Simplest case of a property with a primitive
    // that implies the default value false
    boolean PARALLEL_PROCESSING();

    // The @Default annotation defines 5 as the default value
    // which is used if there is no explicit value given
    @Default("5")
    int MAX_DB_CONNECTIONS();

    // The accessor has to supply a default value
    // that is used if there is no explicit value given
    String HOST_NAME(String defaultHostName);

    // The property value has to be given explicitly
    @Required
    Duration CHECK_INTERVAL();

    // The @Name annotation defines the actual property name. Use it if a java method identifier would be invalid because of e.g. special characters.
    @Name("CHECK-VALIDITY")
    String checkValidity();

    // An example for a collection property
    List<File> MAPPING_FILES();
}

Supported Property Types

Properties can have one of the supported base types or collection types.

Base Types

TypeImplicit DefaultString Format
Boolean / booleanfalsetrue | false
Character / char'\u0000'A | b | 1 | ...
Byte / byte0255
Short / short04711
Integer / int04711
Long / long04711
Float / float0.03.141592
Double / double0.03.141592
BigDecimal0.03.141592
Stringnullsome text
Datenullyyyy-MM-dd['T'HH[:mm[:ss[.SSS]]]][Z] | yyyyMMdd['T'HH[mm[ss[SSS]]]][Z]
DurationnullP[nD]T[nH][nM][n.nS]
Filenullsome/path/to/a/file.txt
Pathnullsome/path/to/a/file.txt
Classnullfoo.bar.SomeClass
EnumnullENUM_CONSTANT

Collection Types

Collection types use delimiters in their patterns to separate elements, keys and values from each other. If you want to use these delimiters, take care of proper url escaping.

TypePattern
Listvalue1,value2,...
Setvalue1,value2,...
Mapkey1=value1,key2=value2,...

Supported Annotations

TypeDescription
@RequiredDefines that a property is mandatory. If the actual lookup has no value given, an IllegalStateException is thrown
@DefaultDefines a default value for a property in its string representation in case the actual lookup has no value.
@NameDefines the name of the accessed property. This overrides the default behavior that the name of the accessor method defines the property name.
@DecryptDefines that the property value should be decrypted with a parameterized algorithm. This allows to avoid direct exposure of confidential information on screen when editing or viewing property assignments.

Usage Example

In order to create and access a lookup implementation with all cross cutting concerns see following example which uses the example interface and standard java system environment variables as actual lookup:

public class Main {

    public static void main(String args[]) {

        // create a custom property access implementation
        XyzProperties properties = PropertyLookups.create(
            // use the property access interface
            XyzProperties.class,
            // use System.getenv() function as actual backend lookup
            System::getenv
        );

        // access one property with referential integrity and type-safety
        if (properties.PARALLEL_PROCESSING())
            System.out.println("Parallel processing is active");
    }

}