{"id":16373077,"url":"https://github.com/bischoffdev/property-aggregator","last_synced_at":"2025-10-26T08:30:22.530Z","repository":{"id":43259067,"uuid":"455614457","full_name":"bischoffdev/property-aggregator","owner":"bischoffdev","description":"Java property management that combines different property sources like system properties, environment variables and multiple properties files into one.","archived":false,"fork":false,"pushed_at":"2023-08-09T09:57:58.000Z","size":125,"stargazers_count":7,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-06T02:08:10.993Z","etag":null,"topics":["hierarchy","java","management","properties"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bischoffdev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-04T16:16:52.000Z","updated_at":"2024-12-09T19:55:03.000Z","dependencies_parsed_at":"2023-01-23T00:30:36.949Z","dependency_job_id":null,"html_url":"https://github.com/bischoffdev/property-aggregator","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bischoffdev%2Fproperty-aggregator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bischoffdev%2Fproperty-aggregator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bischoffdev%2Fproperty-aggregator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bischoffdev%2Fproperty-aggregator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bischoffdev","download_url":"https://codeload.github.com/bischoffdev/property-aggregator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238293198,"owners_count":19448138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hierarchy","java","management","properties"],"created_at":"2024-10-11T03:13:19.062Z","updated_at":"2025-10-26T08:30:22.199Z","avatar_url":"https://github.com/bischoffdev.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white)](https://www.linkedin.com/in/benjamin-bischoff/)\n[![Apache V2 License](http://img.shields.io/badge/license-Apache%20V2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Maven Central](https://img.shields.io/maven-central/v/blog.softwaretester/property-aggregator.svg)](https://repo1.maven.org/maven2/blog/softwaretester/property-aggregator/)\n[![Run Unit Tests](https://github.com/bischoffdev/property-aggregator/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/bischoffdev/property-aggregator/actions/workflows/unit-tests.yml)\n\n![Property Aggregator Logo](logo.png)\n\n# Property Aggregator\n_Simplify Java property handling and create a single source of truth!_\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Property Aggregator](#property-aggregator)\n- [Changelog](#changelog)\n- [Maven dependency](#maven-dependency)\n- [Usage](#usage)\n  - [General usage](#general-usage)\n    - [Building a PropertyAggregator](#building-a-propertyaggregator)\n    - [Retrieving properties](#retrieving-properties)\n  - [Specifying property sources](#specifying-property-sources)\n    - [System properties](#system-properties)\n    - [Environment variables](#environment-variables)\n    - [Properties files](#properties-files)\n      - [Properties file in a fixed path](#properties-file-in-a-fixed-path)\n      - [Properties file in the application's class path](#properties-file-in-the-applications-class-path)\n  - [Specifying property hierarchies](#specifying-property-hierarchies)\n  - [Querying properties](#querying-properties)\n  - [Filtering property keys during the build](#filtering-property-keys-during-the-build)\n  - [Specifying custom filters during the build](#specifying-custom-filters-during-the-build)\n  - [Retrieving subsets of properties from the final list](#retrieving-subsets-of-properties-from-the-final-list)\n  - [Setting default values](#setting-default-values)\n  - [Logging the final properties](#logging-the-final-properties)\n  - [Checking the size of the final properties](#checking-the-size-of-the-final-properties)\n  - [Retrieving all properties](#retrieving-all-properties)\n- [Appendix](#appendix)\n  - [Building](#building)\n  - [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# Property Aggregator\n\nThis project takes care of various properties sources in Java like system and \nenvironment variables as well as properties files. It allows you to specify \nwhich sources override others, filter them and give them default values in order \nto have one single aggregated source of application properties.\n\n# Changelog\n\nAll changes can be seen in the linked [changelog](CHANGELOG.md).\n\n# Maven dependency\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eblog.softwaretester\u003c/groupId\u003e\n    \u003cartifactId\u003eproperty-aggregator\u003c/artifactId\u003e\n    \u003cversion\u003eCheck the version number above\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n# Usage\n\n## General usage\n\n### Building a PropertyAggregator\n\nThe Property Aggregator uses a simple builder pattern to specify property \nsources and options. \n\n```\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withEnvironmentProperties()\n    .withPropertiesFile(\"path/to/Test1.properties\")\n    .build();\n```\n\nThe boolean parameter inside `Builder()` determines if logs should be shown or not.\nThe `false` option can be useful if the PropertyAggregator should be a \"silent part\" of another library.\n\nIn this case,\n\n1. environment properties (aka environment variables) are loaded first\n2. a `Test1.properties` file is loaded which overrides existing properties from the step before\n\nYou can specify multiple sources like this in any order to create your custom \nproperty hierarchies.\n\nWhen the final `build()` method is called, all property sources are combined,\nfilters are applied and default values are set.\n\n### Retrieving properties\n\nTo query for certain properties, use it as shown below:\n\n```\npropertyAggregator.getProperty(\"property1\")\n```\n\n## Specifying property sources\n\n### System properties\n\nTo use system properties as a property source, use the `withSystemProperties()` option:\n\n```\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withSystemProperties()\n    .build();\n```\n\n### Environment variables\n\nTo use environment properties as a property source, use the `withEnvironmentProperties()` option:\n\n```\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withEnvironmentProperties()\n    .build();\n```\n\n### Properties files\n\n#### Properties file in a fixed path\n\nTo use a properties file as a property source, use the `withPropertiesFile()` option:\n\n```\nPropertyAggregator propertyAggregator = \n    new PropertyAggregator.Builder(true)\n    .withPropertiesFile(\"path/to/custom.properties\")\n    .build();\n```\n\n#### Properties file in the application's class path\n\nIf the properties file can be anywhere inside the application's class path, \nuse this method to retrieve them:\n\n```\nPropertyAggregator propertyAggregator = \n    new PropertyAggregator.Builder(true)\n    .withPropertiesFileInClassPath(pathToProperties)\n    .build();\n```\n\n## Specifying property hierarchies\n\nThe power of Property Aggregator is the ability to specify which properties \nhave a higher order than others.\n\nThis enables hierarchies such as:\n\n1. the application's standard _property file_ `application.properties`\n2. this can be overwritten with _system properties_ \n3. this can be overwritten with _environment properties_.\n\nThis example would look like this in code:\n\n```\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withPropertiesFile(\"path/to/application.properties\")\n    .withSystemProperties()\n    .withEnvironmentProperties()\n    .build();\n```\n\nIf properties do not exist in a _higher_ source but only in a _lower_ one, \nthe _lower_ one is added to the final properties. That means that _higher_ \nsources overwrite properties that already exist in a _lower_ one.\n\n## Querying properties\n\nTo retrieve a property value by key, just use\n\n```\nString propertyValue =\n    propertyAggregator.getProperty(\"propertyKey\"));\n```\n\nThis returns the property value from the final processed and filtered set of \nproperties or an appropriate default value if it exists. Otherwise, the \nreturn value will be `null`.\n\n## Filtering property keys during the build\n\nEspecially when using environment properties, they can be quite large and \nnot all of them may be relevant for your application. It is possible to add \na filter in this case to remove all properties whose keys are not required.\n\n```\nList\u003cString\u003e filteredKeys =\n    List.of(\"property1\", \"property2\");\n\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withEnvironmentProperties()\n    .withFilteredKeys(filteredKeys)\n    .build();\n```\n\nHere, all environment properties that are not called \"property1\" or \n\"property2\" are stripped out of the `PropertyAggregator` instance.\n\n__Note:__ The filter is applied when the final `build()` is called on the \n`PropertyAggregator` builder. That means that it is applied after all \nproperty sources are combined.\n\n## Specifying custom filters during the build\n\nIf you want to permanently filter properties in the final list based on \n_custom_ predicates, you can do it like this:\n\n```\nPredicate\u003c? super Map.Entry\u003cString, String\u003e\u003e myAppFilter =\n        (Predicate\u003cMap.Entry\u003cString, String\u003e\u003e) entry -\u003e\n                entry.getKey().startsWith(\"myApp\");\n\nPropertyAggregator propertyAggregator = new PropertyAggregator.Builder(true)\n        .withPropertiesFile(RESOURCES_DIR + \"application.properties\")\n        .withCustomPredicate(myAppFilter)\n        .build();\n```\n\nThis example permanently alters the property list and only keep properties \nwhose key starts with \"myApp\".\n\n__Note:__ It is possible to use `withCustomPredicate` multiple times.\n\n## Retrieving subsets of properties from the final list\n\nIt is possible to get subsets of properties that match custom predicates. \nOne use case for this is having different sets of properties that have to be \npassed on to application plugins.\n\n```\nPredicate\u003c? super Map.Entry\u003cString, String\u003e\u003e filterXProperties =\n    (Predicate\u003cMap.Entry\u003cString, String\u003e\u003e) entry -\u003e\n        entry.getKey().startsWith(\"X\");\n\nProperties properties =\n        propertyAggregator.getPropertiesWithCustomPredicate(filterXProperties);\n```\n\nThis example would return properties that have keys starting with the letter\n\"X\".\n\n## Setting default values\n\nSetting default values can be beneficial if certain properties _must_ exist \nand can optionally be overwritten.\n\n```\nMap\u003cString, String\u003e defaults =\n    Map.of(\"property1\", \"default1\");\n\nPropertyAggregator propertyAggregator =\n    new PropertyAggregator.Builder(true)\n    .withDefaultValues(defaults)\n    .withPropertiesFile(\"path/to/application.properties\")\n    .build();\n```\n\nHere, the key \"property1\" is set with a default value of \"default1\". If any \nof the property sources (in this example a properties file) does not include \n\"property1\", it is added to the final list of properties with the default \nvalue. If, however, \"property1\" __is__ specified in a property source, the \ndefault value is replaced by the actual value. \n\n__Note:__ If you use defaults and filters together, properties with default \nvalues are added to the final set regardless of filters!\n\n## Logging the final properties\n\nIf you want to check the properties after all applied operations, you can \nlog all properties like this:\n\n```\npropertyAggregator.logFinalProperties();\n```\n\n__Note:__ These logs are always shown regardless of the log settings of the builder!\n\n## Checking the size of the final properties\n\nIn order to get the size of processed properties including properties that \nare only specified via default values, use \n\n```\npropertyAggregator.getPropertiesCount()\n```\n\n## Retrieving all properties\n\nThis method returns all processed property keys and values that are set by \nproperty sources or defaults and are not filtered out:\n\n```\npropertyAggregator.getAllProperties()\n```\n\n# Appendix\n\n## Building\n\nProperty Aggregator requires Java \u003e= 11 and Maven \u003e= 3.3.9.\n\nIt is available in [Maven central](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22blog.softwaretester%22%20AND%20a%3A%22property-aggregator%22).\n\n## License\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbischoffdev%2Fproperty-aggregator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbischoffdev%2Fproperty-aggregator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbischoffdev%2Fproperty-aggregator/lists"}