Spring Boot : Cannot load driver class: org.hsqldb.jdbcDriver - spring

I have a simple Spring Boot application (generated through Spring Roo).
The database is configured as following :
spring.datasource.driver-class-name=org.hsqldb.jdbcDriver
spring.datasource.url=jdbc\:hsqldb\:mem\:PetClinic
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.messages.encoding=ISO-8859-1
spring.messages.fallback-to-system-locale=false
spring.thymeleaf.mode=html
Here are the how I declared the HSQLDB dependency :
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>provided</scope>
</dependency>
When I start the application, I get the error :
Caused by: java.lang.IllegalStateException: Cannot load driver class: org.hsqldb.jdbcDriver
at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:214) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE]
The Spring-boot-autoconfigure module tries to load the class with the ClassUtils utility class that loads the current context classes.
I wonder if this method works fine since I use a Tomcat container which is responsible to load the Maven dependencies ?
Why even with the JAR in the libs directory Spring is not able to find it ?

Remove <scope>provided</scope> from your pom.xml
Remove both spring.datasource.driver-class-name and spring.datasource.url properties from your application properties
Because:
when spring.datasource.url is provided the driver class name is redundant as Spring Boot will automatically attempt to load the correct driver.
since you want to use an embedded database you don't need to provide spring.datasource.url at all. Just need to have an embedded database JAR on the classpath (like HSQLDB)
Relevant docs snippet:
Spring Boot can auto-configure embedded H2, HSQL and Derby databases.
You don’t need to provide any connection URLs, simply include a build
dependency to the embedded database that you want to use.
Please read the Working with SQL databases section in of Spring Boot documentation. Everything I said is mentioned there, so you can get more detail.

I see the scope you gave is provided, <scope>provided</scope>, I don't think Tomcat provides the hsqldb.jar with it out of the box.
So try removing the provided scope.

Related

Is Zonky embedded database supported for Spring boot 3.0 version?

I am trying to migrate my application from spring boot 2.7.2 to 3.0.0 version.
On running integration test case, I am getting below error :
java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.JdbcMapping.getJdbcValueBinder()" because "jdbcMapping" is null
Hibernate ORM core version is 6.1.5.Final.
Could someone please guide if they have used zonky libraries with spring boot 3.0 ?
I have added below dependencies in pom.xml :
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-postgres</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
In case the test class uses a spring context that already contains a data source bean, the data source bean will be automatically replaced with a testing data source. The newly created data source bean will be injected into all related components, and you can also inject it into a test class.

Spring Cloud Config: Bootstrap context not loading profile-specific property files for binding

Setup
Spring Boot 2.6.0
Spring Cloud Config 3.1 RC1
Apache Maven 3.8.x
OpenJDK 11
Overview
I have a multi-module Apache Maven project that is set up with the following modules:
bootstrap: contains a PropertySourceLocator for BootstrapConfiguration, defined in spring.factories file.
starter: depends on bootstrap, and it's a (servlet-based) web application
reference: deploys the starter application using the Maven Cargo plugin, deploying into an Apache Tomcat 9.0.55
Runtime
The starter module declares a configuration class, annotated with #PropertySource("wa.properties"). This wa.properties on the classpath of the starter module has a setting: cas.authn.syncope.name=Starter
The starter module has a ServletInitializer that sets the spring.config.name property to "wa" when building the spring application.
The reference module only has a wa-embedded.properties file on the classpath with a setting: cas.authn.syncope.name=Embedded
The reference module starts with the spring activated profiles: embedded,all
Note: the cas.authn.syncope.name is bound to a Java POJO, CasConfigurationProperties, that is annotated with #ConfigurationProperties("cas").
Observation
The following bean in the application exists, simplified for this post:
#Bean
#ConditionalOnMissingBean(name = "something")
#RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public Something something(ApplicationContext ctx, CasConfigurationProperties cas) {
...
}
If I look at the contents of cas.getAuthn().getSyncope().getName()), it shows: "Starter"
If I look at ctx.getEnvironment().getProperty("cas.authn.syncope.name"), it shows "Embedded".
In other words, property binding used during the bootstrapping process does not match the actual environment for the application's context.
Analysis
It appears that when the bootstrap application context is created, wa-embedded.properties, a profile-specific property is not read. In fact, the only property source that is used for binding is wa.properties as part of "localProperties", which I believe comes from #PropertySource("wa.properties"). Nothing else is read or found.
Then, property binding takes place binding CasConfigurationProperties and cas.authn.syncope.name initialized from #PropertySource("wa.properties"). The value of this property is set to Starter.
Then, the application servlet context is initialized and its environment is post-processed with profiles and the appropriate listener and Spring beans are created. In particular, this bean:
#Bean
#ConditionalOnMissingBean(name = "something")
#RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public Something something(ApplicationContext ctx, CasConfigurationProperties cas) {
...
}
...shows that ctx is the actual application context with an environment that is post-processed via all profiles and shows ctx.getEnvironment().getProperty("cas.authn.syncope.name") as "Embedded".
However, CasConfigurationProperties was processed using the Bootstrap context only, and its equivalent property shows "Starter".
...which means the bean would be created using the wrong values in CasConfigurationProperties.
Research
This setup works OK using Spring Boot 2.5.6 and Spring Cloud 3.0.5. I don't think anything in Spring Boot has changed that would affect this, but I do see a number of differences in Cloud between 3.0 and 3.1.
I am not sure I can create a reproducer to adequately showcase this. I'll try. In the meantime, could you evaluate this and see if this might be seen as a bug, or misconfiguration of some kind?

