5

how can I use external configurations within my Spring application?

package hello.example2.Container

import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.client.RestTemplate

@RestController
class ContainerController {
    @RequestMapping("/container/{cid}")
    public list(@PathVariable Integer cid) {
        def template = new RestTemplate();
        def container = template.getForObject("http://localhost:5050/container/" + cid.toString(), Container);
        return container;
    }
}

I want to replace "http://localhost:5050" with a configuration option (f.e. application.yml or application.properties).

This is my application file (Groovy):

package hello.example2

import groovy.transform.CompileStatic
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Configuration

@SpringBootApplication
@Configuration
@EnableAutoConfiguration
@CompileStatic
class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

I tried to set "@Configuration" and "@EnableAutoConfiguration" but to be honest I don't know what they are doing. I'm new to Java/Groovy and the Spring framework (but not to programming in general).

I have read these pages but there is no complete example only snippets:

[1] http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html

[2] https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

codependent
  • 23,193
  • 31
  • 166
  • 308
MonkeyMonkey
  • 826
  • 1
  • 6
  • 19
  • The host will be set when you deploy. You can set the context name and port in application.yml. You need to learn a bit more. Keep reading the documentation. – duffymo Aug 26 '16 at 12:01
  • Yes I need to read and learn more, but at some point you have to start trying things, and that's where I stuck :( – MonkeyMonkey Aug 26 '16 at 12:24

2 Answers2

7

In your configuration file (application.yml or application.properties) add a new entry:

endpointUrl: http://localhost:5050

Then inject that property in your controller:

@RestController
class ContainerController {

    @Value("${endpointUrl}")
    private String ednpointUrl;

    @RequestMapping("/container/{cid}")
    public list(@PathVariable Integer cid) {
        def template = new RestTemplate();
        def container = template.getForObject(endpointUrl+"/container/" + cid.toString(), Container);
        return container;
    }
}
codependent
  • 23,193
  • 31
  • 166
  • 308
  • And where do I have to put my application.yml? I put it under config/application.yml. When I build the project with gradle (`gradle bootRun`) I can't compile because of `[..]/hello/example3/container/ContainerController.groovy: 11: Expected '$endpointUrl' to be an inline constant of type java.lang.String [..]` – MonkeyMonkey Aug 26 '16 at 12:11
  • The application.yml file shoud be under src/main/resources – codependent Aug 26 '16 at 12:17
  • Or more elaborately, your application.yml or application.properties file should be in classpath. – Vinay Prajapati Aug 26 '16 at 12:25
  • I copied application.yml and application.properties files in almost every folder of my project, still receiving the same error - I don't know where this classpath should be – MonkeyMonkey Aug 26 '16 at 12:35
  • @MonkeyMonkey See my answer below. – Vinay Prajapati Aug 26 '16 at 12:59
  • The solution was to use [single quotes](http://stackoverflow.com/questions/5648398/using-value-spring-annotation-with-groovy) => `@Value('${endpointUrl}')` instead of `@Value("${endpointUrl}")` because of Groovy – MonkeyMonkey Aug 26 '16 at 13:06
  • 1
    Or you could have use #{} rather than ${}. – Vinay Prajapati Aug 26 '16 at 13:10
5

Though above answers your question. I'm not that convinced with that. Let me elaborate one by one:

@Configuration: You could have spring configuration set in two ways. a) Using xml file. b) And using Java Configuration class.

To use Java class as configuration file for spring, you need to add @Configuration annotation. In this Configuration class, now you could specify beans using @Bean tag. Specify scope as singleton or prototype using @Scope annotation. And everything you can do using xml configuration file.

Also, a wide community don't like xmls to be used for configurations and hence, they prefer configuring spring in java classes.

@EnableAutoConfiguration: is from springboot framework. It automatically configures conventional or expected configurations which could later be overridden. Basically it wisely configures default beans required by default using different java Configuration classes for different default configurations.

Regarding externalising configuration: You could externalise configuration to application.properties or application.yml. Following should be the location.

  1. A /config subdirectory of the current directory.
  2. The current directory
  3. A classpath /config package
  4. The classpath root

The above are ordered in sequence of their precedence. Hence if config directory is present under current project directory. It would have highest precedence.

Below I am adding a tree diagram of my application. May be this helps.

vinayprajapati@localhost:~/Desktop/project/gradleSpringBoot$ tree
.
├── build.gradle
├── gradleSpringBoot.iml
└── src
    ├── main
    │   ├── groovy
    │   │   └── org.test
    │   │       ├── components
    │   │       │   └── TestComponent.groovy
    │   │       ├── configuration
    │   │       │   └── BaseConfiguration.groovy
    │   │       |
    │   │       └── utils
    │   │           ├── AppConfig.groovy
    │   │           └── AppInfo.groovy
    │   ├── java
    │   │   └── org
    │   │       └── test
    │   │           ├── GradleSpringBootApplication.java
    │   │           └── HelloController.java
    │   └── resources
    │       ├── application-qa.yml
    │       ├── application-uat.yml
    │       ├── application.properties
    │       ├── application.yml
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── org
                └── test
                    └── GradleSpringBootApplicationTests.java

Looks like you are having troubleshooting problem.

Let's do one thing. Put the config file in the resource like in tree diagram above and delete same from all the other places in project. Reason for doing this is that any config file in the root directory or /config subdirectory has higher precedence and hence would override config which is in classpath.

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86
  • Thanks for this great overview. I put my config now under src/main/resources. I think I will come back to `@Configuration` and `@EnableAutoConfiguration` at a later stage of my development. Thank you again! (I dont like XML either) – MonkeyMonkey Aug 26 '16 at 13:08