Issue with spring cloud task mutiple datasources - spring-boot

I configured two data sources in my app following the guide of spring example:https://github.com/spring-cloud/spring-cloud-task/blob/master/spring-cloud-task-samples/multiple-datasources.
The spring boot version I use is :2.0.0.RELEASE
The spring.cloud.task.version I use is :1.2.2.RELEASE.
This application works fine in my local computer, But when deploy to the to AWS, I got the following error with the defination of class:CustomTaskConfigurer.java.
which defined the same as here:https://github.com/spring-cloud/spring-cloud-task/blob/master/spring-cloud-task-samples/multiple-datasources/src/main/java/io/spring/configuration/CustomTaskConfigurer.java
The error message is like below:
exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cloud.task.configuration.SimpleTaskConfiguration': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customTaskConfigurer' defined in file [/home/vcap/app/BOOT-INF/classes/com/xxx/configuration/CustomTaskConfigurer.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.xxx.configuration.CustomTaskConfigurer$$EnhancerBySpringCGLIB$$bc80cd46]: Constructor threw exception; nested exception is java.lang.IllegalStateException: Unable to create a TaskExecutionDao.

The root cause for this error is that when I developed the application locally I configure a local datasource bean for postgresql like below:
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public HikariDataSource sourceDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
This bean read the properties in the application.properties file which identify the username and password url for the local postgres.
When This application deloyed to cloud,It will connect to the cloud data base instead of the local databases, which means the url,username,and password are no longer correct.
After add the configuration for cloud, this error disppeared.
But this exception stack trace only tell you that it is unable to create taskExecutionDao, It is really hard for the user to fix the issue when see such a error message

If it is a multiple datasource issue, you can try marking it as #Primary. Providing a better stack trace is helpful.

Related

Couldn't able to retrieve the path of h2 db when spring-boot application being deployed with application jar

I am deploying a spring boot application with jar built by maven, and i am using the h2 db as file which is placed in the resource folder. And i am creating the spring JdbcTemplate connection using the Hikari configuration. Here for Hikari configuration i need to provide the location of the h2 db location as URL and i trying to provide as per the h2 db documentation. But while creating the connection application failed saying following exception
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'h2DBConnection' defined in com.xx.Application: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jdbc.core.JdbcTemplate]: Factory method 'h2DBConnection' threw exception; nested exception is java.io.FileNotFoundException: class path resource [h2DB.mv.db] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/app/app.jar!/BOOT-INF/classes!/h2DB.mv.db
But when i check the jar file to see the content file is there in the mentioned path.
And i saw other posts saying need to use the ResourceLoader with inputstream to load the files from the jar. But here i need to provide the path to db file for Hikari config.
It is working fine in the IDE only issue when i start the application using Jar
Can someone help me how can it be done?
i tried to use the classpathResource and ResourceLoader but it couldn't able to get the file by jdbctemplate.

Unable to create retry-able datasource for spring boot jdbc

I would like to add the retry feature for database connection certain number of times until the app acquires it. For the I have used the spring-retry on the DataSource but it is not working. It is throwing the following error
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbcTemplate' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/JdbcTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'jdbcTemplate' 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$Hikari.class]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: ExistingValue must be an instance of com.zaxxer.hikari.HikariDataSource
I have seen the debug logs but those are not helpful. Here is the sample source code . kindly help
Note: the dependencies mentioned in build.gradle is required for my app. I have only extracted the retry part.
Your use-case is delaying the start of Spring Boot until your database is up. Spring actually ships with a component that does that. The DatabaseStartupValidator is that component and has existed since about Spring 1.x.
You can add it as a bean and it will wait for further bootstrapping until the database is up.
#Bean
public DatabaseStartupValidator databaseStartupValidator(DataSource dataSource) {
var dsv = new DatabaseStartupValidator();
dsv.setDataSource(dataSource);
return dsv;
}
For a more detailed explanation see this blog post of mine.

Spring Boot application cannot join Coherence cluster on server: Join request was aborted

