Skip to content

Examples

Oswaldo Baptista Vicente Junior edited this page Jul 1, 2024 · 31 revisions

Load properties file from classpath (generic way)

This example demonstrates how to load a properties file from the classpath.

ℹ️ Required module confectory-core
☑️ Required version 2.6.0+
flowchart LR
  subgraph Configuration
    direction TB
    subgraph Properties
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  Properties -- 2️⃣ load --> my-application.properties
  u -- 3️⃣ get...(key) --> Configuration
Loading

Suppose you have the following properties file in your classpath (my-app.properties):

web.enable=true
web.host=localhost
web.port=1910
  1. Using the ConfigurationBuilder class, create a new Configuration<?> as follows:
import net.obvj.confectory.*;
...
Configuration<?> config = Configuration.builder()
        .source("my-app.properties"))
        .build();
  1. Use the getters available in the Configuration class to access the loaded properties values by key:
System.out.println(config.getBoolean("web.enable")); // result: true
System.out.println(config.getString("web.host"));    // result: "localhost"
System.out.println(config.getInteger("web.port"));   // result: 1910
🔝 Back to top

Load properties file from classpath (type-safe way)

This example demonstrates how to load a properties file from the classpath.

ℹ️ Required module confectory-core
flowchart LR
  subgraph Configuration
    direction TB
    subgraph Properties
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  Properties -- 2️⃣ load --> my-application.properties
  u -- 3️⃣ get...(key) --> Configuration
Loading

Suppose you have the following properties file in your classpath (my-app.properties):

web.enable=true
web.host=localhost
web.port=1910
  1. Using the ConfigurationBuilder class, create a new Configuration of java.util.Properties, combined with the ClasspathFileSource and the PropertiesMapper:
import java.util.Properties;
import net.obvj.confectory.*;
...
Configuration<Properties> config = new ConfigurationBuilder<Properties>()
        .source(new ClasspathFileSource("my-app.properties"))
        .mapper(new PropertiesMapper())
        .build();
  1. Use the getters available in the Configuration class to access the loaded properties values by key:
System.out.println(config.getBoolean("web.enable")); // result: true
System.out.println(config.getString("web.host"));    // result: "localhost"
System.out.println(config.getInteger("web.port"));   // result: 1910
🔝 Back to top

Load properties file as POJO

This example demonstrates loading a properties file into a POJO (user-defined object).

ℹ️ Required module confectory-core
☑️ Required version 1.2.0+
flowchart LR
  subgraph Configuration
    direction TB
    subgraph MyProperties
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  MyProperties -- 2️⃣ load as POJO --> my-app.properties
  u -- 3️⃣ get() --> Configuration
Loading

Suppose you have the following properties file in your classpath (my-app.properties):

web.host=localhost
web.port=1910

And the following class:

