54

I am currently learning more about implementing JDBC and using databases in a Spring Boot webapp, and I encountered the following Stack Trace written in the bottom of the post.

I have created a simple Employee model, and I am trying to execute some database code on the same class which my main() lies in. The model and the main class are the only two java files existing in this whole project. I am trying to implement the following run() code that overrides the one from the interface, CommandLineRunner, but I do not get the logs that should come after log.info("Part A:"):

log.info("Part A:")
employees.forEach(employee -> {log.info(employee.toString());
        log.info("part a");});

--Things I noticed:

I noticed that the last line of the log before the stack trace starts comes from: "Thread-1" instead of "main". I think that means that a thread from somewhere other than the main encountered an error and closed connection before when it should close normally.

Also, I think that because HikariPool closed before "peer's close_notify", which I presume that it refers to the normal closure of HikariPool, I am not able to see the final bit of logging that I have kept trying to procure. The final bit of logging that I want to see is the logging of the employee that has become inserted into my database.

The final bit of logging that I want to see should be procured from this line of code:

employees.forEach(employee -> {log.info(employee.toString());
        log.info("part a");});

--Things to note:

Because of this line in the log, I thought I would see the employee inserted into my database, but when I queried directly on MySQL Command Line Client, it returned an empty set:

2018-11-03 21:08:35.362  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : rows affected: 1

I don't understand why a row has been affected when nothing has been inserted into the database.

The stacktrace and logs: (The stacktrace pasted below actually repeats itself several more times but I cut it off for brevity.)

2018-11-03 21:08:32.997  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Starting JdbcTest1Application on KitKat with PID 2408 (C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1\target\classes started by Nano in C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1)
2018-11-03 21:08:33.003  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : No active profile set, falling back to default profiles: default
2018-11-03 21:08:33.770  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Started JdbcTest1Application in 1.024 seconds (JVM running for 1.778)
2018-11-03 21:08:33.770  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Creating tables
2018-11-03 21:08:33.770  INFO 2408 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-11-03 21:08:34.082  INFO 2408 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2018-11-03 21:08:35.135  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Inserting Baggins Hopkins
2018-11-03 21:08:35.362  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : rows affected: 1
2018-11-03 21:08:35.362  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Querying for employee
2018-11-03 21:08:36.065  INFO 2408 --- [           main] c.j.jdbctest1.JdbcTest1Application       : Part A:
2018-11-03 21:08:36.065  INFO 2408 --- [       Thread-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
Sat Nov 03 21:08:36 KST 2018 WARN: Caught while disconnecting...

EXCEPTION STACK TRACE:



** BEGIN NESTED EXCEPTION ** 

javax.net.ssl.SSLException
MESSAGE: closing inbound before receiving peer's close_notify

STACKTRACE:

javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:255)
    at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:645)
    at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:624)
    at com.mysql.cj.protocol.a.NativeProtocol.quit(NativeProtocol.java:1312)
    at com.mysql.cj.NativeSession.quit(NativeSession.java:182)
    at com.mysql.cj.jdbc.ConnectionImpl.realClose(ConnectionImpl.java:1750)
    at com.mysql.cj.jdbc.ConnectionImpl.close(ConnectionImpl.java:720)
    at com.zaxxer.hikari.pool.PoolBase.quietlyCloseConnection(PoolBase.java:135)
    at com.zaxxer.hikari.pool.HikariPool.lambda$closeConnection$1(HikariPool.java:441)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)


** END NESTED EXCEPTION **

The Java Code:

@SpringBootApplication
public class JdbcTest1Application implements CommandLineRunner {
    private static final Logger log = LoggerFactory.getLogger(JdbcTest1Application.class);

    @Autowired
    JdbcTemplate jdbcTemplate;