Spring/tomcat Cannot load driver class: com.mysql.jdbc.driver

Lately I have been trying to learn spring boot. I have the following relevant files:
an #Configuration class: I use this to generate the entitymanagerfactory
an #Entity class: I use this to map to a mysql table instance
an #Repository crudrepository interface: this is built in to spring
an #Controller class: this is used to test auto-wiring (when I can inject, I will move this to the service layer)
an #SpringBootApplication class: this runs my application
an application.properties file
a pom.xml: this is used for maven and includes mysql jar
an entity class mapped to a mysql table and a UserRepository class(annotated with #Repository). I am trying to inject the crudrepository class via #Autowire annotation, but spring is having difficulty creating the datasource for it because it cannot find the mysql driver. What confuses me is that I have the mysql dependency in maven and I am deploying this on a glassfish 4 server, but Spring is trying to use apache tomcat to connect to the database. Below is my stack trace, code snippets, and mysql-connector:
Relevant Stack Trace (inner exception)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.driver
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 62 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.driver
notice how this is trying to use org.apache.tomcat to create datasource, even though I am using a glassfish server. Does this matter?
Source Code: the first relevant exception occurs when spring tries to inject the datasource bean that is a parameter to this method and can't create it
#Configuration
#EnableAutoConfiguration
public class AppConfigUtil {
#Autowired
#Bean
public EntityManagerFactory entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setPackagesToScan("com.connor");
bean.setDataSource(dataSource);
return bean.getObject();
}
Maven (pom.xml) for mysql jar:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
application.properties: this is the entirety of my application.properties file spring uses to generate datasource
spring.datasource.url=jdbc:mysql://localhost:3307/craigslist
spring.datasource.username=dbadmin
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.driver
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
Here is picture of my maven dependencies: the mysql jar is present:
downloaded maven dependencies: including mysql jar
Any ideas on how to fix this?
Assuming you are using Spring boot.
Here are some things you can do to make it work (You might have done some of these, I added anything I can think of just to make sure):
Remove your AppConfigUtil class because Spring boot will "magically" find the datasource for you if your application.properties is configured right.
Add #SpringBootApplication to your ConnerApplication.java class
Add spring-boot-starter-data-jpa dependency in your pom
Some side notes:
#Autowire is not intended to be marked with #Bean annotation. #Autowire CAN be used to autowire bean which is annotated with #Bean.
EDIT :
I realized that OP wants to deploy it on Glassfish. In that case, you will need to tweak Spring to produce a deployable war file and configure your application container (glassfish) to include a jdbc driver. All of it is doable but requires a lot of efforts.
I suggested that you go with embedded tomcat approach if you use Spring-boot for new project. It is basically battle-ready. You can hardly go wrong with this.
You don't need declare in pom.xml
spring.datasource.driver-class-name=com.mysql.jdbc.driver
You can read my configuration in a simple app using Spring Boot here
Beside, if you're using Spring Boot you don't need use codes "Source Code: the first relevant exception occurs when spring tries to inject the datasource bean that is a parameter to this method and can't create it..."

Error when trying to use both mongo and sql jpa in the same spring app

We have a spring app that works with mongodb.
Now we need it to connect also to mysql.
All the beans are defined in a applicationContext.xml legacy file.
We like that the new mysql configuration will be in java classes.
We created an entity, repository and a configuraion java files.
But it seems that as we try to do so, spring gets confused.
If we try to run the app, it start complaining about the mongo repositories:
Error creating bean with name 'MyMongoRepository': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities
In the intellij we have the "could not autowire" error only on the sql repository (the first 3 are the mongo repositories):
Is it possible that the #configuration class is clashing with the applicationContext?
Should the #configuraion class be in a certain package/folder to work correctly?
Also, in the #configuration file, as there are green beans on the left side, it seems like intellij is able to understand where is the persistence repository.
Thanks for any help.

SpringBoot DataSource configuration

I'm trying to use the application.properties file to configure the datasource Spring Boot will have to use.
I've put the following properties inside :
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.user=test
spring.datasource.password=test
spring.datasource.jdbcUrl=jdbc:postgresql://localhost:5432/test
The application.properties file is well used by other systems. But I can't get it to work for the automatic datasource configuration.
I'm still getting this Exception :
org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database url for database type NONE.
The postgresql driver is included and loaded. And I can configure the datasource using a Configuration class, and the same parameters as above.
I've also added the #EnableAutoConfiguration and #EnableJpaRepositories to my Application.class.
Any clues?
You should use spring.datasource.url to configure the JDBC URL rather than spring.datasource.jdbcUrl.
spring.datasource.jdbcUrl will work if the specific DataSource implementation that you're using has a setJdbcUrl method (HikariCP, for example) where as spring.datasource.url will work with any of the supported datasources.
Using spring.datasource.url also has the added benefit that you don't need to specify spring.datasource.driverClassName as it will be inferred from the url.

Resources