I have developed a small REST API application with Spring Boot after another sample application with classic Spring XML configuration. It imports context from a library with a Coherence cache set up.
When I developed it locally, running the Spring Boot app with Intellij Idea runner, there were no issues, the application worked fine and the endpoint worked connecting to that cache.
When I deployed the application to the Unix server, I am getting the following error during the application startup:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'coreSearchSync' defined in class path resource [core-search-core-context.xml]: Cannot resolve reference to bean 'corePersistenceManager' while setting bean property 'corePersistenceManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'corePersistenceManager': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ' coreSearchResultCache' defined in class path resource [core-search-coherence-context.xml]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.tangosol.net.NamedCache]: Factory method 'getCache' threw exception; nested exception is (Wrapped: Failed to start Service "Management" (ServiceState=SERVICE_STOPPED)) java.lang.RuntimeException: Join request was aborted
The application on the server is using the application.properties but they are the same as in the application.yaml locally.
I am not sure where to continue the investigation...
The problem was solved by passing JVM arguments to the script to start the application:
-Dtangosol.coherence.clusterport=<port> -Dtangosol.coherence.site=<site> -Dtangosol.coherence.clusteraddress=<cluster_ip_ddress> -Dtangosol.coherence.cluster=<cluster_name>
It appears that these properties are not applied from the application properties because starting the coherence cluster works on the system level and/or starts before the properties are initialized. Or those properties are not visible to the coherence.

How to avoid spring application failure due to BeanCreationException caused by third party package

I am using a third-party package in my spring boot app. This one to be specific. This package has a method that creates a bean when the application starts. The bean is only created successfully if this package is able to talk to nats service. In most cases, this all works fine. The remote server is available, the bean is created, my spring boot apps boots up correctly.
But there are some edge cases when remote nats servers might not be up. This causes my spring boot app to fail to start as the above function throws BeanCreationException
How can I avoid this i.e avoid my spring app boot failure due to this exception when the nats server is not up?
Note: It is fine for my spring app/business logic to be up and running if this bean (connections to nats service) is not available.
Specific Exception :
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'natsConnection' defined in class path resource [io/nats/spring/boot/autoconfigure/NatsAutoConfiguration.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.nats.client.Connection]:
Factory method 'natsConnection' threw exception; nested exception is java.io.IOException: Unable to connect to NATS server.\n\tat org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)\n\tat org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:635)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)\n\tat org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)\n\tat org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)\n\tat org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)\n\tat
The bean natsConnection is created by auto-configuration and annotated with #ConditionalOnMissingBean. Such beans are instantiated after your own beans.
You can create your own bean of this type, io.nats.client.Connection, and register it as natsConnection. This bean should have no own logic. When called for the first time, it should create a worker instance via NatsAutoConfiguration.natsConnection(...) and then delegate all calls to it.
Because of #ConditionalOnMissingBean the default bean from the NATS library will not be instantiated and only your bean will be created.

Spring Boot: How to define new object classes in UnboundID LDAP?

In a Spring Boot 2.1.6 project I'm using the embedded LDAP service (UnboundID LDAP). I need to define new attribute types and object classes. My LDIF file contains something like that:
dn: cn=schema
changetype: modify
add: attributetypes
attributetypes: ( 2.25.128424792425578037463837247958458780603.1 NAME 'customAttribute' DESC 'a custom attribute' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
However, when I deploy my WAR on tomcat I get this exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'directoryServer' defined in class path resource [org/springframework/boot/autoconfigure/ldap/embedded/EmbeddedLdapAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.unboundid.ldap.listener.InMemoryDirectoryServer]: Factory method 'directoryServer' threw exception; nested exception is java.lang.IllegalStateException: Unable to load LDIF classpath:test.ldif
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.unboundid.ldap.listener.InMemoryDirectoryServer]: Factory method 'directoryServer' threw exception; nested exception is java.lang.IllegalStateException: Unable to load LDIF classpath:test.ldif
...
Caused by: LDAPException(resultCode=68 (entry already exists), errorMessage='Unable to add an entry with a DN that is the same as or subordinate to the subschema subentry DN 'cn=schema'.', ldapSDKVersion=4.0.11, revision=34e39aab27ea4fb92659a6888933db08099c7e41)
at com.unboundid.ldap.listener.InMemoryRequestHandler.addEntry(InMemoryRequestHandler.java:4916)
at com.unboundid.ldap.listener.InMemoryRequestHandler.importFromLDIF(InMemoryRequestHandler.java:4624)
at com.unboundid.ldap.listener.InMemoryDirectoryServer.importFromLDIF(InMemoryDirectoryServer.java:1255)
at org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration.importLdif(EmbeddedLdapAutoConfiguration.java:164)
... 76 more
What happens obviously is that, for some reason, the LDAP service "thinks" that I'm trying to ad the entry "cn=schema", and refuses the operation as the entry already exists, while I'm trying to modify it, hence the statememnt "changetype: modify" in the LDIF file.
Could someone please advise me what I'm doing wrong ?
Many thanks in advance.
Kind regards,
Nicolas

Resources