    public static void main(String[] args) {
        SpringApplication.run(JdbcTest1Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("Creating tables");

        jdbcTemplate.execute("DROP TABLE IF EXISTS employees");
        jdbcTemplate.execute("CREATE TABLE employees (emp_id int, name varchar(100), role varchar(100), status varchar(100))");

        log.info("Inserting Baggins Hopkins");
        int rowsAffected = jdbcTemplate.update("INSERT INTO EMPLOYEE(EMP_ID, NAME, ROLE, STATUS)"
                + " VALUES(1,'Baggins Hopkins','thief','WORKING')");
        log.info("rows affected: "+ Integer.toString(rowsAffected));
        log.info("Querying for employee");
        String sql = "SELECT emp_id,name,role,status FROM employees";
        List<Employee> employees = jdbcTemplate.query(sql,(rs, rowNum)-> 
        new Employee(rs.getInt("emp_id"), rs.getString("name"),
                rs.getString("role"),Status.valueOf(rs.getString("status"))));
        log.info("Part A:");
        employees.forEach(employee -> {log.info(employee.toString());
            log.info("part a");});

    }
}

Also just in case this matters, I pasted this code from application.properties:

spring.datasource.url=jdbc:mysql://localhost:3306/employee_database
spring.datasource.username=employee
spring.datasource.password=employee
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
DP Park
  • 815
  • 1
  • 9
  • 19

14 Answers14

112

The SSL connection to the database is failing, try changing your datasource URL to:

spring.datasource.url=jdbc:mysql://localhost:3306/employee_database?useSSL=false
  • Hi, thanks for answering, but I get an error: java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed – DP Park Nov 05 '18 at 02:51
  • 13
    In mysql connector 8.0.13 this parameter bacame legacy.Adding ?sslMode=DISABLED instead solved the problem for me. – schrom Nov 08 '18 at 07:43
  • I was getting the same error executing when trying to connect to jdbc via Liquibase's command (liquibase:update) and after adding to url ?useSSL=false in the file *.properties works perfectly. This must be the accepted question please. – bishop Jan 29 '19 at 11:34
  • 3
    @bishop I'm pretty sure the questioner selects the answer that solved the questioner's problem as accepted. Even though this answer isn't accepted as the answer, it's still voted the highest and stays above mine for others to check first, so I think I'll keep my own answer as accepted. In other words, it didn't work for me and I'm the one who asked, so no, this will not be the accepted answer. As long as it stays at the top and has the most votes, I see no great problem. – DP Park Jan 30 '19 at 06:06
  • 6
    This is a workaround for testing purposes only, not a solution. See @Michael Técourt's answer. – Jason Young Feb 21 '19 at 17:50
20

The warning looks like a MySQL driver bug with Java 11 and SSL enabled : https://bugs.mysql.com/bug.php?id=93590
Deactivating encryption because of a driver warning is a bad idea.

Your insertion problem looks more like a classic transaction issue though, I doubt it is related to the SSL warning.

Michael Técourt
  • 3,457
  • 1
  • 28
  • 45
  • The same bug seems to exist for Java 8.0.27x. I found it on 8.0.272.hs-adpt (via sdkman) and 8.0.275-amzn. 8.0.265.fx-librca was the latest version via sdkman that doesn't error with MySQL driver 8.0.21. – randy Dec 18 '20 at 17:22
14

This Worked for me

   <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
        <version>8.0.20</version>
    </dependency>
abu kalam azad
  • 161
  • 1
  • 4
  • This also worked for me. Looks like using the latest version (I am using 8.0.23) can resolve the issue – Lei Z Jan 21 '21 at 14:23
  • This worked for me too, but not sure why? Is it something to do with self-signed certs with the older versions? – ephemeralCoder Jun 01 '21 at 18:04
  • According to https://bugs.mysql.com/bug.php?id=93590 this was fixed in 8.0.16, and 5.1.48 see https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/news-8-0-16.html and https://dev.mysql.com/blog-archive/mysql-connector-j-5-1-48/ (Bug #29054329, Bug #93590) – FelixJongleur42 Dec 22 '22 at 08:24
9

To solve this problem, it took me about three days.

(Edit: This is a workaround for testing and not actually a solution.)

At first, I started solving the problem from trying to configure my own SSL for mysql, and I spent quite a few hours on that. Too much time had passed until I realized configuring it had to do with Cmake and C++, which made me give up. It was very frustrating. However I did not give up and tried to disable SSL entirely through a method that hasn't been found. And I eventually did find the method. Here it is:

  1. You have to use the legacy password for MySQL. The legacy password is the way MySQL authenticated things in version 5.7x.

Open up the MySQL installer again, and reconfigure the MySQL Server settings. When you get there you will see this screen:

The screen that you should get to

You might get some errors when reaching the final stage of the reconfiguration:

I had problems at the final stage I had no idea how to fix so I uninstalled MySQL altogether. I use windows. I deleted the MySQL project root directory from Program Files to uninstall MySQL. I also deleted the databases saved in Program Data (a hidden folder in the C Drive) because I wanted to start afresh(WARNING: this will delete all your previously saved data!). Uninstalling MySQL from the control panel might not be enough to completely erase MySQL from your computer.

  1. Delete all *.pem files in C:\ProgramData\MySQL\MySQL Server 8.0\Data. (or move it somewhere else, which is what I did)

You might not see ProgramData in the C Drive. That is because it is a hidden folder. In order to see hidden folders:

search for folder options in the control panel.

Go to view.

Under 'Advanced settings' and under 'Hidden files and folders' of that, click "Show hidden files, folders, and drives."

  1. Go to C:\ProgramData\MySQL\MySQL Server 8.0 and open my.cnf (or my.ini). Add the following line after [mysqld]:

ssl=0

Then save. It should work now.

References:

