0

I'm implementing two plugins for DB access to a springboot project in order to run simple SQL commands (they're the last two dependencies in my pom.xml file). I've developed several REST endpoints up to this point with no problem. The generated war file is hosted in Tomcat on a linux box.

This is an excerpt from my pom.xml file:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>        

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.11.0</version>
        </dependency>

        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>

        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

    </dependencies>

This is the Tomcat version:

Using CATALINA_BASE:   /apps/tomcat/apache-tomcat-9.0.34
Using CATALINA_HOME:   /apps/tomcat/apache-tomcat-9.0.34
Using CATALINA_TMPDIR: /apps/tomcat/apache-tomcat-9.0.34/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /apps/tomcat/apache-tomcat-9.0.34/bin/bootstrap.jar:/apps/tomcat/apache-tomcat-9.0.34/bin/tomcat-juli.jar
Server version: Apache Tomcat/9.0.34
Server built:   Apr 3 2020 12:02:52 UTC
Server number:  9.0.34.0
OS Name:        Linux
OS Version:     3.10.0-1160.24.1.el7.x86_64
Architecture:   amd64
JVM Version:    1.8.0_275-b01
JVM Vendor:     Red Hat, Inc.

Apache Maven version 3.6.3

After compiling (with Maven), all looks good, no build errors, builds the war file and all is fine, like any other previous build. Only now any end point I attempt to hit returns a 404, if I remove the 'spring-boot-starter-jdbc' dependency all returns to normal.

This is the walkthrough I'm following: https://www.codejava.net/frameworks/spring-boot/connect-to-microsoft-sql-server-examples

These are the logs while deploying with and without the dependency.

Logs without the dependency:

==> catalina.2021-04-25.log <==
25-Apr-2021 01:09:51.912 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.undeploy Undeploying context [/ciamdev]

==> localhost.2021-04-25.log <==
25-Apr-2021 01:09:51.917 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log Destroying Spring FrameworkServlet 'dispatcherServlet'
25-Apr-2021 01:09:51.940 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

==> catalina.2021-04-25.log <==
25-Apr-2021 01:09:52.079 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/apps/tomcat/apache-tomcat-9.0.34/webapps/ciamdev.war]
25-Apr-2021 01:09:54.783 INFO [Catalina-utility-2] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

==> localhost.2021-04-25.log <==
25-Apr-2021 01:09:55.017 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log 2 Spring WebApplicationInitializers detected on classpath
25-Apr-2021 01:09:58.028 INFO [Catalina-utility-2] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext

==> catalina.2021-04-25.log <==
25-Apr-2021 01:09:59.704 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/apps/tomcat/apache-tomcat-9.0.34/webapps/ciamdev.war] has finished in [7,625] ms

Logs with dependency:

==> catalina.2021-04-25.log <==
25-Apr-2021 01:12:59.805 INFO [Catalina-utility-1] org.apache.catalina.startup.HostConfig.undeploy Undeploying context [/ciamdev]

==> localhost.2021-04-25.log <==
25-Apr-2021 01:12:59.841 INFO [Catalina-utility-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

==> catalina.2021-04-25.log <==
25-Apr-2021 01:12:59.923 INFO [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/apps/tomcat/apache-tomcat-9.0.34/webapps/ciamdev.war]
25-Apr-2021 01:13:03.342 INFO [Catalina-utility-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

==> localhost.2021-04-25.log <==
25-Apr-2021 01:13:03.536 INFO [Catalina-utility-1] org.apache.catalina.core.ApplicationContext.log 2 Spring WebApplicationInitializers detected on classpath
25-Apr-2021 01:13:07.432 INFO [Catalina-utility-1] org.apache.catalina.core.ApplicationContext.log Initializing Spring embedded WebApplicationContext

==> catalina.2021-04-25.log <==
25-Apr-2021 01:13:09.189 SEVERE [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive [/apps/tomcat/apache-tomcat-9.0.34/webapps/ciamdev.war]
        java.lang.IllegalStateException: Error starting child
                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:720)
                at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
                at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
                at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:978)
                at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1849)
                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
                at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
                at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
                at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:773)
                at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:427)
                at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1620)
                at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:305)
                at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
                at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1151)
                at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
                at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1357)
                at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
                at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
                at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
                at java.lang.Thread.run(Thread.java:748)
        Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/ciamdev]]
                at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
                at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
                ... 25 more
        Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
                at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:656)
                at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
                at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
                at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
                at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
                at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
                at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
                at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
                at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
                at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
                at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
                at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
                at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
                at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:152)
                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:132)
                at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:92)
                at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
                at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5140)
                at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
                ... 26 more
        Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
                at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
                at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
                ... 48 more
        Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
                at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:233)
                at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:174)
                at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:43)
                at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:85)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
                ... 49 more
25-Apr-2021 01:13:09.190 INFO [Catalina-utility-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/apps/tomcat/apache-tomcat-9.0.34/webapps/ciamdev.war] has finished in [9,267] ms

I see 'dataSource' mentioned in the logs, this is what I have on the application.properites file:

spring.datasource.url=jdbc:sqlserver://some-server.net;databaseName=somedbname
spring.datasource.username=serverusername
spring.datasource.password=1346794613

The walkthrough provides to was of connecting to a db

3. Connect to SQL Server with Spring JDBC
4. Connect to SQL Server with Spring Data JPA

I'm attempting #3 as it's only basic SQL commands I need to execute.

I haven't found a similar issue while searching for a fix.

Has anyone else experienced this? What could be the issue?

Thanks in advance.

Raul Marquez
  • 948
  • 1
  • 17
  • 27

2 Answers2

1

Spring MVC (Springboot) and many other MVC frameworks share the same concept, where Controller (C) is strictly separated from Model (M). Thus, it is very unlikely that any persistence module, JDBC, interfares with your controller. In your question,

Only now any end point I attempt to hit returns a 404

I can only assume that the application did not even get started in this scenario.

You can post the stact trace when you are trying to get the app up and running.


There is another thing to notice though, which might not be relevant to your question. In the walkthrough you are following, you might want to add @Repository,

package net.codejava;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
 
}

So this is turned into a Spring Bean which you can further autowire it somewhere.


UPDATE: After checking the stacktrace you just posted, I noticed that the driver class is the problem here.

Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: 
Factory method 'dataSource' threw exception; nested exception is 
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: 
Failed to determine a suitable driver class

See the Failed to determine a suitable driver class? It is advising you to define a driver class.

For Microsoft sqlserver, try defining the driver class name in your .properties configuration file. For example, it could be:

spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
# or
# spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver

See also https://springframework.guru/configuring-spring-boot-for-microsoft-sql-server/

Notice that the driver class name may change from version to version.

justthink
  • 439
  • 3
  • 6
  • I will update my post with the logs and the contents of application.properties – Raul Marquez Apr 25 '21 at 01:16
  • BTW, I haven't even used the dependency or tried instantiating anything in code, I'm first just trying to make sure the dependency gets imported and is ready for use. – Raul Marquez Apr 25 '21 at 01:27
  • @Raul Marquez The dependency `mssql-jdbc` automatically configures the datasource by checking your configurations in `.properties` file. If there is anything wrong with the configurations, it will complain and stop your application from running. – justthink Apr 27 '21 at 03:25
0

I found the solution in this post: https://stackoverflow.com/a/31199853/3247471

Which was adding this line

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

in the springboot application class like so:

@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class HealthcheckApiApplication extends SpringBootServletInitializer {
...}

Thanks @justthink for pointing me in the right direction.

Raul Marquez
  • 948
  • 1
  • 17
  • 27