public class MyProperties {
    @Property("web.host") private String host;
    @Property("web.port") private int port;
   // getters and setters omitted
  1. Using the ConfigurationBuilder class, create a new Configuration of MyProperties, combined with the PropertiesToObjectMapper:
Configuration<MyProperties> config = new ConfigurationBuilder<MyProperties>()
        .source(new ClasspathFileSource("my-app.properties"))
        .mapper(new PropertiesToObjectMapper<>(MyProperties.class))
        .build();
  1. Use the getBean() method available in the Configuration class to access the loaded object:
MyProperties myProperties = config.getBean();
🔝 Back to top

Load JSON document from the file system as JSONObject

This example demonstrates how to load a JSON document from a local file in the file system as a JSONObject (json-smart implementation).

ℹ️ Required module confectory-core
flowchart LR
  subgraph Configuration
    direction TB
    subgraph JSONObject
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  JSONObject-- 2️⃣ load --> agents.json
  u-- 3️⃣ get...(jsonpath) --> Configuration
Loading

Suppose you have the following JSON document in the file system (agents.json):

{
  "enabled": true,
  "agents": [
    {
      "class": "Agent1",
      "interval": "*/2 * * * *"
    },
    {
      "class": "Agent2",
      "interval": "10s"
    }
  ]
}
  1. Using the ConfigurationBuilder class, create a new Configuration of net.minidev.json.JSONObject, combined with the FileSource and the JSONObjectMapper:
import net.obvj.confectory.*;
import net.minidev.json.JSONObject;
...
Configuration<JSONObject> config = new ConfigurationBuilder<JSONObject>()
        .source(new FileSource("${HOME}/myapp/myconf.json"))
        .mapper(new JSONObjectMapper())
        .build();
  1. Use the getters available in the Configuration class to access document data using JSONPath expressions:
System.out.println(config.getString("$.agents[?(@.class=='Agent1')].interval")); // result: "*/2 * * * *"
  1. (Optional) Use the getBean() method to access the actual JSONObject parsed by this Configuration:
JSONObject json = config.getBean();
🔝 Back to top

Load JSON document as POJO using Gson

This example demonstrates loading a JSON document into a POJO (user-defined object) using Gson as the mapping provider.

ℹ️ Required module confectory-datamapper-gson
flowchart LR
  subgraph Configuration
    direction TB
    subgraph MyBean
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  MyBean-- 2️⃣ load as POJO --> agents.json
  u-- 3️⃣ get() --> Configuration
Loading

Suppose you have the following JSON document in your classpath (agents.json):

{
  "enabled": true,
  "agents": [
    {
      "class": "Agent1",
      "interval": "*/2 * * * *"
    },
    {
      "class": "Agent2",
      "interval": "10s"
    }
  ]
}

And the following classes:

public class MyBean {
    private boolean enabled;
    private List<Agent> agents;
    // getters and setters omitted
}
...
class Agent {
    @SerializedName("class") // com.google.gson.annotations
    private String clazz;
    private String interval;
    // getters and setters omitted
}
  1. Using the ConfigurationBuilder class, create a new Configuration of MyBean, combined with the GsonJsonToObjectMapper:
Configuration<MyBean> config = new ConfigurationBuilder<MyBean>()
        .source("classpath://agents.json") // dynamic source
        .mapper(new GsonJsonToObjectMapper<>(MyBean.class))
        .build();
  1. Use the getBean() method available in the Configuration class to access the loaded object:
MyBean myBean = config.getBean();
🔝 Back to top

Load XML file from classpath

This example demonstrates how to load an XML document from the classpath and use XPath to query its elements and attributes.

ℹ️ Required module confectory-core
☑️ Required version 2.4.0+
flowchart LR
  subgraph Configuration
    direction TB
    subgraph Document
        direction RL
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  Document-- 2️⃣ load --> agents.xml
  u-- 3️⃣ get...(xpath) --> Configuration
Loading

Suppose you have the following XML file available in your classpath (agents.xml):

<conf>
    <enabled>true</enabled>
    <agents>
        <agent>
            <class>Agent1</class>
            <interval>*/2 * * * *</interval>
        </agent>
        <agent>
            <class>Agent2</class>
            <interval>10s</interval>
        </agent>
    </agents>
</conf>
  1. Using the ConfigurationBuilder class, create a new Configuration of org.w3c.dom.Document with a DocumentMapper:
import org.w3c.dom.Document;
import net.obvj.confectory.*;
...
Configuration<Document> config = new ConfigurationBuilder<Document>()
        .source("classpath://agents.xml")
        .mapper(new DocumentMapper())
        .build();
  1. Use the getters available in the Configuration class to access document data using XPath expressions:
System.out.println(config.getString("/conf/enabled")); // result: true
System.out.println(config.getString("//agents/agent[1]/class")); // result: "Agent1"
System.out.println(config.getString("//agents/agent[class='Agent2']/interval")); // result: "10s"
🔝 Back to top

Load XML from URL as JSONObject

This example demonstrates how to load an XML document from a URL into a JSONObject (json.org reference implementation).

ℹ️ Required module confectory-datamapper-json-org
flowchart LR
  subgraph Configuration
    direction LR
    subgraph JSONObject
        direction TB
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  JSONObject -- 2️⃣ load XML as JSON --> URL
  u -- 3️⃣ get...(jsonpath) --> Configuration
Loading

Suppose you have the following XML document returned by a URL:

<conf>
    <enabled>true</enabled>
    <agents>
        <agent>
            <class>Agent1</class>
            <interval>*/2 * * * *</interval>
        </agent>
        <agent>
            <class>Agent2</class>
            <interval>10s</interval>
        </agent>
    </agents>
</conf>
  1. Using the ConfigurationBuilder class, create a new Configuration of org.json.JSONObject, combined with the URLSource and the JsonOrgXMLToJSONObjectMapper:
import org.json.JSONObject;
import net.obvj.confectory.*;
...
Configuration<JSONObject> config = new ConfigurationBuilder<JSONObject>()
        .source(new URLSource("http://myserver:8080/config"))
        .mapper(new JsonOrgXMLToJSONObjectMapper())
        .build();

Important

Because of differences between XML and JSON formats, the document structure may suffer modifications in this transformation. Find additional details here.

Warning

The generated JSON object may vary depending on the selected Mapper implementation.

