createArrayOf AbstractMethodError - jdbc

I am trying to insert an array to postgres using java code , but I always get this error :
SEVERE [http-nio-8080-exec-2]org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service()
for servlet [] in context with path [/] threw exception
[Servlet execution threw an exception] with root cause
java.lang.AbstractMethodError:
com.mchange.v2.c3p0.impl.NewProxyConnection.createArrayOf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/sql/Array;
Code Used
pst = getConnection().prepareStatement(INSERT_QUERY,PreparedStatement.RETURN_GENERATED_KEYS);
pst.setString(1, t.getname());
pst.setString(2, t.getEmail());
Array itemIds = conn.createArrayOf("bigint", t.getItemIds());
pst.setArray(3, itemIds);
If I run the function through main class it works fine , but after deploying to tomcat server, http calls fail with above error .
DB Used - Postgres
JDBC Driver postgres-9.1-901-1.jdbc4
c3p0-0.9.5-pre10
tomcat-8.0.24
As per research I have done , createArrayOf() supposed to work with jdbc4 and c3p0-0.9.5 .
Using this works fine , but I don't see it as right approach
if (conn instanceof C3P0ProxyConnection) {
C3P0ProxyConnection proxy = (C3P0ProxyConnection) conn;
try {
Method m = Connection.class.getMethod("createArrayOf", String.class, Object[].class);
Object[] args = { "bigint", t.getItemIds() };
itemIds = (Array) proxy.rawConnectionOperation(m, C3P0ProxyConnection.RAW_CONNECTION, args);
} catch (IllegalArgumentException e) {
throw new SQLException(e);
}
} else {
itemIds = conn.createArrayOf("bigint", t.getItemIds());
}
Need help .
Thanks

I strongly suspect that you have an older version of c3p0 somewhere in your application's effective CLASSPATH. I've downloaded and verified from c3p0-0.9.5-pre10.jar and c3p0-0.9.5.1.jar on Maven Central that com.mchange.v2.c3p0.impl.NewProxyConnection does in fact contain the createArrayOf method.
% javap -sysinfo -cp ./c3p0-0.9.5.1.jar com.mchange.v2.c3p0.impl.NewProxyConnection
Classfile jar:file:/Users/swaldman/tmp/c3p0jars/c3p0-0.9.5.1.jar!/com/mchange/v2/c3p0/impl/NewProxyConnection.class
Last modified Jun 16, 2015; size 27098 bytes
MD5 checksum c1ff36b87219ddc84c92fb6c1445a2d1
Compiled from "NewProxyConnection.java"
public final class com.mchange.v2.c3p0.impl.NewProxyConnection implements java.sql.Connection,com.mchange.v2.c3p0.C3P0ProxyConnection {
//...
public synchronized java.sql.Array createArrayOf(java.lang.String, java.lang.Object[]) throws java.sql.SQLException;
//...
}
Although this is not likely the cause of your problem, I recommend that you do upgrade to c3p0-0.9.5.1 rather than using the prerelease version.
To see what version of c3p0 your application is actually using, look at INFO in your log files for the banner printed when the c3p0 library is initialized. It should look something like this:
INFO: Initializing c3p0-0.9.5.1 [built 16-June-2015 00:06:36 -0700; debug? true; trace: 10]
I suspect that you will see an older version, that somewhere, perhaps among the transitive dependencies, you are pulling in 0.9.1.x or 0.9.2.x versions of the library.
Good luck!

I can see you are using old version of the c3p0 library.
if you are using maven, update the library to higher version in you pom file from
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
to
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
I hope it help someone.

Updating dependency to following solved my problem.
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

Related

The web application [AuthShop] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it [duplicate]

