user2145488
user2145488

Reputation:

Intellij IDEA and Spring Boot: how to restart only parts of my java code?

I have a complex java spring boot project where one class MyClass has a static attribute that takes 30 seconds to load from the database. MyClass is annotated as @SpringBootApplication and the method

@Bean
public CommandLineRunner demo() {...

is executed when the application is started.

During development, I want to avoid these 30 seconds when I am debugging/correcting other parts of the project that need that static attribute of MyClass.

I want to take profit of the compiler.automake.allow.when.app.running registry setting in Intellij IDEA, so that the changed classes are loaded again via hot swapping.

How can I avoid that MyClass is executed again and again (respectively the whole project is restarted) each time I change somewhere else a class?

Upvotes: 3

Views: 837

Answers (3)

Mark Bramnik
Mark Bramnik

Reputation: 42541

Spring Boot includes something called "devtools" - a jar that you can place in a classpath.

It does a couple of thing during development and gets disabled in production. One of its nifty features is auto restarting. You can read about it here (see section 20.2 it covers these restart capabilities).

At least it is worth knowing that this option exists :)

Upvotes: 1

Mark Bramnik
Mark Bramnik

Reputation: 42541

I'm not aware of this registry setting, I must admit.

However it looks like you restart the application and don't want the heavy class will be loaded again and again.

Well, if you're already using hot-swap - you don't really need to restart the application - just change the code and as long as it don't change method signatures or class definitions (in other words only changes inside the methods are allowed) - you'll be fine - and the application won't be restarted.

Its a JVM's feature, spring or IntelliJ has nothing to do with this.

Now, if you still want to reload (read, restart the process) after the change, and don't want to load the heavy spring bean, there are spring-specific solutions. I'll mention 2 of them:

  1. Use @Lazy bean so that spring won't load the bean unless you'll really need it for running the code. From your explanations it sounds like it could help because you don't need this bean anyway

  2. Provide some mock / in-memory implementation and use Profiles (or @Conditional if you're on spring 4.x) - the same idea around which beans should be actually loaded depending on environment. So for running in "dev" environment a "light-weight" implementation of bean can be loaded, and the real bean can be loaded on production environment.

Upvotes: 0

Avinash
Avinash

Reputation: 4289

You can do the same in spring way using a bean of @RefreshScope

Create a Separate class where the static variable loads the value and don't keep it static.

@Componen
@RefreshScope
public class MyClass {
    private String myRefreshableObject;

    @PostConstruct
    public void init() {
        // set the values of myRefreshableObject
    }

    public void getMyRefreshableObject() {
     return this.myRefreshableObject;
    }
}

Now, whenever you want to reload the bean you have throw a POST request actuator endpoint refresh like below.

curl -d{} http://localhost:8080/refresh

Following Spring Boot dependencies are required here

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Upvotes: 1

Related Questions