1

The struts 2 set the struts.ognl.allowStaticMethodAccess to false, for security issues. The static method invocation may be useful in some cases for example when dealing with expression base validators Struts 2 using StringUtils in validator expersions.

One way to solve this problem is to define a helper method in the action, for example, if we want to use Math class we should add below:

public double randomMath(){
  return Math.random();
}


public double asinMath(double a){
  return Math.asin(a);
}

....

And use it as ${randomMath} or ${asinMath(1)}

As you can see for every method in Math class we need to define a public method in our action, with same signature.

Is there a better way to avoid these boilerplate getters?!

Community
  • 1
  • 1
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
  • XY problem. Create custom validator. – Aleksandr M Oct 05 '16 at 16:18
  • Dear @AleksandrM thanks, But in this way I will end up creating *many* non atomic custom validator. As you guess with custom validators I need to remove `@FieldExpressionValidator` and `@ExpressionValidator` and create a custom validator for *every expression*. – Alireza Fattahi Oct 06 '16 at 05:16
  • What do you mean by non atomic? Testability. If you have complex conditions in your validators, then how do you test it? Putting it inside custom validator gives you the ability to unit test it. You don't have to create custom validators for each expression only for complex ones. And you can create some more general validator and control it with parameters. – Aleksandr M Oct 06 '16 at 15:13

1 Answers1

1

OGNL allows execution of methods, but the static access is disabled by default, so you cannot use static method in expressions. However, you can teach OGNL which classes needs to access the static methods.

OGNL developer guide: Method Accessors

Method calls are another area where OGNL needs to do lookups for methods based on dynamic information. The MethodAccessor interface provides a hook into how OGNL calls a method. When a static or instance method is requested the implementor of this interface is called to actually execute the method.

public interface MethodAccessor
{

    Object callStaticMethod( Map context, Class targetClass, String methodName, List args )
        throws MethodFailedException;

    Object callMethod( Map context, Object target, String methodName, List args )
        throws MethodFailedException;

}

You can set a method accessor on a class-by-class basis using OgnlRuntime.setMethodAccessor(). The is a default method accessor for Object (which simply finds an appropriate method based on method name and argument types and uses reflection to call the method).


You can code something

public class StringUtil extends StringUtils implements MethodAccessor {
  //implement above methods
}  

Action class

public static final String MESSAGE = "hello.message";

/**
 * Field for Message property.
 */
private String message;

/**
 * Return Message property.
 *
 * @return Message property
 */
public String getMessage() {
    return message;
}
private StringUtil stringUtil = new StringUtil();

public StringUtil getStringUtil() {
  return stringUtil;
}

public String execute() throws Exception {
    setMessage(getText(MESSAGE));
    OgnlRuntime.setMethodAccessor(StringUtil.class, stringUtil);
    return SUCCESS;
}

In JSP

<s:if test="!stringUtil.isEmpty(message)">
  <h2><s:property value="message"/></h2>
</s:if>

Roman C
  • 49,761
  • 33
  • 66
  • 176
  • 1
    Why this is better than `struts.ognl.allowStaticMethodAccess`? – Aleksandr M Oct 07 '16 at 18:52
  • What about xml validation? There no sign of it in your post. – Aleksandr M Oct 07 '16 at 18:52
  • @AleksandrM `struts.ognl.allowStaticMethodAccess` isn't used by this code. – Roman C Oct 07 '16 at 18:55
  • Exactly. But why this method is better than `struts.ognl.allowStaticMethodAccess`? What do you think `struts.ognl.allowStaticMethodAccess` do? – Aleksandr M Oct 07 '16 at 18:56
  • @AleksandrM You don't understand OP's question, better means not `struts.ognl.allowStaticMethodAccess` but without writing manually all that delegate methods to the static methods that doesn't work with `struts.ognl.allowStaticMethodAccess` is false. – Roman C Oct 07 '16 at 19:00
  • @AleksandrM You also don't understand the context of the OP's question. It doesn't matter where such OGNL expressions are used in the tags, validators, configuration, text, etc. If `struts.ognl.allowStaticMethodAccess` is `false` the expression that requires static access doesn't work. In my answer it works. – Roman C Oct 07 '16 at 19:05
  • @AleksandrM *Do you know what that config line do?* is *not* the question about. – Roman C Oct 07 '16 at 19:12
  • @AleksandrM What *answers* are you talking? If you don't like my answers write yours, what's the problem? – Roman C Oct 07 '16 at 19:23
  • @RomanC exactly what I was looking for. With this way I can call static method where I need it, without generally setting `allowStaticMethodAccess` to `true`. Mean while there will be no use to define one `getter` per each `static method`. – Alireza Fattahi Oct 08 '16 at 06:14