Question

i am designing a web service in java where i need to do a sort of AB testing with requests in java.

Basically I'm looking for ways to easily configure parameters which will be dynamically loaded by a request handler to determine the code path based on config values.

for example, let's say i need to get some data either from an external web service or from local DB. i want to have a way to configure parameters(criteria in this context) so that it would determine whether to go fetch data from external web service or from local DB.

if i go with a key-value pair config system above example might produce something like this.

locale=us
percentage=30
browser=firefox

which would mean that i would be fetching data from local DB for 30% of requests from US users whose user-agent is firefox. and i would like this config system to be dynamic so that server does not need to be restarted.

sorry about very high level description but any insights/leads would be appreciated. if this is a topic that is beaten to death in the past, please kindly let me know the links.

Was it helpful?

Solution

I've used this in the past. It is the most common way in java to achieve what you are asking using java.util.Properties:

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

/**
* Class that loads settings from config.properties
* @author Brant Unger
*
*/
public class Settings 
{
public static boolean DEBUG = false; 

/**
 * Load settings from config.properties
 */
public static void load()
{
    try
    {
        Properties appSettings = new Properties();
        FileInputStream fis = new FileInputStream("config.properties"); //put config properties file to buffer
        appSettings.load(fis); //load config.properties file

                   //This is where you add your config variables:
                   DEBUG = Boolean.parseBoolean((String)appSettings.get("DEBUG"));

        fis.close();
        if(DEBUG) System.out.println("Settings file successfuly loaded");

    }
    catch(IOException e)
    {
        System.out.println("Could not load settings file.");
        System.out.println(e.getMessage());
    }
}

}

Then in your main class you can do:

Settings.load(); //Load settings

Then you can check the values of those variables in every other class like:

if (Settings.DEBUG) System.out.println("The debug value is true");

OTHER TIPS

I'm not sure if it helps you, but i usually put config data in some editable file:

file params.ini

vertices 3
n_poly 80
mutation_rate 0.0001f
photo_interval_sec 60
target_file monalisa.jpeg
randomize_start true
min_alpha 20
max_alpha 90

I use this class to load it:

import java.io.*;
import java.util.HashMap;
import java.util.Scanner;

public class Params 
{
 static int VERTICES = 0;
 static int N_POLY = 0;
 static float MUTATION_RATE = 0.0f;
 static int PHOTO_INTERVAL_SEC = 0;
 static String TARGET_FILE;
 static boolean RANDOMIZE_START = false;
 static int MIN_ALPHA = 0;
 static int MAX_ALPHA = 0;
 
 public Params() 
 { 
  Scanner scanner = new Scanner(this.getClass().getResourceAsStream("params.ini")); 
  HashMap<String, String> map = new HashMap<String, String>();
  
  while (scanner.hasNext()) 
  {
   map.put(scanner.next(), scanner.next());
  }
  
  TARGET_FILE = map.get("target_file");
  VERTICES = Integer.parseInt(map.get("vertices"));
  N_POLY = Integer.parseInt(map.get("n_poly"));    
  MUTATION_RATE = Float.parseFloat(map.get("mutation_rate"));
  PHOTO_INTERVAL_SEC = Integer.parseInt(map.get("photo_interval_sec"));
  RANDOMIZE_START = Boolean.parseBoolean(map.get("randomize_start"));
  MIN_ALPHA = Integer.parseInt(map.get("min_alpha"));
  MAX_ALPHA = Integer.parseInt(map.get("max_alpha"));
 }
 
}

Then just load and read:

// call this to load/reload the file
new Params();

// then just read
int vertices = Params.VERTICES;    

Hope it helps!

I've just released an open source solution to this using .yml files, which can be loaded into POJOs, thus creating a nicer solution than a map of properties. In addition, the solution interpolates system properties and environment variables into placeholders:

url: ${database.url}
password: ${database.password}
concurrency: 12

This can be loaded into a Map or better still a Java POJO.

See https://github.com/webcompere/lightweight-config

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top