简体   繁体   中英

Declaring configuration of custom configurable application in java?

So for a hobby project of mine, I would like to create an application that translates an HTTP call and request between two services.

The application does that based on a configuration that can be set by the user. The idea is that the application listens to an incoming API call translates the call and then forwards it.

Then the application waits for a response then translates the response and sends it back to the caller.

A translation can be as simple as renaming a field value in a body object or replace a header field to the body.

I think a translation should begin with mapping the correct URL so here is an example of what I was thinking of a configuration should look like:

    //request mapping
    incoming URL = outgoing URL(
    
        //Rename header value
        header.someobject.renameto = "somevalue"
        
        //Replace body object to header
        body.someobject.replaceto.header
    )

I was thinking that the configuration should be placed in a .txt file and read by the application.

My question is, are there other similar systems that use a configuration file for a configuration like this? And are there other/better ways to declare a configuration?

I have done something sort-of-similar in a different context (generate code from an input specification), so I will provide an outline of what I did to provide some food for thought. I used Config4 * (disclosure: I developed that). If the approach I describe below is of interest to you, then I suggest you read Chapters 2 and 3 of the Config4* Getting Started Guide to get an overview of the Config4* syntax and API. Alternatively, express the concepts below in a different configuration syntax, such as XML.

Config4* is a configuration syntax, and the subset of syntax relevant to this discussion is as follows:

# this is a comment
name1 = "simple value";
name2 = ["a", "list of", "values"];
# a list can be laid out in columns to simulate a table of information
name3 = [
  # item      colour
  #------------------
    "car",    "red",
    "jeans",  "blue",
    "roses",  "red",
];

In a code generator application, I used a table to provide rules to specify how to generate code for assigning values to fields of messages. If no rule was specified for a particular field, then some built-in rules provided default behaviour. The table looked something like the following:

field_rules = [
  # wildcarded message.field    instruction
  #----------------------------------------------------------------
    "Msg1.username",            "@config:username",
    "Msg1.password",            "@config:password",
    "Msg3.price",               "@order:price",
    "*.account",                "@string:foobar",
    "*.secondary_account",      "@ignore",
    "*.heartbeat_interval",     "@expr:_heartbeatInterval * 1000",
    "*.send_timestamp",         "@now",
];

When my code generator wanted to generate code to assign a value to a field, the code generator constructed a string of the form "<message-name>.<field-name>" , for example, Msg3.price . Then it examined the field_rules table line-by-line (starting from the top) to find a line in which the first column matched "<message-name>.<field-name>" . The matching logic permitted * as a wildcard character that could match zero or more characters. (Conveniently, Config4* provides a patternMatch() utility operation that provides this functionality.)

If a match was found, then the value in the instruction column told the code generator what sort of code to generate. (If no match was found, then built-in rules were used, and if none of those applied, then no code was generated for the field.)

Each instruction was a string of the form "@<keyword>:optional,arguments" . That was tokenized to provide the keyword and the optional arguments. The keyword was converted to an enum , and that drove a switch statement for generating code. For example:

  • The @config:username instruction specified that code should be generated to assign the value of the username variable in a runtime configuration file to the field.
  • The @order:price instruction specified that code should be generated to assign the value returned from calling orderObj->getPrice() to the field.
  • The @string:foobar instruction specified the string literal foobar should be assigned to the field.
  • The @expr:_heartbeatInterval * 1000 instruction specified that code should be generated to assign the value of the expression _heartbeatInterval * 1000 to the field.
  • The @ignore instruction specified that no code should be generated to assign a value to the field.
  • The @now instruction specified that code should be generated to assign the current clock time to the field.

I have used the above technique in several projects, and each time I have invented instructions specific to the needs of the particular project. If you decide to use this technique, then obviously you will need to invent instructions to specify runtime translations rather than instructions to generate code. Also, don't feel you have to shoehorn all of your translation-based configuration into a single table. For example, you might use one table to provide a source URL -> destination URL mapping, and a different table to provide instructions for translating fields within messages.

If this technique works as well for you as it has worked for me on my projects, then you will end up with your translation application being an "engine" whose behaviour is driven entirely by a configuration file that, in effect, is a DSL (domain-specific language). That DSL file is likely to be quite compact (less than 100 lines), and will be the part of the application that is visible to users. Because of this, it is worthwhile investing effort to make the DSL as intuitive and easy-to-read/modify as possible, because doing that will make the translation application: (1) user friendly, and (2) easy to document in a user manual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM