Connect to Azure KeyVault using K8s ConfigMap and Spring Boot - spring-boot

I have a configmap created in my AKS with these properties
config-application-dev.properties: |
server.port=5001
server.compression.enabled=true
azure.keyvault.uri=<URL>
azure.keyvault.client-id=<CLIENTID>
azure.keyvault.client-key=<CLIENTKEY>
My Spring boot application read those properties using #PropertySource
#PropertySource({ "${propertiesDir}/${envTarget}/config/config-application-${envTarget}.properties" })
public class Application{
...
}
And I want to read the Key using #Value property
#Value("${azure-key-vault-secret}")
private String mySecretProperty;
But, when SpringBoot starts, It throws this error message ...
It can't resolve the placeholder ...
the connection to azure is not working ?
2019-08-21 16:17:26.051 WARN 1 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'exampleController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'secret-in-keyvault' in value "${secret-in-keyvault}"

Related

Spring tries to initialize AutoConfiguration beans using default constructor

We are having issues starting up our Spring Boot Web application. The main problem to properly diagnose the startup is that it only seems to happen in 1% of the startups. In 99% of the startup procedures all works fine and we end up having a properly working spring boot application. However in those 1% of those cases we see issues like this:
WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'errorPageFilterRegistration' defined in org.springframework.boot.web.servlet.support.Error
PageFilterConfiguration: Unsatisfied dependency expressed through method 'errorPageFilterRegistration' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorPageFilter' defined in org.springframework.boot.web.servlet.support.ErrorPageFilterConfiguration: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.spring
framework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigu
re.web.servlet.error.ErrorMvcAutoConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.<init>() []
For some reason it tries to initialize AutoConfiguration beans by using a default constructor which obviously is not present. There is a constructor present which should be autowired.
Also the AutoConfiguration that is in the stacktrace can be different. Sometimes it is another one like e.g. org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
Any help or ideas on why this could be happening is appreciated. As this happens very occasionally this is hard to debug as we cannot relyably reproduce. Note that the stacktrace does not contain any custom code. Our application is quite big and we rely mostly on #Configuration classes to do configure the Beans.
Why would spring attempt to initialize an AutoConfiguration bean with a default constructor ?
The errorPageFilterConfiguration source of spring looks like this:
#Configuration(proxyBeanMethods = false)
class ErrorPageFilterConfiguration {
#Bean
ErrorPageFilter errorPageFilter() {
return new ErrorPageFilter();
}
#Bean
FilterRegistrationBean<ErrorPageFilter> errorPageFilterRegistration(ErrorPageFilter filter) {
FilterRegistrationBean<ErrorPageFilter> registration = new FilterRegistrationBean<>(filter);
registration.setOrder(filter.getOrder());
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return registration;
}
}
According to the stack on creation of the errorPageFilter it is initializing the ErrorMvcAutoConfiguration as a prerequisite ? Why ?
We are not initializing these beans manually. The only relevant code for error page handling that we have is this following:
#Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> webServerFactoryCustomizer() {
return webServerFactory -> {
ErrorPage errorPage = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error");
webServerFactory.addErrorPages(errorPage);
};
}
This is a bug in Spring framework, introduced in version 5.3 in AbstractBeanFactory.
BeanPostProcessorCacheAwareList and accesses to the beanPostProcessors instance are not Thread safe. If multiple Threads are running during initialization and a Thread calls getBeanPostProcessorCache() while another Thread is calling addBeanPostProcessors, you can create a cache which does not contain all BeanPostProcessor instances and thus doesn't find the appropriate constructor.
I will submit a bug for this to spring-framework.
https://github.com/spring-projects/spring-framework/blob/16ea4692bab551800b9ba994ac08099e8acfd6cd/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java#L964
Issue created : https://github.com/spring-projects/spring-framework/issues/29299

Why creating been in Spring occurs with error?

