Application won't start when adding function.routing.enabled=true with AWS Kinesis binder - spring-boot

I have a Spring Cloud Stream application where I'm using the AWS Kinesis Binder. I have the following configuration in the application.yml file:
cloud:
stream:
bindings:
customerEvents-out-0:
binder: kinesis
destination: 'customers-service-stream-name'
content-type: application/json
functionRouter-in-0:
destination: 'another-service-stream-name'
content-type: application/json
default:
group: customers-service-group
kinesis:
binder:
checkpoint:
table: 'SpringIntegrationMetadataStore'
locks:
table: 'SpringIntegrationLockRegistry'
headers:
- spring.cloud.function.definition
The application starts without errors.
The moment I add function.routing.enabled=true, the application won't start.
Configuration which stops the app from starting
cloud:
stream:
function:
routing:
enabled: true
bindings:
customerEvents-out-0:
binder: kinesis
destination: 'customers-service-stream-name'
content-type: application/json
functionRouter-in-0:
destination: 'another-service-stream-name'
content-type: application/json
default:
group: customers-service-group
kinesis:
binder:
checkpoint:
table: 'SpringIntegrationMetadataStore'
locks:
table: 'SpringIntegrationLockRegistry'
headers:
- spring.cloud.function.definition
This is part of the logs I see:
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'kinesisBinderHealthIndicator' defined
in
org.springframework.cloud.stream.binder.kinesis.config.KinesisBinderConfiguration$KinesisBinderHealthIndicatorConfiguration:
Unsatisfied dependency expressed through method
'kinesisBinderHealthIndicator' parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'kinesisMessageChannelBinder' defined in
org.springframework.cloud.stream.binder.kinesis.config.KinesisBinderConfiguration:
Unsatisfied dependency expressed through method
'kinesisMessageChannelBinder' parameter 3; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'kinesisCheckpointStore' defined in
org.springframework.cloud.stream.binder.kinesis.config.KinesisBinderConfiguration:
Invocation of init method failed; nested exception is
com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The
security token included in the request is invalid. (Service:
AmazonDynamoDBv2; Status Code: 400; Error Code:
UnrecognizedClientException; Request ID:
BDMVHHRUG4F7DD4GOH9POQGUKBVV4KQNSO5AEMVJF66Q9ASUAAJG; Proxy: null)
Caused by:
com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The
security token included in the request is invalid. (Service:
AmazonDynamoDBv2; Status Code: 400; Error Code:
UnrecognizedClientException
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'kinesisCheckpointStore'
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'kinesisMessageChannelBinder'
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'kinesisBinderHealthIndicator'
org.springframework.context.ApplicationContextException: Failed to
start bean 'inputBindingLifecycle'
In order to make the application start, I have to create the following 2 beans:
#Bean
AmazonKinesisAsync amazonKinesis(AWSCredentialsProvider awsCredentialsProvider) {
return AmazonKinesisAsyncClientBuilder
.standard()
.withCredentials(awsCredentialsProvider)
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpointUrl, region))
.build();
}
#Bean
#Primary
AmazonDynamoDBAsync amazonDynamoDBAsync(AWSCredentialsProvider awsCredentialsProvider) {
return AmazonDynamoDBAsyncClientBuilder.standard()
.withCredentials(awsCredentialsProvider)
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpointUrl, region))
.build();
}
However, these are beans that I add for local development with localstack, I shouldn't add these beans for prod.
Any ideas?

Related

Spring Security OAuth2 - Unable to start Spring Boot App if configured with multiple external Auth Servers and failed to connect to one of them

Background :
Configure Spring Boot Application to support Multiple External Authorization Servers
Example of application.properties :
#First Authorization Server
spring.security.oauth2.client.registration.my_okta_account.client-id=<client id>
spring.security.oauth2.client.registration.my_okta_account.client-secret=<client secret>
spring.security.oauth2.client.provider.my_okta_account.issuer-uri=<okta issuer>
#Second Authorization Server
spring.security.oauth2.client.registration.my_azure_ad.client-id=<client id>
spring.security.oauth2.client.registration.my_azure_ad.client-secret=<client secret>
spring.security.oauth2.client.provider.my_azure_ad.issuer-uri=<azure ad issuer>
Problem Description :
At startup time Spring Boot will try to create a clientRegistrationRepository Bean based on the configuration info in the properties file for each Authorization Server and try to establish rest connection with it.
If Connection to External Authorization Server failed, Application will fail to start.
Error :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientRegistrationRepository' defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository]: Factory method 'clientRegistrationRepository' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of
This is caused by : Caused by: java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "<azure ad issuer>" at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:220) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1] at org.springframework.security.oauth2.client.registration.ClientRegistrations.fromIssuerLocation(ClientRegistrations.java:144) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1] at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesRegistrationAdapter.getBuilderFromIssuerIfPossible(OAuth2ClientPropertiesRegistrationAdapter.java:83) ~[spring-boot-autoconfigure-2.4.5.jar:2.6.3]
This is caused by Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "< azure ad issuer >/.well-known/openid-configuration": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.6.jar:5.3.6] at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:670) ~[spring-web-5.3.6.jar:5.3.6] at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:155) ~[spring-security-oauth2-client-5.6.1.jar:5.6.1]
This is a snippet of the method in org.springframework.security.oauth2.client.registration.ClientRegistrations that failed :
private static Supplier<ClientRegistration.Builder> oidc(URI issuer) {
// #formatter:off
URI uri = UriComponentsBuilder.fromUri(issuer)
.replacePath(issuer.getPath() + OIDC_METADATA_PATH)
.build(Collections.emptyMap());
// #formatter:on
return () -> {
RequestEntity<Void> request = RequestEntity.get(uri).build();
Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();
OIDCProviderMetadata metadata = parse(configuration, OIDCProviderMetadata::parse);
ClientRegistration.Builder builder = withProviderConfiguration(metadata, issuer.toASCIIString())
.jwkSetUri(metadata.getJWKSetURI().toASCIIString());
if (metadata.getUserInfoEndpointURI() != null) {
builder.userInfoUri(metadata.getUserInfoEndpointURI().toASCIIString());
}
return builder;
};
}
ClientRegistrations.java can be found here : https://github.com/spring-projects/spring-security/blob/5.6.x/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java
The Line that failed is : Map<String, Object> configuration = rest.exchange(request, typeReference).getBody();
Disclaimer :
As you might noticed this is a Certificate Exception and can easily be recovered by importing the root CA for <azure ad issuer>
Question :
Is there a way to suppress this error and force Spring Boot App to start even if the configuration of one of the Authorization Servers failed to create the 'clientRegistrationRepository'?
I tried to use Spring Lazy Initialization at the level of the Controller which depends on 'clientRegistrationRepository' Bean, but even if the controller is not yet initialized 'WebMvcAutoConfiguration' will try to instantiate the 'clientRegistrationRepository'
Error : org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setClientRegistrationRepository' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientRegistrationRepository' defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository]: Factory method 'clientRegistrationRepository' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of < azure ad issuer >
My goal here is to successfully start the Spring Boot Application even if the connection to one of the External Authorization Server is not working.

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.

Spring boot application gives "unable to start tomcat" exception with spring-boot-starter-actuator

I had my spring-boot application, with spring-boot-starter-web, then I added spring-boot-starter-actuator to gradle file. There is no compilation error. But when i try to run the server it gives the following exception.
my build.gradle content (only the main ones included )
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
} ...........
compile "org.springframework.boot:spring-boot-starter-actuator"
compile group: 'io.micrometer', name: 'micrometer-registry-prometheus', version: '1.1.3' .........
my application.properties content
server.port = 2128
spring.couchbase.env.timeouts.connect=10000
spring.couchbase.env.timeouts.query=180000
spring.couchbase.env.timeouts.view=20000
spring.couchbase.bootstrap-hosts=localhost
spring.couchbase.bucket.name=localdb
spring.couchbase.bucket.password=*****
spring.data.couchbase.repositories.type=auto
spring.data.couchbase.auto-index=true
server.compression.enabled=true
server.compression.mime-types=application/json,text/plain
spring.servlet.multipart.enabled=true
spring.servlet.multipart.maxFileSize=50MB
spring.servlet.multipart.maxRequestSize=50MB
my Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Gives the following exception while starting the server.
org.springframework.context.ApplicationContextException: Unable to start web server;
nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'servletEndpointRegistrar' defined in class path resource
WebMvcServletEndpointManagementContextConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar]: Factory method 'servletEndpointRegistrar' threw exception;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'healthEndpoint' defined in class path resource
org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]: Unsatisfied dependency expressed through method 'healthEndpoint' parameter 1;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'healthIndicatorRegistry' defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthIndicatorAutoConfiguration.class]: Bean instantiation via factory method failed
Any helpful hints?
I was finally able to start the application after I turned off default health checks via the following entry in application.properties file
management.health.defaults.enabled=false

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).

spring boot: can't initialize a postgresql datasource

I have the following bean configured.
#Bean
#Primary
#ConfigurationProperties(prefix="datasource.etlTarget")
public DataSource datasourceTest() {
System.out.println("************");
System.out.println("************");
return DataSourceBuilder.create().build();
}
Then error log is:
************
************
2014-12-14 21:12:35.718 WARN 21758 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.Collection org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.dataSources; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'datasourceTest' defined in class path resource [com/testcom/etc/ETLJobRepository.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'datasourceTest' threw exception; nested exception is java.lang.IllegalStateException: No supported DataSource type found
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
Key error message is
nested exception is java.lang.IllegalStateException: No supported DataSource type found
The gradle setting is
dependencies {
compile "org.springframework.boot:spring-boot-starter-batch:1.2.0.RELEASE"
compile "org.springframework:spring-jdbc:4.1.3.RELEASE"
compile 'org.postgresql:postgresql:9.3-1102-jdbc41'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
I tried hard to figure it out why it error out, but don't find out the root cause
The property is
datasource.etlTarget.url=jdbc:postgresql://localhost/example
datasource.etlTarget.driverClassNname=org.postgresql.Driver
datasource.etlTarget.username=postgres
datasource.etlTarget.password=test
You made a typo in your configuration:
datasource.etlTarget.driverClassNname=org.postgresql.Driver
Should be:
datasource.etlTarget.driverClassName=org.postgresql.Driver
(i.e. driverClassName instead of driverClassNname)

Resources