4

I want to evaluate the OS (operating system) system property to load the environment corresponding configuration file. E.g. if OS evaluates to Windows, the properties-win.xml will be loaded or if OS evaluates to Unix or Linux, the properties-unix.xml will be loaded.

The below spel works fine

#{(systemProperties['os.name'].indexOf('nix') >= 0 or systemProperties['os.name'].indexOf('nux') >= 0 or systemProperties['os.name'].indexOf('aix') > 0 ) ? 'linux' : 
        ((systemProperties['os.name'].indexOf('Win') >= 0) ? 'windows' : 'Unknow OS')}

But in place of evaluating the systemProperties['os.name'] each time, I want to have this in a variable and then wants to match the condition. I saw the #this variable usage (http://docs.spring.io/spring-framework/docs/3.0.6.RELEASE/spring-framework-reference/html/expressions.html sec 6.5.10.1) and tried to make the below spel

#{systemProperties['os.name'].?((#this.indexOf('nix') >= 0 or #this.indexOf('nux') >= 0 or #this.indexOf('aix') > 0 ) ? 'unix' : 
    (#this.indexOf('win') >= 0) ? 'windows' : 'Unknown')}

But somehow, it's giving parsing exception.

Does anyone can suggest anything?

dertkw
  • 7,798
  • 5
  • 37
  • 45
ashishgupta_mca
  • 578
  • 6
  • 27
  • You could use the `@Value` annotation on a variable in a `@Component` to store the value of your first (working) expression. Or did I misunderstand your intent? – Uwe Allner Apr 29 '14 at 06:33
  • My question is to create the spel to have a variable support for matching a criteria(see second bold text). – ashishgupta_mca Apr 29 '14 at 06:40
  • You want to set and use a variable within the Spel? Am I correct? This is not possible as such, as far as I know. Variables have to be set to the context. You could do as `context.setVariable("os", SystemProperties.getProperty("os.name"));` and then use it in your Spel as #os. – Uwe Allner Apr 29 '14 at 07:05
  • You are right. Yep, I saw the context usage but was wondering if it can be set directly through 'this' usage. Anyway, thanks for your tip. – ashishgupta_mca Apr 29 '14 at 07:20

3 Answers3

8

How about this approach, a more elegant one, I would say. Requires Spring 4.

public class WindowsEnvironmentCondition implements Condition {
     public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
          return context.getEnvironment().getProperty("os.name").indexOf("Win") >= 0;
     }
}

public class LinuxEnvironmentCondition implements Condition {
     public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
          return (context.getEnvironment().getProperty("os.name").indexOf("nux") >= 0 
                 || context.getEnvironment().getProperty("os.name").indexOf("aix") >= 0);
     }
}

And then you can use the Conditions above to annotate the desired methods or classes to be loaded depending on the environment:

@Configuration
@Conditional(LinuxEnvironmentCondition.class)
@ImportResource("classpath:/META-INF/spring/linux.xml")
public class LinuxConfig {

private @Value("${test}") String message;

public @Bean
ExampleService service() {
    ExampleService service = new ExampleService();
    service.setMessage(message);
    return service;
}
}

@Configuration
@Conditional(WindowsEnvironmentCondition.class)
@ImportResource("classpath:/META-INF/spring/windows.xml")
public class WindowsConfig {

private @Value("${test}") String message;

public @Bean
ExampleService service() {
    ExampleService service = new ExampleService();
    service.setMessage(message);
    return service;
}
}

linux.xml:

<context:property-placeholder location="classpath:/META-INF/spring/linux.properties" />

windows.xml:

<context:property-placeholder location="classpath:/META-INF/spring/windows.properties" />

Maybe it can be enhanced more, but just wanted to show you another idea of using certain xml files depending on the OS.

Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89
2

It is not possible to set a variable within a Spel expression. Variables have to be set to the context. You could do as

context.setVariable("os", SystemProperties.getProperty("os.name")); 

and then use it in your Spel as #os

Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
0

For future searchs, follows the other alternative:

root:
  pathLinux: ${ROOT_PATH_LINUX:/mnt/data/}
  pathWindows: ${ROOT_PATH_WINDOWS:F:/data/}
  path: "${ROOT_PATH:#{systemProperties['os.name'].toLowerCase().contains(\"windows\") ? \"${root.pathWindows}\" : \"${root.pathLinux}\" }}"

In case, it's possible overrides the configuration using the ROOT_PATH environment variable yet, or ROOT_PATH_LINUX, or ROOT_PATH_WINDOWS, OS specific vars.

rafaelnaskar
  • 619
  • 6
  • 11