Hello I am creating program which will communicate and send information using channel. When I run program it doesn't work.
Errors:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-02 13:47:37.938 ERROR 12584 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloWorldQueueProducer' defined in file [C:\workspace\target\classes\edu\producer\HelloWorldQueueProducer.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jmsTemplate' defined in class path resource [org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration$JmsTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'jmsTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryConfiguration$SimpleConnectionFactoryConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.connection.CachingConnectionFactory]: Factory method 'cachingJmsConnectionFactory' threw exception; nested exception is java.lang.IllegalStateException: Unable to create ActiveMQConnectionFactory
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.5.jar:5.3.5]
#Component
#RequiredArgsConstructor
public class HelloWorldQueueProducer {
private final JmsTemplate jmsTemplate;
#Scheduled(fixedRate = 2000)
public void sendHello() {
HelloMessage message = HelloMessage.builder()
.id(HelloMessage.nextId())
.createdAt(LocalDateTime.now())
.message("Hello world!")
.build();
jmsTemplate.convertAndSend(JmsConfig.QUEUE_HELLO_WORLD, message);
System.out.println("HelloWorldQueueProducer.sendHello - sent message: " + message);
}
}
Not quite sure about it, but have you defined the necessary properties in your application.properties? You need to set them like this i. e.
spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=developer
spring.artemis.password=developer
jms.queue.destination=myqueue
Otherwise the autoconfiguration of spring boot wouldn't bootstrap the necessary beans. I had this problem once.

Run Spring Boot Application With Dev Configuration Or Test Configuration

