{"id":20038530,"url":"https://github.com/yahoo/ycb-java","last_synced_at":"2026-03-04T13:32:15.694Z","repository":{"id":53126042,"uuid":"41558540","full_name":"yahoo/ycb-java","owner":"yahoo","description":"YCB Java","archived":false,"fork":false,"pushed_at":"2023-06-16T18:15:06.000Z","size":61,"stargazers_count":27,"open_issues_count":2,"forks_count":14,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-05T06:37:23.369Z","etag":null,"topics":["configuration-loader","ycb"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yahoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-28T16:49:44.000Z","updated_at":"2023-09-08T17:01:03.000Z","dependencies_parsed_at":"2024-11-13T10:40:32.785Z","dependency_job_id":null,"html_url":"https://github.com/yahoo/ycb-java","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yahoo/ycb-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yahoo","download_url":"https://codeload.github.com/yahoo/ycb-java/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yahoo%2Fycb-java/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30081437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T13:22:36.021Z","status":"ssl_error","status_checked_at":"2026-03-04T13:20:45.750Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["configuration-loader","ycb"],"created_at":"2024-11-13T10:29:48.583Z","updated_at":"2026-03-04T13:32:15.662Z","avatar_url":"https://github.com/yahoo.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YCB\n\n[![Build Status](https://travis-ci.org/yahoo/ycb-java.svg?branch=master)](https://travis-ci.org/yahoo/ycb-java)\n\nYCB is a multi-dimensional configuration library that builds bundles from\nresource files describing a variety of values.  The library allows applications\nto configure themselves based on multiple dimensions describing locations,\nlanguages, environments, etc.\n\nThis is a Java port of the [Javascript YCB library](https://github.com/yahoo/ycb).\n\n## Installation\n\nThis projects uses [Maven](http://maven.apache.org/). One can just clone this\nrepository and run `mvn install` (to install in the local Maven repository),\nor `mvn package` (to build the jar library in the target folder).\n\n## Overview\n\nYCB allows applications to specify configurations that change in response to\nspecific environments. But, different than traditional systems in which this\nenvironment is a single dimension (_e.g._ development _vs_ production), YCB\npermits the specification of more orthogonal dimensions. Examples of dimensions\ninclude:\n\n * Device: iPhone, Android, Desktop Browser.\n * Deployment: development, staging, production.\n * Language: en-US, es-ES, pt-BR\n * Location: North America, Asia, Europe\n\nEach of these dimensions has a name (like  \"Language\"), and a set of possible\nvalues (\"en-US\", \"es-ES\", \"pt-BR\"). Also, dimensions can be immutable per\napplication instance (like \"Deployment\"), or change dynamically\nat at different context (like \"Device\" in an HTTP request).\n\nA _realization_ of a set of dimensions is called \"context\", _e.g._ of a context\nfor the previous dimensions specification can be something like:\n\n * Device: Android\n * Deployment: development\n * Language: *\n * Location: Asia\n\nIn this example we illustrated the use of the special value `*` - also \"any\" or\n\"unspecified\" - this means that \"Language\" not specified. This issues the\nselection of default values for when language dimension matters in a\nconfiguration. The case when all dimensions in a contexts are `*` is called \"master\".\n\nDimension values hierarchical, `*` is the root in the value tree (_i.e._ all\nvalues are descendant of `*`), and the user can specify other value hierarchies.\nThe `dimensions.yml` file is the place to specify the dimensions and it's value\ntree, example:\n\n```yaml\n- dimensions:\n    -\n         deployment:\n            development:\n            staging:\n            production:\n              east-coast:\n              west-coast:\n    -\n        user_type:\n            free:\n            premium:\n    -\n        locale:\n            en:\n                en-AU:\n                en-BG:\n            es:\n                es-AR:\n                es-BO:\n```\n\nIn the example `en-AU` is descendant of `en`, this means that all configuration\nthat applies for `en` also applies for `en-AU` - same thing for `west-coast` and\n`production` in `deployment`, for example. The `*` value is implicitly the root\nvalue, so that all configuration that applies to `*`, also applies to all others.\n\nThe way configuration is specified is in YAML or JSON files containing one or\nmore \"bundles\". Each bundle is composed of a context and a delta. The configuration\ndelta get's used if the configuration context matches the bundle contexts, example:\n\n```yaml\n\n# omitted dimensions defaults to \"*\",\n# therefore this is the \"master\"\n- settings: {}\n  feature_x:\n      enabled : false\n      constant_alpha: 0.8\n\n- settings: {user_type: premium}\n  feature_x:\n      enabled: true\n\n- settings: {deployment: development}\n    feature_x:\n      constant_alpha: .99\n```\n\nThis example has three bundles, \"settings\" is a reserved key used to specify the\nbundle's context; everything else is bundle's delta.\n\nThe final configuration (called \"projection\") is a composition from the most\ngeneric to the most specific delta (_i.e._ from the delta that specify dimension\nvalues higher in the value tree to the ones that specify deeper values).\n\nIf the user requests a projection with the \"master\" context, she will get exactly\nthe delta specified in the \"master\" bundle (first one), because no other bundle\nmatches the context.\n\nIf the user requests a projection if `user_type` = `premium`, then YCB will start\nfrom the \"master\" (because is more generic, and matches the contexts,\nbecause `premium` is descendant of `*`), and then apply the second bundle. In\nthis case the `feature_x.enabled` gets overwritten with `true`, so the final\n\"projected\" configuration will be:\n\n```yaml\nfeature_x:\n    enabled : true\n    constant_alpha: 0.8\n```\n\nThis behavior is analogous for when the contexts is `deployment` = `development`.\n\nOn a more complex example, if the context has both `user_type` = `premium` and\n`deployment` = `development`, then YCB will start from master and apply both\nbundles. When the specificity of the context is ambiguous, the the dimension\nis used to disambiguate, by following the order of definition of the dimension.\nIn this case, `environment` was defined first, so the third bundle is applied\nbefore the second one, resulting in the final projected configuration:\n\n```yaml\nfeature_x:\n    enabled : true\n    constant_alpha: 0.99\n```\n\n## API Usage\n\nUsing YCB involves four steps:\n\n 1. Specifying a configuration Loader.\n 2. Loading the (unprojected) configuration into a `Configuration` instance (optionally with a base context).\n 3. Projecting a context to get the final configuration.\n 4. Get values from configuration entries.\n\nTypically, steps 1 and 2 are executed only once in an application, and step 3 can be executed one or more times\n(_i.e._ in a context of a HTTP request), and step 4 is certainly used several times to actually get the values.\n\nCurrently the only Loader implemented is a filesystem Loader, but one can easily add more\nconfiguration Loaders by implementing the Loader interface (PRs welcome!). The following code\nsnippet is an example of usage:\n\n```java\n// Step 1: specify a configuration loader\nURL url = Thread.currentThread().getContextClassLoader().getResource(\"my/config/path\");\nLoader loader =  FileSystemLoader(new File(url.getPath()));\n\n// Step 2: Load the configuration\nConfiguration configuration = Configuration.load(loader);\n\n// Optionally, one can pass a fixed context that should never change\n// (e.g. deployment environment)\nMap\u003cString, String\u003e fixedContext = new HashMap\u003c\u003e();\nfixedContext.put(\"deployment\", \"development\");\nconfiguration = Configuration.load(loader, fixedContext);\n\n// Step 3: Project a configuration using a context\nMap\u003cString, String\u003e context = new HashMap\u003c\u003e();\ncontext.put(\"user_type\", \"premium\");\nConfiguration.Projection projection = configuration.project(context);\n\n// Step 4: Load values (there are several type acessors)\nprojection.getBoolean(\"feature_x.enabled\") // true\n```\n\nPlease check out the unit tests for more comprehensive use cases.\n\n## System Property Override\n\nThe project API accepts a flag in which that the configuration can be override by JVM System\nproperties. That feature is useful if one wants to override specific configuration properties\nin a particular running instance of the application, by simply setting properties in the java\ncommand line (like `java -Dmyapp.foo.bar=10`).\n\n## License\n\nCode licensed under the BSD license.  See LICENSE file for terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahoo%2Fycb-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyahoo%2Fycb-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyahoo%2Fycb-java/lists"}