2016-09-08 18 views
4

ユーザーが介入せずにプログラムを再起動しようとしています。プログラムでSpring起動アプリケーションを再起動する/ Springコンテキストを更新する

基本的には、アプリケーションのモードを切り替えることができるページがあります(実際には現在アクティブなプロファイルを切り替えることを意味します)。わかっている限り、コンテキストを再起動する必要があります。

context.close() 
    application.setEnvironment(context.environment) 
    ClassUtils.overrideThreadContextClassLoader(application.javaClass.classLoader) 
    context = application.run(*argsArray) 

私がやる瞬間がcontext.close() JVMはすぐに存在するしかし:

現在、私のコードは、それが(これは方法によってKotlinである)だけ再起動ビットのためだ、非常に簡単です。私もcontext.refresh()を試しましたが、それはTomcat/Jettyを殺す(Tomcatの問題の場合にのみ両方を試しました)と思われ、何も起こりません。

私はProgrammatically restart Spring Boot applicationも見たことがありますが、それらの回答から何もうまくいかないようです。さらに、私は、おそらく/restartエンドポイントを持っているスプリングアクチュエータを見ましたが、それはもはや存在しないようですか?

助けていただければ幸いです。ありがとう。

+0

私はちょうど最後の時間春 - クラウドについて何かを読んで、アルリフレッシュし 'リフレッシュendpoint'がありました文脈の中の豆。たぶんあなたはそこに役立つ何かを見つけるでしょう。 [Refresh Scope](http://projects.spring.io/spring-cloud/spring-cloud.html) – Patrick

+0

なぜこのタグは "java"ですか? –

+0

誰かがJavaやKotlinのソリューションを持っているかどうかは気にしなかったので。 Kotlinはこの問題に意義はない。 – Crembo

答えて

4

を作品アレックスのソリューションは、私は2つの追加の依存関係を含めて信じていないにもかかわらず、 (ActuatorおよびCloud Context)を使用すると、1つの操作しか実行できません。代わりに、私は自分の答えを組み合わせて、自分が望むことをするために自分のコードを修正しました。

だからまず重要なnew Thread()setDaemon(false);を使用してコードが実行されます。私は、再起動処理し、次のエンドポイント法います

val restartThread = Thread { 
    logger.info("Restarting...") 
    Thread.sleep(1000) 
    SpringMain.restartToMode(AppMode.valueOf(change.newMode.toUpperCase())) 
    logger.info("Restarting... Done.") 
} 
restartThread.isDaemon = false 
restartThread.start() 

Thread.sleep(1000)は必須ではありませんが、私は出力に私のコントローラ実際にアプリケーションを再起動する前に、表示したいです。contextapplicationは、アプリケーションの起動時にmain方法から来

@Synchronized fun restartToMode(mode: AppMode) { 
    requireNotNull(context) 
    requireNotNull(application) 

    // internal logic to potentially produce a new arguments array 

    // close previous context 
    context.close() 

    // and build new one using the new mode 
    val builder = SpringApplicationBuilder(SpringMain::class.java) 
    application = builder.application() 
    context = builder.build().run(*argsArray) 
} 

val args = ArrayList<String>() 
lateinit var context: ConfigurableApplicationContext 
lateinit var application: SpringApplication 

@Throws(Exception::class) 
@JvmStatic fun main(args: Array<String>) { 
    this.args += args 

    val builder = SpringApplicationBuilder(SpringMain::class.java) 
    application = builder.application() 
    context = builder.build().run(*args) 
} 

私は、これはすべての問題を生成する場合、完全にわからない

SpringMain.restartToModeには、以下があります。もしあれば、私はこの答えを更新します。うまくいけば、これは他人の助けになるだろう。

3

あなたはプログラムで春のブートアプリケーションを再起動する(spring-cloud-context依存関係で)RestartEndPointを使用することができます。

@Autowired 
private RestartEndpoint restartEndpoint; 

... 

Thread restartThread = new Thread(() -> restartEndpoint.restart()); 
restartThread.setDaemon(false); 
restartThread.start(); 

それはそれ、これはメモリリークにつながる可能性があることを通知する例外がスローされますにもかかわらず、動作します:

Webアプリケーション[xyx]が [スレッド6]というスレッドを開始したように見えますが、停止できませんでした。これは、メモリリーク を作成する可能性が非常に高いです。スレッドのスタックトレース:同じ答えが(違った言葉で表現)この他の質問のために提供された

Call Spring actuator /restart endpoint from Spring boot using a java function

+1

あなたの答えは私が必要としていたものではありませんでした。私の自己投稿の答えを見てください。ありがとう。 – Crembo

1

誰かを助けてくれるかもしれない場合は、Cremboの受け入れられた答えのプラーJava翻訳があります。

コントローラ方法:

@GetMapping("/restart") 
void restart() { 
    Thread restartThread = new Thread(() -> { 
     try { 
      Thread.sleep(1000); 
      Main.restart(); 
     } catch (InterruptedException ignored) { 
     } 
    }); 
    restartThread.setDaemon(false); 
    restartThread.start(); 
} 

メインクラス(のみ上位ビット):

private static String[] args; 
private static ConfigurableApplicationContext context; 

public static void main(String[] args) { 
    Main.args = args; 
    Main.context = SpringApplication.run(Main.class, args); 
} 

public static void restart() { 
    // close previous context 
    context.close(); 

    // and build new one 
    Main.context = SpringApplication.run(Main.class, args); 

} 
関連する問題