  1. If you want to check the parse result, you can print the generated JSONObject:
JSONObject json = config.getBean();
System.out.println(json.toString(2)); // pretty-printed JSON with indentation factor of 2

Note

The JSON generated by this configuration will be as follows:

{"conf": {
  "enabled": true,
  "agents": {"agent": [
    {
      "class": "Agent1",
      "interval": "*/2 * * * *"
    },
    {
      "class": "Agent2",
      "interval": "10s"
    }
  ]}
}}
  1. Use the getters available in the Configuration class to access document data using JSONPath expressions:
System.out.println(config.getString("**.agent[?(@.class=='Agent1')].interval")); // result: "*/2 * * * *"
🔝 Back to top

Load YAML document as JSONObject using SnakeYAML

This example demonstrates how to load a YAML document into a JSONObject.

ℹ️ Required module confectory-datamapper-snakeyaml
flowchart LR
  subgraph Configuration
    direction LR
    subgraph JSONObject
        direction TB
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  JSONObject -- 2️⃣ load as JSON --> person.yaml
  u -- 3️⃣ get...(jsonpath) --> Configuration
Loading

Suppose you have the following YAML document (person.yaml):

firstName: John
lastName: Doe
age: 31
contactDetails:
   - type: mobile
     number: 123456789
   - type: landline
     number: 456786868
  1. Using the ConfigurationBuilder class, create a new Configuration of net.minidev.json.JSONObject (json-smart implementation), combined with the YAMLToJSONObjectMapper:
import net.minidev.json.JSONObject;
import net.obvj.confectory.*;
...
Configuration<JSONObject> config = new ConfigurationBuilder<JSONObject>()
        .source("classpath://person.yaml") // dynamic source
        .mapper(new YAMLToJSONObjectMapper())
        .build();

Tip

Since json-smart's JSONObject extends java.util.HashMap, there is no overhead in converting from SnakeYAML map to this JSON implementation.

