When running the native-image from the spring-native rsocket sample in this branch, it fails with this exception:
org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'server.servlet.encoding' to org.springframework.boot.web.servlet.server.Encoding
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:387) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:347) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:324) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:293) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:278) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration.stringHttpMessageConverter(HttpMessageConvertersAutoConfiguration.java:80) ~[rsocket:3.0.0-SNAPSHOT]
at java.lang.reflect.Method.invoke(Method.java:568) ~[rsocket:na]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:281) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.instantiate(AutowiredInstantiationArgumentsResolver.java:360) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.instantiate(AutowiredInstantiationArgumentsResolver.java:332) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveAndInstantiate(AutowiredInstantiationArgumentsResolver.java:195) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveAndInstantiate(AutowiredInstantiationArgumentsResolver.java:177) ~[na:na]
at org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration_StringHttpMessageConverterConfiguration__BeanDefinitions.getStringHttpMessageConverterInstance(HttpMessageConvertersAutoConfiguration_StringHttpMessageConverterConfiguration__BeanDefinitions.java:52) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1223) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1209) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1156) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:566) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:930) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[rsocket:6.0.0-SNAPSHOT]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:735) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:431) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1307) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1296) ~[rsocket:3.0.0-SNAPSHOT]
at com.example.rsocket.RSocketApplication.main(RSocketApplication.java:12) ~[rsocket:0.0.1-SNAPSHOT]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.server.Encoding]: No default constructor found
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:146) ~[na:na]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.create(JavaBeanBinder.java:67) ~[na:na]
at org.springframework.boot.context.properties.bind.Binder.create(Binder.java:369) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.handleBindResult(Binder.java:358) ~[rsocket:3.0.0-SNAPSHOT]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:344) ~[rsocket:3.0.0-SNAPSHOT]
... 30 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.springframework.boot.web.servlet.server.Encoding.<init>()
at java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[rsocket:na]
at java.lang.Class.getDeclaredConstructor(DynamicHub.java:2754) ~[rsocket:na]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141) ~[na:na]
... 34 common frames omitted
Seems there are some hints for the binding missing.
Comment From: wilkinsona
In an app with a ServerProperties bean, I don't think this will occur as we'll already have hints for binding ServerProperties.
Two questions come to mind:
- Why are we using the binder directly rather than
@EnableConfigurationProperties(ServerProperties.class)? - Why is
HttpMessageConvertersAutoConfigurationactive in a pure RSocket app?
Comment From: mhalbritter
To answer the 2nd question:
HttpMessageConvertersAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.http.converter.HttpMessageConverter' (OnClassCondition)
- NoneNestedConditions 0 matched 1 did not; NestedCondition on HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition.ReactiveWebApplication did not find reactive web application classes (HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition)
org.springframework.boot:spring-boot-starter-rsocket uses org.springframework.boot:spring-boot-starter-json, which in turn uses org.springframework:spring-web
Comment From: wilkinsona
I'd like to discuss this with the team. I'm wondering about both tightening up the conditions and possibly switching to using ServerProperties rather than calling the binder manually.
Comment From: mbhave
We discussed this on the team call. We don't use ServerProperties directly due to this issue. Given that, we'd need to add hints for Encoding.
Comment From: wilkinsona
The current conditions also seemed reasonable. In such an app we suspect we will have also configured RestTemplate (which only requires spring-web) and it uses HTTP message converters.
In short, we need to configure a hint specifically for server.servlet.encoding for situations where StringHttpMessageConverterConfiguration is active without a ServerProperties bean.
Comment From: sdeleuze
Impact Spring Cloud Config as well.