  1. https://community.atlassian.com/t5/Confluence-questions/MySQL-Public-Key-Retrieval-is-not-allowed/qaq-p/778956
  2. https://scalegrid.io/blog/configuring-and-managing-ssl-on-your-mysql-server/
Community
  • 1
  • 1
DP Park
  • 815
  • 1
  • 9
  • 19
  • Does this also mean "disable" SSL when you set ssl=0? I think in most cases - especially in commercial world - this is not a desired setting. – Lei Z Jan 21 '21 at 13:52
9

I also faced the same issue. if you look the the stacktrace, it's cleary mentioned what to do -

Sat Mar 16 09:00:01 IST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. 
You need either to explicitly disable SSL by setting **useSSL=false**, or set **useSSL=true** and provide truststore for server certificate verification.

so after disabling the ssl by making changes in data source url solved the problem -

spring.datasource.url=jdbc:mysql://localhost:3306/security?useSSL=false
Arvind Kumar
  • 459
  • 5
  • 21
  • disabling ssl is a bad thing, perhaps its something you to debug a problem. Running without encryption will set you up for data leaks. – JustEngland Dec 13 '22 at 15:55
6

My similar problem in a tomcat trying to conect via ssl to Aurora mysql (AWS)

I solved the problem by updating the driver version from 'mysql-connector-java-5.1.40.jar' to 'mysql-connector-java-5.1.49.jar', and installing a root CA into ceacerts:

keytool -import -trustcacerts -file rds-ca-2019-root.pem -keystore /<your_java_home>/lib/security/cacerts

Hope be use to you

Ruimán
  • 61
  • 1
  • 2
  • 1
    Reference to AWS certificate: https://docs.aws.amazon.com/es_es/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html – Ruimán Jun 22 '21 at 10:28
  • This was the exact issue I was running into. Once I updated the mysql-connector (along with pulling down the appropriate cert) everything worked fine. – Marcus Sep 16 '21 at 03:48
5

Try using the following URL. As they suggested use useSSL=false Also, Make sure to use <&amp> instead of just & when you have multiple properties defined in your URL.

jdbc:mysql://localhost:3306/TestDB?serverTimezone=PST&amp;useSSL=false

Avatar Girase
  • 133
  • 2
  • 6
2

I was also facing the same issue

But then i updated the mysql-connector-java version from 5.1.46 to 8.0.20 and by changing com.mysql.jdbc.Driver to com.mysql.cj.jdbc.Driver it solved my issue

Deviprasad Sharma
  • 470
  • 1
  • 8
  • 19
1

My similary prolem is in spark, I solove the problem by down the java verion from 'openjdk version "1.8.0_275"' to 'openjdk version "1.8.0_265"', hope be use to you

jlbhdfsl
  • 11
  • 1
0

I had this issue and decided to use Carrier Pigeon Protocol's solution until I accidentally solved it by updating Tomcat from version 9.0.12 to 9.0.16.

Jack J
  • 1,514
  • 3
  • 20
  • 28
  • Sadly I am getting it for 9.0.16 as well – Gunith D Apr 06 '19 at 06:42
  • 1
    I thought I had it working when I posted this answer, but I am not so sure now. What I have been doing recently is using a connection pool with [Tomcat's PoolProperties](https://stackoverflow.com/a/15632353/2031150). This allows me to make a connection without disabling SSL, but I do now have a memory leak warning that I haven't bothered to resolve yet. – Jack J Apr 06 '19 at 11:23
0

I faced a similar issue when I upgraded the Java version in my server to 11 from 8.

The spring boot started supporting Java 11 from 2.1 and onwards. So make sure your project's dependencies are also updated accordingly. This is relevant for this answer as SpringBoot also influence MySQL connector, Hibernate core, and other dependencies.

The inability to connect to DB was resulting in some more NoClassDefFoundErrors. So make sure you solve this first before looking into other errors.

An example pom dependency for the SpringBoot starter

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

Hope this helps someone.

Chethan
  • 501
  • 1
  • 8
  • 15
0

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: name-unit] Unable to build Hibernate SessionFactory

I had exactly the same problem, I also modified a false my useSSL like this useSSL=false and it works fine. I think for those who use intelliJ ultimate the error the problem does not arise. But for those who use the community version "yes" also for those who are on netbeans like my case. This concerns the management of persistence.xml files and the EntityManagerHolder file

AhmedO
  • 1
0

Rather than disabling SSL/TLS I appended the following to the database connection string: &enabledTLSProtocols=TLSv1.2

tschumann
  • 2,776
  • 3
  • 26
  • 42
0

I was getting the same issue with the Wildfly application server running on Temurin jdk8u362 using mysql-connector-java-8.0.15 to connect to MySQL 8, the issue disappeared just by updating to the latest versions of Temurin JDK 8 and Connector/J to date (jdk8u372-b07, com.mysql.mysql-connector-j:8.0.33).

jpangamarca
  • 713
  • 2
  • 13
  • 33