  1. If you want to check the parse result, you can print the generated JSONObject:
JSONObject json = config.getBean();
System.out.println(json.toJSONString());

Note

The JSON generated by this configuration will be as follows:

{
  "firstName": "John",
  "lastName": "Doe",
  "contactDetails": [
    {
      "type": "mobile",
      "number": 123456789
    },
    {
      "type": "landline",
      "number": 456786868
    }
  ],
  "age": 31,
}
  1. Use the getters available in the Configuration class to access document data using JSONPath expressions:
System.out.println(config.getString("$.firstName")); // result: "John"
System.out.println(config.getLong("$.contactDetails[?(@.type=='mobile')].number")); // result: 123456789
🔝 Back to top

Load TOML document as JsonNode

This example demonstrates how to load a TOML document into Jackson's JsonNode for queries using JSONPath:

ℹ️ Required module confectory-datamapper-jackson2-toml
flowchart LR
  subgraph Configuration
    direction LR
    subgraph JsonNode
        direction TB
    end
  end
  u([User]) -- 1️⃣ build --> Configuration
  JsonNode -- 2️⃣ load as JSON --> application.toml
  u -- 3️⃣ get...(jsonpath) --> Configuration
Loading

Suppose you have the following TOML document (application.toml):

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000

[servers]
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"
  1. Using the ConfigurationBuilder class, create a new Configuration of JsonNode, combined with the JacksonTOMLToJsonNodeMapper:
import com.fasterxml.jackson.databind.JsonNode;
import net.obvj.confectory.*;
...
Configuration<JsonNode> config = new ConfigurationBuilder<JsonNode>()
        .source("classpath://application.toml") // dynamic source
        .mapper(new JacksonTOMLToJsonNodeMapper())
        .build();
  1. If you want to check the parse result, you can print the generated JSONObject:
JsonNode json = config.getBean();
System.out.println(json.toPrettyString());

Note

The JSON generated by this configuration will be as follows:

{
  "database" : {
    "server" : "192.168.1.1",
    "ports" : [ 8001, 8001, 8002 ],
    "connection_max" : 5000
  },
  "servers" : {
    "alpha" : {
      "ip" : "10.0.0.1",
      "dc" : "eqdc10"
    },
    "beta" : {
      "ip" : "10.0.0.2",
      "dc" : "eqdc10"
    }
  }
}
  1. Use the getters available in the Configuration class to access document data using JSONPath expressions:
System.out.println(config.getString("$.servers.alpha.ip"));   // result: "10.0.0.1"
System.out.println(config.getInteger("$.database.ports[0]")); // result: 8001
🔝 Back to top

Merge two YAML files

This example demonstrates how to merge two YAML configuration sources.

ℹ️ Required module confectory-datamapper-snakeyaml
☑️ Required version 2.2.0+
flowchart LR
  subgraph merged
    direction LR
    subgraph JSONObject
        direction TB
    end
  end
  subgraph config1
    direction LR
    subgraph JSONObject1
        direction TB
    end
  end
  subgraph config2
    direction LR
    subgraph JSONObject2
        direction TB
    end
  end
  JSONObject1-- load as JSON --> config1.yaml
  JSONObject2 -- load as JSON --> config2.yaml
  u([User]) --> merged
  JSONObject -- generated by --> config1
  JSONObject -- generated by --> config2
Loading

Suppose you have the following files:

  • config1.yaml (to have higher precedence)

    agents:
    - class: Agent1
      interval: 1 minute
    - class: Agent2
      interval: 2 minutes
  • config2.yaml (to have lower precedence)

    agents:
    - class: Agent2
      interval: 2 hours
    - class: Agent3
      interval: 3 minutes
  1. Using the ConfigurationBuilder class, create a new Configuration for config1.yaml:
Configuration<JSONObject> config1 = Configuration.<JSONObject>builder()
        .source("classpath://config1.yaml")
        .mapper(new YAMLToJSONObjectMapper())
        .precedence(9)
        .build();
  1. Now build another Configuration for the second file with a lower precedence number:
Configuration<JSONObject> config2 = Configuration.<JSONObject>builder()
        .source("classpath://config2.yaml")
        .mapper(new YAMLToJSONObjectMapper())
        .precedence(1)
        .build();
  1. Merge both Configuration objects, defining a distinct key class to identify each object in the agents list:
Configuration<JSONObject> merged = config1.merge(config2,
                JsonMergeOption.onPath("$.agents").findObjectsIdentifiedBy("class")
                       .thenPickTheHighestPrecedenceOne());

Tip

The merge method accepts an arbitrary number of options.

Note

The JSON generated by the merge operation will be as follows:

{
  "agents": [
    {
      "class": "Agent1",
      "interval": "1 minute"
    },
    {
      "class": "Agent2",
      "interval": "2 minutes"
    },
    {
      "class": "Agent3",
      "interval": "3 minutes"
    }
  ]
}
  1. Use the getters to access document data using JSONPath expressions:
config.getString("$.agents[?(@.class=='Agent1')].interval"); // "1 minute"  (config1.yaml, precedence 9)
config.getString("$.agents[?(@.class=='Agent2')].interval"); // "2 minutes" (config1.yaml, precedence 9)
config.getString("$.agents[?(@.class=='Agent3')].interval"); // "3 minutes" (config2.yaml, precedence 1)
🔝 Back to top