A library to connect your Java applications to Conqueso. Everything's better... Conqueso.
Conqueso is a central repository for managing dynamic property values for the Archaius library.
The conqueso-java-client serves three purposes:
- Gather and transmit instance metadata about your application to the Conqueso server
- Gather and transmit info about what Archaius dynamic properties are used by your application to the Conqueso server
- Provide an API to query the Conqueso server for property values and instance metadata
You can download the conqueso-java-client binaries from Maven Central.
To add conqueso-java-client to your Maven project, use the following
<dependency>
<groupId>com.rapid7.conqueso</groupId>
<artifactId>conqueso-client-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
The primary purpose of Conqueso is to act as a central repository for managing dynamic property values for the Archaius library. To make use of Conqueso, you should configure Archaius to refer to the Conqueso server as a configuration source:
-Darchaius.configurationSource.additionalUrls=http://<myconquesoserver>/api/roles/<rolename>/properties
<rolename> is the definition of your Java application's role, which will be used to keep your distinct applications' properties separate and group instances of the same application together.
Another important Archaius configuration is the polling interval:
-Darchaius.fixedDelayPollingScheduler.delayMills=<millis>
This setting will determine how frequently your application checks for updates of property values with the Conqueso server. The default frequency if unconfigured is every minute (60000 milliseconds). The Conqueso server will also use this polling frequency to determine when your application instance is no longer checking in with the Conqueso server.
At some point during the startup of your Java application, code should be added to initialize an instance of the ConquesoClient.
The ConquesoClient Initializer supports many configuration options to customize how the connection, instance metadata and Archaius dynamic properties used by your application are specified.
Here's an example with minimal configuration:
ConquesoClient.initializer()
.withConfigurationClasses(AppConfig.class)
.initialize();
Most of the configuration options for the ConquesoClient are based on convention and reasonable defaults, with the option to customize as needed. Let's explore the options for each type of configuration.
By default, the URL to communicate with the Conqueso server is read from the Archaius additionalUrls system property:
-Darchaius.configurationSource.additionalUrls=http://<myconquesoserver>/api/roles/<rolename>/properties
You can override this default using the withConquesoUrl method:
ConquesoClient.initializer()
.withConquesoUrl("http://<anotherconquesoserver>/api/roles/<rolename>/properties")
.withConfigurationClasses(AppConfig.class)
.initialize();
On initialization of the ConquesoClient, instance metadata about your application instance is gathered and transmitted as part of the initial communication with the Conqueso server. This instance metadata is a simple map of String key/value pairs of data that uniquely identifies your instance and can be used to later query the Conqueso server based on metadata values.
By default, the instance metadata is produced by from reading EC2 metadata (if your application is running on AWS EC2) and system properties.
If your application instance is running on AWS EC2, selected values from the Amazon EC2 Metadata are included in the instance metadata:
- ami-id
- instance-id
- instance-type
- local-hostname
- local-ipv4
- public-hostname
- public-ipv4
- availability-zone
- security-groups
See the Amazon EC2 User Guide for more information about Amazon EC2 Metadata.
Instance metadata key/values can be specified as command-line options for your application using Java system properties. All system properties with keys with the prefix conqueso.metadata. will be included in the instance metadata. For example, if your application is launched with:
-Dconqueso.metadata.app.name=reporting-service
the key/value pair app.name=reporting-service will be included in the instance metadata.
Instance metadata can be specified programmatically with the ConquesoClient Initializer. If you want to set all of the metadata values yourself, you can do the following:
Map<String, String> myMetadata = new HashMap<>();
... populate myMetadata
ConquesoClient.initializer()
.withInstanceData(myMetadata)
.withConfigurationClasses(AppConfig.class)
.initialize();
If you want to include the EC2 metadata and system properties values as described above you can do the following:
Map<String, String> myMetadata = new HashMap<>();
... populate myMetadata
InstanceMetadataProvider provider = new CompositeInstanceMetadataProvider(
ConquesoClient.Initializer.createDefaultInstanceDataProvider(),
new CustomInstanceMetadataProvider(myMetadata));
ConquesoClient.initializer()
.withInstanceData(provider)
.withConfigurationClasses(AppConfig.class)
.initialize();
If you don't want metadata about your application instance to be transmitted to the Conqueso server, initialize with the following:
ConquesoClient.initializer()
.skipReportingInstanceData()
.withConfigurationClasses(AppConfig.class)
.initialize();
On initialization of the ConquesoClient, information about the Archaius dynamic properties used by your application is gathered and transmitted as part of the initial communication with the Conqueso server. This is needed to pre-populate the Conqueso server with the property keys, property type and default property values for the application's role.
There are several configuration options available for detecting the properties.
You can tell the ConquesoClient about the classes within your application that contain the Archaius dynamic properties.
ConquesoClient.initializer()
.withConfigurationClasses(AppConfig.class, DbConfig.class, QueueConfig.class)
.initialize();
These classes will be scanned for static field declarations of Archaius types. Any properties found in these classes will be included in the set of properties sent.
public class ExampleConfigClass {
private static final DynamicStringProperty STRING1 =
DynamicPropertyFactory.getInstance().getStringProperty("string1", "foo");
public static final DynamicIntProperty INT1 =
DynamicPropertyFactory.getInstance().getIntProperty("int1", 42);
public static final DynamicStringListProperty STRING_LIST1 =
new DynamicStringListProperty("stringList1", ImmutableList.of("foo", "bar", "baz"));
...
}
You can tell the ConquesoClient to scan your application's classpath for classes containing marker annotations on the type. The marker annotation can be a custom type you specify, or the default @ConquesoConfig
annotation.
ConquesoClient.initializer()
.withConfigurationScan("com.myapp.package1", "com.myapp.package2")
.initialize();
Or with a custom annotation type:
ConquesoClient.initializer()
.withConfigurationScan(Configuration.class, "com.myapp.package1", "com.myapp.package2")
.initialize();
@ConquesoConfig
public class ExampleConfigClass {
private static final DynamicStringProperty STRING1 =
DynamicPropertyFactory.getInstance().getStringProperty("string1", "foo");
public static final DynamicIntProperty INT1 =
DynamicPropertyFactory.getInstance().getIntProperty("int1", 42);
public static final DynamicStringListProperty STRING_LIST1 =
new DynamicStringListProperty("stringList1", ImmutableList.of("foo", "bar", "baz"));
...
}
The classes discovered by this scan will be introspected to find the Archaius properties as described above.
Properties can also be defined in JSON files, specified using the conqueso.properties.jsonUrls system property. The system property value is a comma-separated list of URLS for retrieving the property definition JSON files.
-Dconqueso.properties.jsonUrls=file:/path/to/props1.json,http://path/to/props2.json
The format of the JSON file is as follows:
[
{
"name":"exampleString",
"type":"STRING",
"value":"foo"
},
{
"name":"exampleStringList",
"type":"STRING_LIST",
"value":"foo,bar,baz"
}
]
The values for the type field are defined in the PropertyType enum in the conqueso-client-java artifact. The value field provides the default value for the property (but not necessarily the value returned by the Conqueso server if modified).
The default values of properties are read from the object declarations when introspecting configuration classes and from the JSON file definition as described above. These default values can also be overridden using external Java Properties files, specified by a system property:
-Dconqueso.properties.overridePropertiesUrls=file:/path/to/props1.properties,http://path/to/props2.properties
These properties files will be read and the values of any keys matching already defined properties will override the property's default value. This is useful for dynamically overriding property default values differently at development / test / production time.
The ConquesoClient instance returned by a successful initialization can be used to query the Conqueso server.
The complete set of the current properties value can be retrieved from the Conqueso server, external to the use by any Archaius code.
ConquesoClient client = ConquesoClient.initializer()
.withConfigurationClasses(AppConfig.class)
.initialize();
Properties props = client.getLatestProperties();
conqueso-java-client uses SLF4J (http://www.slf4j.org/) for logging. SLF4J is a facade over logging that allows you to plug in any (or no) logging framework. See the SLF4J website for details.