user64752
user64752

Reputation: 411

Reloading/Refreshing Spring configuration file without restarting the servlet container

How can I refresh Spring configuration file without restarting my servlet container?

I am looking for a solution other than JRebel.

Upvotes: 41

Views: 56243

Answers (4)

Dovmo
Dovmo

Reputation: 8749

For those stumbling on this more recently -- the current and modern way to solve this problem is to use Spring Boot's Cloud Config.

Just add the @RefreshScope annotation on your refreshable beans and @EnableConfigServer on your main/configuration.

So, for example, this Controller class:

@RefreshScope
@RestController
class MessageRestController {

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

    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}

Will return the new value of your message String property for the /message endpoint when refresh is invoked on Spring Boot Actuator (via HTTP endpoint or JMX).

See the official Spring Guide for Centralized Configuration example for more implementation details.

Upvotes: 12

Guillaume
Guillaume

Reputation: 5557

Well, it can be useful to perform such a context reload while testing your app.

You can try the refresh method of one of the AbstractRefreshableApplicationContext class: it won't refresh your previously instanciated beans, but next call on the context will return refreshed beans.

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class ReloadSpringContext {

    final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
        "<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\"\n" +
        " \t\"http://www.springframework.org/dtd/spring-beans.dtd\">\n";

    final static String contextA =
        "<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
            "\t\t<constructor-arg value=\"fromContextA\"/>\n" +
        "</bean></beans>";

    final static String contextB =
        "<beans><bean id=\"test\" class=\"java.lang.String\">\n" +
            "\t\t<constructor-arg value=\"fromContextB\"/>\n" +
        "</bean></beans>";

    public static void main(String[] args) throws IOException {
        //create a single context file
        final File contextFile = File.createTempFile("testSpringContext", ".xml");

        //write the first context into it
        FileUtils.writeStringToFile(contextFile, header + contextA);

        //create a spring context
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
            new String[]{contextFile.getPath()}
        );

        //echo the bean 'test' on stdout
        System.out.println(context.getBean("test"));

        //write the second context into it
        FileUtils.writeStringToFile(contextFile, header + contextB);

        //refresh the context
        context.refresh();

        //echo the bean 'test' on stdout
        System.out.println(context.getBean("test"));
    }

}

And you get this result

fromContextA
fromContextB

Another way to achieve this (and maybe a more simple one) is to use the Refreshable Bean feature of Spring 2.5+ With dynamic language (groovy, etc) and spring you can even change your bean behavior. Have a look to the spring reference for dynamic language:

24.3.1.2. Refreshable beans

One of the (if not the) most compelling value adds of the dynamic language support in Spring is the 'refreshable bean' feature.

A refreshable bean is a dynamic-language-backed bean that with a small amount of configuration, a dynamic-language-backed bean can monitor changes in its underlying source file resource, and then reload itself when the dynamic language source file is changed (for example when a developer edits and saves changes to the file on the filesystem).

Upvotes: 11

Rohan S Raju
Rohan S Raju

Reputation: 456

You can take a look at this http://www.wuenschenswert.net/wunschdenken/archives/138 where once you change any thing in the properties file and save it the beans will be reloaded with the new values.

Upvotes: 2

LiorH
LiorH

Reputation: 18824

I wouldn't recommend you to do that. What do you expect to happen to singleton beans which their configuration modified? do you expect all singletons to reload? but some objects may hold references to that singletons.

See this post as well Automatic configuration reinitialization in Spring

Upvotes: 5

Related Questions