5

I have property file(key/value) pair from where I currently read a value against a key and display that value as it is in the UI .

The complexity have increased,Now the value is more dynamic based on some formula. The formula includes a variable parameter whose value I will get at run time.

Is there any java design pattern to design this scenario .

I was thinking to put a method name in the property file against a key.

Now I will read the key and fetch the method name . This method will calculate the value for that particular key.

Please let me know your suggestion

Programmer
  • 713
  • 1
  • 8
  • 23
  • 2
    The design pattern is "write a parser / tree expression evaluator" ... or "embed an existing expression interpretter". – Stephen C Nov 20 '15 at 08:21
  • You may use usual serialization and this https://en.wikipedia.org/wiki/Reverse_Polish_notation For example: http://stackoverflow.com/questions/1320891/java-rpn-reverse-polish-notation-infix-to-postfix – Alexmelyon Nov 20 '15 at 08:26
  • Solutions like MVEL or spring EL will help you. – Amit Parashar Nov 20 '15 at 08:34
  • @AmitParashar MVEL and EL have serious security issues which maybe fine for his use case but for general user input they are not safe. – Adam Gent Nov 20 '15 at 17:49
  • @AdamGent, Agreed. As long the formula is maintained in a property file, it should be fine. In case the formula is also passed by user input, there is a risk. You must be from OWASP :) – Amit Parashar Nov 20 '15 at 18:08

6 Answers6

1

Is there any java design pattern to design this scenario .

I don't know if there is a pattern.


If I understand your question right I can explain what I do usually.

  • Insert localizable strings in my properties values
    I usually use #number#
  • Replace it later when variables are resolved

Little example:

messages.properties

name.of.key = sum of #0# + #1# = #2#

Then I read the value from and replace the #num# with appropiated values (NOTE: here is in the same method for shortenes, but I use an external replace method):

public void printSum(int n1, int n2) {
    String myString = messageSource("name.of.key", Locale.getDefault(), null, null));
    myString.replace("#0#", String.valueOf(n1));
    myString.replace("#1#", String.valueOf(n2));
    myString.replace("#2#", String.valueOf(n1+n2));
    System.out.println(myString);
}

OUTPUT printSum(1,2);

sum of 1 + 2 = 3
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
1

Use Java built-in JavaScript engine to evaluate expressions. To match the spirit more closely, you can use JSON for properties.

If security is important, you need to provide the class filter. It can be very simple and restrictive as you only need to evaluate trivial expressions. The example on class filter can be found here.

Community
  • 1
  • 1
Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
  • I would hesitate to recommend this solution because it creates a vulnerability to injection attacks. With this change, the developer must now attend to the security of the key,value pairs. – scottb Nov 20 '15 at 16:34
  • It is very easy to restrict the JavaScript if this is an issue. I have edited the question explaining how to do this. – Audrius Meškauskas Nov 20 '15 at 20:03
1

Looks like the ANTLR would make here a great fit.

It is a parser generator. You give it grammar as an input and in return it provides you with a parser.

You can use the parser to transform the textual formula into a parsed tree representation. After that, you can run a visitor to evaluate each of the nodes. You just write some simple function to implement the behavior, such as:

public Double visitAdd(AntlrNode left, AntlrNode right) {
    Double left = visit(left);
    Double right = viist(right);

    return left + right;
}

The grammar is very close to the familiar BNF notation. You just describe how your formula strings are. For example:

formula : left '+' right;
left: Number;
right: Number;
Number: [0-9]+;
Rekin
  • 9,731
  • 2
  • 24
  • 38
0

You can use the strategy pattern putting the method/algorithm name in the property file:

public interface IFormula{
    public int formula(int a, int b);
}
public class Sum implements IFormula{
    public int formula(int a, int b){
        return a+b;
    }
}

Then you can select the method getting the name from a property file:

public static Strategy getStrategy(Name name) {
    switch (name) {
        case SUM:
            return new Sum();
        ...
    }
}
Valerio
  • 110
  • 4
  • Except for the minor issues of operator precedence and parentheses. – user207421 Nov 20 '15 at 09:03
  • This is just one example of the strategy pattern. The question does not specify the formula... – Valerio Nov 20 '15 at 09:17
  • The question is entitled 'Java design pattern to keep a formula in a property file', and you haven't answered it correctly except for trivial cases, and without specifying its limitations. – user207421 Nov 20 '15 at 09:19
  • But now, he fetch the method name from the property file not a formula... Infact he has proposed to insert the method name in the property file – Valerio Nov 20 '15 at 09:24
  • It doesn't make any difference to your answer. The Strategy pattern is not a parsing algorithm, and cannot be used in this situation other than subject to extreme constraints. – user207421 Nov 20 '15 at 09:30
  • @Programmer Is there any java design pattern to design this scenario. – Valerio Nov 20 '15 at 09:35
  • I agree with @Valerio. The question wasn't about parsing, and as long as putting the formula itself into a property value is not a requirement, the strategy pattern will fit nicely. (I would just use the strategy implementation's class name instead of an enum, though.) – Stefan Walter Nov 20 '15 at 11:02
0

Another solution is to refactor your map so that the value type is a functional interface whose method accepts an arbitrary parameter. For example:

@FunctionalInterface
interface ValueType<R> {
    R eval(Object param);
}

This solution (or a variant of it) would enable you to associate a lambda with your keys rather than a fixed value. The performance of a lambda ought to be much better than a run-time parser while still affording you the flexibility to make the associated value depend upon a run-time argument.

This solution should also be less vulnerable to injection attacks than a solution based on run-time parsing.

scottb
  • 9,908
  • 3
  • 40
  • 56
0

Since you seem to want a name for the pattern... the pattern is called: Domain Specific Language.

And again if you want to remain in the realms of abstract patterns and design you can peruse Martin Fowlers discussion on the topic at length.

Needless to say their are a metric ton of tools that solve the above pattern (including some of the answers here).

The other pattern which I highly recommend you NOT do is use a general purpose language that has an evaluator (ie Javascript, EL, Groovy, etc). This generally has security issues and performance issues (of course there are exceptions).

Adam Gent
  • 47,843
  • 23
  • 153
  • 203