I am getting this message when I run my web application. It runs fine but I get this message during shutdown.
SEVERE: A web application registered the JBDC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Any help appreciated.
Since version 6.0.24, Tomcat ships with a memory leak detection feature, which in turn can lead to this kind of warning messages when there's a JDBC 4.0 compatible driver in the webapp's /WEB-INF/lib which auto-registers itself during webapp's startup using the ServiceLoader API, but which did not auto-deregister itself during webapp's shutdown. This message is purely informal, Tomcat has already taken the memory leak prevention action accordingly.
What can you do?
Ignore those warnings. Tomcat is doing its job right. The actual bug is in someone else's code (the JDBC driver in question), not in yours. Be happy that Tomcat did its job properly and wait until the JDBC driver vendor get it fixed so that you can upgrade the driver. On the other hand, you aren't supposed to drop a JDBC driver in webapp's /WEB-INF/lib, but only in server's /lib. If you still keep it in webapp's /WEB-INF/lib, then you should manually register and deregister it using a ServletContextListener.
Downgrade to Tomcat 6.0.23 or older so that you will not be bothered with those warnings. But it will silently keep leaking memory. Not sure if that's good to know after all. Those kind of memory leaks are one of the major causes behind OutOfMemoryError issues during Tomcat hotdeployments.
Move the JDBC driver to Tomcat's /lib folder and have a connection pooled datasource to manage the driver. Note that Tomcat's builtin DBCP does not deregister drivers properly on close. See also bug DBCP-322 which is closed as WONTFIX. You would rather like to replace DBCP by another connection pool which is doing its job better then DBCP. For example HikariCP or perhaps Tomcat JDBC Pool.
In your servlet context listener contextDestroyed() method, manually deregister the drivers:
// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
}
}
Although Tomcat does forcibly deregister the JDBC driver for you, it is nonetheless good practice to clean up all resources created by your webapp on context destruction in case you move to another servlet container which doesn't do the memory leak prevention checks that Tomcat does.
However, the methodology of blanket driver deregistration is dangerous. Some drivers returned by the DriverManager.getDrivers() method may have been loaded by the parent ClassLoader (i.e., the servlet container's classloader) not the webapp context's ClassLoader (e.g., they may be in the container's lib folder, not the webapp's, and therefore shared across the whole container). Deregistering these will affect any other webapps which may be using them (or even the container itself).
Therefore, one should check that the ClassLoader for each driver is the webapp's ClassLoader before deregistering it. So, in your ContextListener's contextDestroyed() method:
public final void contextDestroyed(ServletContextEvent sce) {
// ... First close any background tasks which may be using the DB ...
// ... Then close any DB connection pools ...
// Now deregister JDBC drivers in this context's ClassLoader:
// Get the webapp's ClassLoader
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// Loop through all drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
// This driver was registered by the webapp's ClassLoader, so deregister it:
try {
log.info("Deregistering JDBC driver {}", driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
log.error("Error deregistering JDBC driver {}", driver, ex);
}
} else {
// driver was not registered by the webapp's ClassLoader and may be in use elsewhere
log.trace("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
}
}
}
I see this issue come up a lot. Yes, Tomcat 7 does automatically deregister it, but it that REALLY taking control of your code and a good coding practice? Surely YOU want to know that you have all the correct code in place to close all your objects, shut down database connection pool threads, and get rid of all warnings. I certainly do.
This is how I do it.
Step 1: Register a Listener
web.xml
<listener>
<listener-class>com.mysite.MySpecialListener</listener-class>
</listener>
Step 2: Implement the Listener
com.mysite.MySpecialListener.java
public class MySpecialListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
// On Application Startup, please…
// Usually I'll make a singleton in here, set up my pool, etc.
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
// On Application Shutdown, please…
// 1. Go fetch that DataSource
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource datasource = (DataSource)envContext.lookup("jdbc/database");
// 2. Deregister Driver
try {
java.sql.Driver mySqlDriver = DriverManager.getDriver("jdbc:mysql://localhost:3306/");
DriverManager.deregisterDriver(mySqlDriver);
} catch (SQLException ex) {
logger.info("Could not deregister driver:".concat(ex.getMessage()));
}
// 3. For added safety, remove the reference to dataSource for GC to enjoy.
dataSource = null;
}
}
Please feel free to comment and/or add...
This is purely driver registration/deregistration issue in mysql`s driver or tomcats webapp-classloader. Copy mysql driver into tomcats lib folder (so its loaded by jvm directly, not by tomcat), and message will be gone. That makes mysql jdbc driver to be unloaded only at JVM shutdown, and noone cares about memory leaks then.
If you are getting this message from a Maven built war change the scope of the JDBC driver to provided, and put a copy of it in the lib directory. Like this:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
<!-- put a copy in /usr/share/tomcat7/lib -->
<scope>provided</scope>
</dependency>
Solution for per-app deployments
This is a listener I wrote to solve the problem: it autodetects if the driver has registered itself and acts accordingly.it
Important: it is meant to be used ONLY when the driver jar is deployed in WEB-INF/lib, not in the Tomcat /lib, as many suggest, so that each application can take care of its own driver and run on a untouched Tomcat. That is the way it should be IMHO.
Just configure the listener in your web.xml before any other and enjoy.
add near the top of web.xml:
<listener>
<listener-class>utils.db.OjdbcDriverRegistrationListener</listener-class>
</listener>
save as utils/db/OjdbcDriverRegistrationListener.java:
package utils.db;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import oracle.jdbc.OracleDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Registers and unregisters the Oracle JDBC driver.
*
* Use only when the ojdbc jar is deployed inside the webapp (not as an
* appserver lib)
*/
public class OjdbcDriverRegistrationListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory
.getLogger(OjdbcDriverRegistrationListener.class);
private Driver driver = null;
/**
* Registers the Oracle JDBC driver
*/
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
this.driver = new OracleDriver(); // load and instantiate the class
boolean skipRegistration = false;
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver instanceof OracleDriver) {
OracleDriver alreadyRegistered = (OracleDriver) driver;
if (alreadyRegistered.getClass() == this.driver.getClass()) {
// same class in the VM already registered itself
skipRegistration = true;
this.driver = alreadyRegistered;
break;
}
}
}
try {
if (!skipRegistration) {
DriverManager.registerDriver(driver);
} else {
LOG.debug("driver was registered automatically");
}
LOG.info(String.format("registered jdbc driver: %s v%d.%d", driver,
driver.getMajorVersion(), driver.getMinorVersion()));
} catch (SQLException e) {
LOG.error(
"Error registering oracle driver: " +
"database connectivity might be unavailable!",
e);
throw new RuntimeException(e);
}
}
/**
* Deregisters JDBC driver
*
* Prevents Tomcat 7 from complaining about memory leaks.
*/
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (this.driver != null) {
try {
DriverManager.deregisterDriver(driver);
LOG.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
LOG.warn(
String.format("Error deregistering driver %s", driver),
e);
}
this.driver = null;
} else {
LOG.warn("No driver to deregister");
}
}
}
I will add to this something I found on the Spring forums. If you move your JDBC driver jar to the tomcat lib folder, instead of deploying it with your webapp, the warning seems to disappear. I can confirm that this worked for me
http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883
I found that implementing a simple destroy() method to de-register any JDBC drivers works nicely.
/**
* Destroys the servlet cleanly by unloading JDBC drivers.
*
* #see javax.servlet.GenericServlet#destroy()
*/
public void destroy() {
String prefix = getClass().getSimpleName() +" destroy() ";
ServletContext ctx = getServletContext();
try {
Enumeration<Driver> drivers = DriverManager.getDrivers();
while(drivers.hasMoreElements()) {
DriverManager.deregisterDriver(drivers.nextElement());
}
} catch(Exception e) {
ctx.log(prefix + "Exception caught while deregistering JDBC drivers", e);
}
ctx.log(prefix + "complete");
}
To prevent this memory leak, simply deregister the driver on context shutdown.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mywebsite</groupId>
<artifactId>emusicstore</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.9</source>
<target>1.9</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
MyWebAppContextListener.java
package com.emusicstore.utils;
import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
public class MyWebAppContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("************** Starting up! **************");
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("************** Shutting down! **************");
System.out.println("Destroying Context...");
System.out.println("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
AbandonedConnectionCleanupThread.checkedShutdown();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (driver.getClass().getClassLoader() == cl) {
try {
System.out.println("Deregistering JDBC driver {}");
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
System.out.println("Error deregistering JDBC driver {}");
ex.printStackTrace();
}
} else {
System.out.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
}
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>com.emusicstore.utils.MyWebAppContextListener</listener-class>
</listener>
<!-- ... -->
</web-app>
Source that inspired me for this bug fix.
I was having a similar problem, but additionally I was getting a Java Heap Space error anytime I modified/saved JSP pages with Tomcat server running, therefore the context were not fully recharged.
My versions were Apache Tomcat 6.0.29 and JDK 6u12.
Upgrading JDK to 6u21 as suggested in References section of URL http://wiki.apache.org/tomcat/MemoryLeakProtection solved the Java Heap Space problem (context now reloads OK) although JDBC Driver error still appears.
I found the same issue with Tomcat version 6.026.
I used the Mysql JDBC.jar in WebAPP Library as well as in TOMCAT Lib.
To fix the above by removing the Jar from the TOMCAT lib folder.
So what I understand is that TOMCAT is handling the JDBC memory leak properly. But if the MYSQL Jdbc jar is duplicated in WebApp and Tomcat Lib, Tomcat will only be able to handle the jar present in the Tomcat Lib folder.
I have faced this problem when I was deploying my Grails application on AWS. This is matter of JDBC default driver org.h2 driver .
As you can see this in the Datasource.groovy inside your configuration folder . As you can see below :
dataSource {
pooled = true
jmxExport = true
driverClassName = "org.h2.Driver" // make this one comment
username = "sa"
password = ""
}
Comment those lines wherever there is mentioned org.h2.Driver in the datasource.groovy file , if you are not using that database .
Otherwise you have to download that database jar file .
Thanks .
This error happened to me in a Grails Application with the JTDS Driver 1.3.0 (SQL Server). The problem was an incorrect login in SQL Server. After solve this issue (in SQL Server) my app was correctly deployed in Tomcat. Tip: I saw the error in stacktrace.log

Debezium MySQL Connector- com.mysql.cj.CharsetMapping.getStaticCollationNameForCollationIndex(Ljava/lang/Integer;)Ljava/lang/String

Debezium mysql connector fail at final stage of snapshotting.
The project is on maven/quarkus , and I want to use debezium/infinispan for cache invalidation .
The Observer and configuration looks like this :
public void startEmbeddedEngine(#Observes #Initialized(ApplicationScoped.class) Object init) throws IOException {
File dbHistoryTempFile = File.createTempFile("offsets", ".dat");
File offsetStorageTempFile = File.createTempFile("dbhistory", ".dat");
final Properties props = new Properties();
props.setProperty("name", "cache-invalidation-engine");
props.setProperty("connector.class", "io.debezium.connector.mysql.MySqlConnector");
props.setProperty("offset.storage.file.filename", offsetStorageTempFile.getAbsolutePath());
props.setProperty("offset.flush.interval.ms", "0");
props.setProperty("database.hostname", "localhost");
props.setProperty("database.port", "3306");
props.setProperty("database.user", "root");
props.setProperty("database.password", "password");
props.setProperty("database.server.id", "1");
props.setProperty("database.server.name", "new_feature");
props.setProperty("database.history",
"io.debezium.relational.history.FileDatabaseHistory");
props.setProperty("database.history.file.filename", dbHistoryTempFile.getAbsolutePath());
props.setProperty("database.include.list", "database");
// props.setProperty("database.history.file.filename","C:/Users/a.pogonet/AppData/Local/Temp/db.dat");
props.setProperty("snapshot.mode", "never");
// props.setProperty("include.unknown.datatypes", "true");
// props.setProperty("include.schema.changes", "false");
DebeziumEngine<ChangeEvent<String, String>> engine = DebeziumEngine.create(Json.class)
.using(props)
.notifying(record -> {
System.out.println(record);
}).build();
executorService = Executors.newSingleThreadExecutor();
executorService.execute(engine);
}
2021-12-09 14:18:34,137 INFO [io.deb.con.mys.MySqlStreamingChangeEventSource] (blc-localhost:3306) Stopped reading binlog after 0 events, no new offset was recorded
Exception in thread "blc-localhost:3306" java.lang.NoSuchMethodError: com.mysql.cj.CharsetMapping.getStaticCollationNameForCollationIndex(Ljava/lang/Integer;)Ljava/lang/String;
at io.debezium.connector.mysql.antlr.MySqlAntlrDdlParser.extractCharset(MySqlAntlrDdlParser.java:404)
at io.debezium.connector.mysql.antlr.listener.CreateAndAlterDatabaseParserListener.enterCreateDatabaseOption(CreateAndAlterDatabaseParserListener.java:49)
at io.debezium.ddl.parser.mysql.generated.MySqlParser$CreateDatabaseOptionContext.enterRule(MySqlParser.java:5912)
at io.debezium.antlr.ProxyParseTreeListenerUtil.delegateEnterRule(ProxyParseTreeListenerUtil.java:46)
at io.debezium.connector.mysql.antlr.listener.MySqlAntlrDdlParserListener.enterEveryRule(MySqlAntlrDdlParserListener.java:89)
at org.antlr.v4.runtime.tree.ParseTreeWalker.enterRule(ParseTreeWalker.java:41)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:25)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
at org.antlr.v4.runtime.tree.ParseTreeWalker.walk(ParseTreeWalker.java:28)
at io.debezium.antlr.AntlrDdlParser.parse(AntlrDdlParser.java:87)
at io.debezium.connector.mysql.MySqlDatabaseSchema.parseDdl(MySqlDatabaseSchema.java:216)
at io.debezium.connector.mysql.MySqlDatabaseSchema.parseStreamingDdl(MySqlDatabaseSchema.java:202)
at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.handleQueryEvent(MySqlStreamingChangeEventSource.java:573)
at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.lambda$execute$14(MySqlStreamingChangeEventSource.java:827)
at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.handleEvent(MySqlStreamingChangeEventSource.java:349)
at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.lambda$execute$25(MySqlStreamingChangeEventSource.java:855)
at com.github.shyiko.mysql.binlog.BinaryLogClient.notifyEventListeners(BinaryLogClient.java:1125)
at com.github.shyiko.mysql.binlog.BinaryLogClient.listenForEventPackets(BinaryLogClient.java:973)
at com.github.shyiko.mysql.binlog.BinaryLogClient.connect(BinaryLogClient.java:599)
at com.github.shyiko.mysql.binlog.BinaryLogClient$7.run(BinaryLogClient.java:857)
at java.base/java.lang.Thread.run(Thread.java:834)
The Quarkus BOM is enforcing a version of the MySQL driver and AFAICS Debezium is using methods that are not available anymore in this version of the driver.
What I recommend you is to use the version of the driver used by the Debezium connector by overriding the version manually in your project.
I can't tell you exactly which version to use given I have no idea which Debezium version you are using. But the version is there for Debezium 1.8: https://github.com/debezium/debezium/blob/1.8/pom.xml#L120 .
That being said, Quarkus 2.5.1.Final+ is also using MySQL Connector 8.0.27 so if you use these versions, I believe it should work.
you need update mysql driver to 8.0.27
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>

Configure HTTPS in Spring Boot Apache Camel REST API with keystore having multiple certs using camel-jetty component

I am trying to configure https in my apache camel Spring Boot REST application (using apache-camel v3.11.1, springboot v2.5.3) with keystore having multiple certificates.
Problem:
Application run failed
org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: KeyStores with multiple certificates are not supported on the base class org.eclipse.jetty.util.ssl.SslContextFactory. (Use org.eclipse.jetty.util.ssl.SslContextFactory$Server or org.eclipse.jetty.util.ssl.SslContextFactory$Client instead)
at org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException(RuntimeCamelException.java:51) ~[camel-api-3.11.1.jar:3.11.1]
Project setup:
pom.xml: (dependencies only, to show that I am not using spring-boot-web-starter)
..
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jetty-starter</artifactId>
</dependency>
..
..<!-- all other required dependencies are in place-->
..
</dependencies>
..
application.properties
#camel.component.jetty.keystore=keystore-with-one-certificate.jks # WORKS
camel.component.jetty.keystore=keystore-with-multiple-certificates.jks # DOESN'T WORK
camel.component.jetty.ssl-key-password=password
camel.component.jetty.ssl-password=password
Rest Route:
restConfiguration()
.component("jetty")
.scheme("https")
.port("8080");
rest()
.path("/api")
.get("/{name}")
..
..
.to("direct:x");
Looked at answers in the below posts, but still not able to resolve the exception that I get,
https://stackoverflow.com/a/60598953/6363894,
https://stackoverflow.com/a/55499113/6363894
I know that exception clearly states to use org.eclipse.jetty.util.ssl.SslContextFactory$Server, but I don't understand how/where to use SslContextFactory.Server object.
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(findKeyStorePath());
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
sslContextFactory.setNeedClientAuth(true);
Also I've created a bean for sslContextParameters and added that to restConfiguration as below, this time application runs successfully but then when I test, SSL handshake fails.
restConfiguration()
.component("jetty")
.endpointProperty("sslContextParameters", "#sslContextParameters")
.scheme("https")
.port("8080");
#Bean(name = "sslContextParameters")
public SSLContextParameters setSSLContextParameters() {
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("keystore-with-multiple-certificates.jks");
ksp.setPassword("password");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("password");
SSLContextServerParameters scsp = new SSLContextServerParameters();
scsp.setClientAuthentication("REQUIRE");
SSLContextParameters scp = new SSLContextParameters();
scp.setServerParameters(scsp);
scp.setKeyManagers(kmp);
return scp;
}
Any help on how to configure SslContextFactory.Server object with the restConfigurations() or any other way I can achieve this? I'll update the post, if any more details are required.

Spring - Websockets - JSR-356

I implemented websockets into my application. I copied the configuration and dependencies from jHipster generated app, but I am getting the following errors:
java.lang.IllegalArgumentException: No 'javax.websocket.server.ServerContainer' ServletContext attribute. Are you running in a Servlet container that supports JSR-356?
and
org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
I believe these errors are the reason for the socket connection not being consistent and the therefore the client is not able to send and/or receive any messages.
I searched for a solution but other post didn't help (ie. adding glassfish dependencies).
These are my ws dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-messaging</artifactId>
</dependency>
Do I need to include some other dependencies or is the problem elsewhere?
I found a solution here.
I added these 2 beans:
#Bean
public TomcatServletWebServerFactory tomcatContainerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();;
factory.setTomcatContextCustomizers(Collections.singletonList(tomcatContextCustomizer()));
return factory;
}
#Bean
public TomcatContextCustomizer tomcatContextCustomizer() {
return new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.addServletContainerInitializer(new WsSci(), null);
}
};
}

Connecting Springboot application to Azure databricks

I'm trying to connect SpringBoot Application to Azure Databricks.
Below is something I have tried....
application.properties
spring.datasource.url = jdbc:spark://adb-**********.*.azuredatabricks.net:**/default;transportMode=http;ssl=1;httpPath=sql/protocolv1/o/******/******-*****-abcd341
spring.datasource.username = username
spring.datasource.password = Generated Token
pom.xml
Below are some dependencies I'm using...
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.10</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.databricks</groupId>
<artifactId>spark-avro_2.10</artifactId>
<version>2.0.1</version>
</dependency>
I'm getting below error..
***************************
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 (no profiles are currently active).
Suggest me if I'm missing any maven dependency.
Thanks in Advance..
To connect from the Spring Boot you need to use JDBC driver, not Spark jars (remove them - you don't need them). You can get JDBC driver as described in documentation, or very recently - directly via Maven using following coordinates:
<dependency>
<groupId>com.databricks</groupId>
<artifactId>databricks-jdbc</artifactId>
<version>2.6.25-1</version>
</dependency>
and then use standard JDBC APIs exposed by Spring. I have a simple example that uses JdbcTemplate to access data in Databricks - you just need to construct JDBC URL correctly:
String host = "";
String httpPath = "";
String token = "";
String jdbcUrl = "jdbc:databricks://" + host +
":443/default;transportMode=http;ssl=1;httpPath=" +
httpPath + ";AuthMech=3;UID=token;PWD=" + token;
and then just access data:
// define data source
SimpleDriverDataSource ds = new SimpleDriverDataSource();
ds.setDriver(new Driver());
ds.setUrl(jdbcUrl);
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
// query data
List<Map<String, Object>> data = jdbcTemplate.queryForList(query);
for (Map<String, Object> row: data) {
....
}
P.S. You may omit username or at least set it to the token value...
Try adding the "spring.datasource.driverClassName" , and let me know if that helps you to proceed

Resources