web-dev-qa-db-ja.com

組み込みのnettyサーバーがspring-boot-starter-webfluxで起動しないようにするにはどうすればよいですか?

Springsの新しいリアクティブwebflux拡張機能を使用して、クライアントとサーバーアプリケーション間の通信を確立したい。

依存関係の管理にはgradleを使用します。サーバーとクライアント側のbuild.gradleファイルは基本的に次のとおりです。

buildscript {
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT")
    }
}

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
}

apply plugin: 'Java'
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management" 

dependencies {
    compile("org.springframework.boot:spring-boot-starter-webflux")
}

(2.0.0.BUILD -[〜#〜] snapshot [〜#〜]は動くターゲットであり、当面の問題は依存関係内の変更により1日消えます)

サーバー側アプリケーションを起動すると、組み込みのnettyサーバーの起動を含め、すべてがうまく起動します。

ただし、クライアントアプリケーションを起動すると、nettyサーバーも起動し、「Java.net.BindException:Address already in use」が発生します。これは、クライアント側のnettyサーバーがサーバー側のnettyサーバーと同じポートでリッスンするためです。

私の質問は次のとおりですなぜ最初にクライアント側でnettyが開始され、どうすればそれを防ぐことができますか?

Spring-Bootドキュメントによると、SpringはWebサポートが必要かどうかを判断し、それに応じてSpringアプリケーションコンテキストを構成します。

また、ドキュメントによると、これはsetWebEnvironment(false)の呼び出しによってオーバーライドできます。クライアントの起動コードは次のようになります。

@SpringBootApplication(scanBasePackages = { "com.tatics.flux.main" })
public class Client {
    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Client.class);
        app.setWebEnvironment(false);
        app.run(Client.class, args);

        WebClient webClient = WebClient.create();

        Mono<String> result = webClient
                .post()
                .uri("http://localhost:8080/fluxService")

                // This does not work any more: .body("Hallo")
                // and must be replaced by:
                .body(BodyInserters.fromObject("Hallo"))

                .accept(MediaType.TEXT_PLAIN)
                .exchange()
                .flatMap(response -> response.bodyToMono(String.class));
    }
}

残念ながら、nettyはまだ起動しています。また、setWebEnvironment(false)が非推奨としてマークされていることにも注意します。

Nettyが起動しないようにするが、それ以外のすべてのwebflux依存関係を維持する方法についての助けがあれば、高く評価されます。

自動構成レポートからの抜粋を以下に示します。

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------------
...

ReactiveWebServerAutoConfiguration matched:
  - found ReactiveWebApplicationContext (OnWebApplicationCondition)

ReactiveWebServerAutoConfiguration#defaultReactiveWebServerCustomizer matched:
  - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.reactive.DefaultReactiveWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactiveWebServerConfiguration.ReactorNettyAutoConfiguration matched:
  - @ConditionalOnClass found required class 'reactor.ipc.netty.http.server.HttpServer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
  - @ConditionalOnMissingBean (types: org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactorCoreAutoConfiguration matched:
  - @ConditionalOnClass found required classes 'reactor.core.publisher.Mono', 'reactor.core.publisher.Flux'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

...

Negative matches:
-----------------
...
ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.Eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.Apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)

...

ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.Eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.Apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)
14
Frank Kaiser

コードの主な問題は、現在SpringApplicationを作成していて、それをカスタマイズして、最終的にすべてを削除して静的メソッドrun(Object primarySource, String... args)を実行することです。

以下はうまくいくはずです:

@SpringBootApplication
public class Client {

    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Client.class);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
    }

    @Bean
    public CommandLineRunner myCommandLineRunner() {
      return args -> {
        // we have to block here, since command line runners don't
        // consume reactive types and simply return after the execution
        String result = WebClient.create("http://localhost:8080")
                .post()
                .uri("/fluxService")
                .body("Hallo")
                .accept(MediaType.TEXT_PLAIN)
                .retrieve()
                .bodyToMono(String.class)
                .block();
        // print the result?
      };
    }
}

そうでない場合は、--debugフラグを使用してアプリケーションを実行し、自動構成レポートの関連部分、特にサーバーを扱う自動構成を質問に追加してください。

10
Brian Clozel

@Brian_Clozelの回答への追加:

Application.yml内で指定することにより、Netty(またはその他のサーバー)を無効にすることができます:

spring.main.web-application-type: none

またはapplication.properties:

spring.main.web-application-type=none
8
Yan Pak