I have some multi-environment configurations.
The application.yml is like
spring:
profiles:
active: #profileActive#
The application-dev.yml is like
server:
port: 8085
spring:
application:
name: xxxx-info
datasource:
name: xxx-db
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.1.14:3306/xxx
username: root
password: *******
driver-class-name: com.mysql.jdbc.Driver
minIdle: 1
maxActive: 8
initialSize : 1
testWhileIdle: true
mybatis:
typeAliasesPackage: com.xxx.commons.common.entity
mapperLocations: classpath:mybatis/*.xml
And the application-test.yml is the same as application-dev.yml.
Application.java is like
#EnableDiscoveryClient
#SpringBootApplication
#EnableEurekaClient
#EnableFeignClients
#MapperScan("com.xxx.ggg.client.dao")
public class ClientInfoApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientInfoApplication.class);
public static void main(String[] args) {
SpringApplication.run(ClientInfoApplication.class, args);
}
}
Then I run spring boot application in IntelliJ
Here is the problem. Running spring boot application with application-test.yml is successful but not with application-dev.yml.
The logs are like
2018-12-17 14:27:23.497 [main][INFO]com.xxx.ggg.client.ClientInfoApplication[597]: The following profiles are active: dev
2018-12-17 14:27:24.490 [main][INFO]org.apache.coyote.http11.Http11NioProtocol[180]: Initializing ProtocolHandler ["http-nio-8080"]
2018-12-17 14:27:24.499 [main][INFO]org.apache.catalina.core.StandardService[180]: Starting service [Tomcat]
2018-12-17 14:27:24.500 [main][INFO]org.apache.catalina.core.StandardEngine[180]: Starting Servlet Engine: Apache Tomcat/8.5.31
2018-12-17 14:27:24.644 [localhost-startStop-1][INFO]org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/][180]: Initializing Spring embedded WebApplicationContext
2018-12-17 14:27:24.956 [main][WARN]org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext[551]: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInfoRunner': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tagService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'tagInfoDao' defined in file [D:\projects\ggg\client-info\target\classes\com\xxx\ggg\client\dao\TagInfoDao.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (the profiles "dev" are currently active).
2018-12-17 14:27:24.956 [main][INFO]org.apache.catalina.core.StandardService[180]: Stopping service [Tomcat]
2018-12-17 14:27:24.981 [main][ERROR]org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter[42]:
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (the profiles "dev" are currently active).

Reading environment variables or properties in a file

I am trying to deploy a spring-boot 2.0.4 application. The configuration looks like below :
#Component
#Configuration
#PropertySource("classpath:elast.properties")
public class ElastSearchLogLevel {
private static final Logger LOG = LoggerFactory.getLogger(ElastSearchLogLevel.class);
#Value("${elast.mail.to}")
private String to;
...
Locally on windows its working fine but in Linux box it says :
WARN o.a.commons.logging.impl.Jdk14Logger.log - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elastSearchBootApplication': Unsatisfied dependency expressed through field 'logsSearch'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elastSearchLogLevel': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'elast.mail.to' in value "${elast.mail.to}"
The instance 'elastSearchLogLevel' is autowired in SpringBootApplication class. Ideally i want to give an external configuration file from which the property can be read. As suggested in one of the forum I also tried but didn't work.
#PropertySource("classpath:file:///my/file/path/elast.properties")
ok some more code :
#ComponentScan(basePackages = "some.packer.log")
#SpringBootApplication
#EnableScheduling
public class ElastSearchBootApplication {
...

Activating Avro message converter in Spring Cloud Dataflow

I am implementing a stream app on Spring Cloud Dataflow. I would like to use Avro based schema registry client for serialization and schema control.
My basic goal is to feed Source app with some external data, transform it to prepared avro-based schema and send it to a Sink app which will accept only this schema.
I would like to use the schema from external schema registry server, not the file version of the schema.
My code looks like:
#EnableBinding(Source.class)
#EnableSchemaRegistryClient
public class DisSampleSource {
private final DisSampleSourceProperties properties;
#Inject
public DisSampleSource(DisSampleSourceProperties properties) {
this.properties = properties;
}
#InboundChannelAdapter(Source.OUTPUT)
public String feed() throws IOException {
if (!Paths.get(properties.getPath()).toFile().exists()) {
throw new InvalidPathException(this.properties.getPath(),
"The file does not exists or is of not proper type.");
}
return new String(Files.readAllBytes(Paths.get(properties.getPath())), StandardCharsets.UTF_8);
}
}
POM:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-schema</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
During starting application I am passing property:
--spring.cloud.stream.bindings.output.contentType=application/foo.bar.v1+avro
At the moment, the application fails to start with following exception:
2017-02-13 16:25:30.430 WARN 2444 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'disSampleSource' defined in URL [jar:file:/D:/git/dis/sample/source/target/dis-sample-source-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/com/atsisa/bit/dis/sample/DisSampleSource.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.stream.config.ChannelBindingAutoConfiguration': Unsatisfied dependency expressed through field 'adapters'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.stream.messaging.Source': Invocation of init method failed; nested exception is org.springframework.cloud.stream.converter.ConversionException: No message converter is registered for application/foo.bar.v1+avro
2017-02-13 16:25:30.440 INFO 2444 --- [ main] o.apache.catalina.core.StandardService : Stopping service Tomcat
2017-02-13 16:25:30.480 INFO 2444 --- [ main] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-02-13 16:25:30.485 ERROR 2444 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'disSampleSource' defined in URL [jar:file:/D:/git/dis/sample/source/target/dis-sample-source-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/com/atsisa/bit/dis/sample/DisSampleSource.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.stream.config.ChannelBindingAutoConfiguration': Unsatisfied dependency expressed through field 'adapters'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.stream.messaging.Source': Invocation of init method failed; nested exception is org.springframework.cloud.stream.converter.ConversionException: No message converter is registered for application/foo.bar.v1+avro
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:754) ~[spring-beans-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.4.RELEASE.jar!/:4.3.4.RELEASE]
What am I doing wrong?
Avro is an optional dependency of Spring Cloud Stream Schema (as the intent is to support other formats in the future. In order to activate schema support, you should simply add
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.1</version>
</dependency>
to the project.

Resources