Skip to content

HHH-19280: reproducer #493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions orm/hibernate-orm-6/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-hikaricp</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-jdbc</artifactId>
<version>2.14.0-alpha</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package org.hibernate.bugs;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please add

/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright Red Hat Inc. and Hibernate Authors
 */

to the class?
Thanks

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can but actually is this correct? it's a copy paste of HikariCPConnectionProvider which have:

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */

Also, ideally, if you know of a way to do without hikaricp, it would be even better :) is there some idiomatic way of wrapping the DataSource used in the tests without implementing my own ConnectionProvider for example?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I'll try to figure it out. Thanks again for the reproducer.


import com.zaxxer.hikari.*;
import io.opentelemetry.api.*;
import io.opentelemetry.instrumentation.jdbc.datasource.*;
import org.hibernate.*;
import org.hibernate.dialect.*;
import org.hibernate.engine.jdbc.connections.internal.*;
import org.hibernate.engine.jdbc.connections.spi.*;
import org.hibernate.hikaricp.internal.*;
import org.hibernate.internal.log.*;
import org.hibernate.internal.util.*;
import org.hibernate.service.*;
import org.hibernate.service.spi.*;

import javax.sql.*;
import java.sql.*;
import java.util.*;

import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess;

/**
* Copy paste from {@link HikariCPConnectionProvider} because I couldn't find another
* way of wrapping a ds without having to parse the url and configuration ^^
*/
public class MyConnectionProvider implements ConnectionProvider, Configurable, Stoppable {

private static final long serialVersionUID = -9131625057941275711L;
private boolean isMetadataAccessAllowed = true;

/**
* HikariCP configuration.
*/
private HikariConfig hcfg = null;

/**
* HikariCP data source.
*/
private HikariDataSource hds = null;

private DataSource ds = null;

// *************************************************************************
// Configurable
// *************************************************************************

@Override
public void configure(Map<String, Object> props) throws HibernateException {
try {
isMetadataAccessAllowed = allowJdbcMetadataAccess( props );

ConnectionInfoLogger.INSTANCE.configureConnectionPool( "HikariCP" );

hcfg = HikariConfigurationUtil.loadConfiguration( props );
hds = new HikariDataSource( hcfg );

// this is the DataSource that will not always work as expected by hibernate
// see https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/13580
ds = JdbcTelemetry.builder(OpenTelemetry.noop())
.build()
.wrap(hds);
}
catch (Exception e) {
ConnectionInfoLogger.INSTANCE.unableToInstantiateConnectionPool( e );
throw new HibernateException( e );
}
}

// *************************************************************************
// ConnectionProvider
// *************************************************************************

@Override
public Connection getConnection() throws SQLException {
return ds != null ? ds.getConnection() : null;
}

@Override
public void closeConnection(Connection connection) throws SQLException {
connection.close();
}

@Override
public boolean supportsAggressiveRelease() {
return false;
}

@Override
public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
return new DatabaseConnectionInfoImpl(
hcfg.getJdbcUrl(),
// Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to
// the database metadata is allowed
!StringHelper.isBlank( hcfg.getDriverClassName() ) ? hcfg.getDriverClassName() : extractDriverNameFromMetadata(),
dialect.getVersion(),
Boolean.toString( hcfg.isAutoCommit() ),
hcfg.getTransactionIsolation(),
hcfg.getMinimumIdle(),
hcfg.getMaximumPoolSize()
);
}

private String extractDriverNameFromMetadata() {
if (isMetadataAccessAllowed) {
try ( Connection conn = getConnection() ) {
DatabaseMetaData dbmd = conn.getMetaData();
return dbmd.getDriverName();
}
catch (SQLException e) {
// Do nothing
}
}
return null;
}

@Override
public boolean isUnwrappableAs(Class<?> unwrapType) {
return ConnectionProvider.class.equals( unwrapType )
|| HikariCPConnectionProvider.class.isAssignableFrom( unwrapType )
|| DataSource.class.isAssignableFrom( unwrapType );
}

@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType )
|| HikariCPConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( HikariDataSource.class.isAssignableFrom( unwrapType ) ) {
return (T) hds;
}
else if ( DataSource.class.isAssignableFrom( unwrapType ) ) {
return (T) ds;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}

// *************************************************************************
// Stoppable
// *************************************************************************

@Override
public void stop() {
if ( hds != null ) {
ConnectionInfoLogger.INSTANCE.cleaningUpConnectionPool( "HikariCP" );
hds.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
*/
package org.hibernate.bugs;

import jakarta.persistence.*;
import org.hibernate.cfg.AvailableSettings;

import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.*;

import java.math.*;

/**
* This template demonstrates how to develop a test case for Hibernate ORM, using its built-in unit test framework.
Expand All @@ -34,37 +37,44 @@
* submit it as a PR!
*/
@DomainModel(
annotatedClasses = {
// Add your entities here.
// Foo.class,
// Bar.class
},
// If you use *.hbm.xml mappings, instead of annotations, add the mappings here.
xmlMappings = {
// "org/hibernate/test/Foo.hbm.xml",
// "org/hibernate/test/Bar.hbm.xml"
}
annotatedClasses = {
// Add your entities here.
ORMUnitTestCase.Foo.class,
// Bar.class
},
// If you use *.hbm.xml mappings, instead of annotations, add the mappings here.
xmlMappings = {
// "org/hibernate/test/Foo.hbm.xml",
// "org/hibernate/test/Bar.hbm.xml"
}
)
@ServiceRegistry(
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults.
settings = {
// For your own convenience to see generated queries:
@Setting(name = AvailableSettings.SHOW_SQL, value = "true"),
@Setting(name = AvailableSettings.FORMAT_SQL, value = "true"),
// @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ),
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults.
settings = {
// For your own convenience to see generated queries:
@Setting(name = AvailableSettings.SHOW_SQL, value = "true"),
@Setting(name = AvailableSettings.FORMAT_SQL, value = "true"),
// @Setting( name = AvailableSettings.GENERATE_STATISTICS, value = "true" ),

// Add your own settings that are a part of your quarkus configuration:
// @Setting( name = AvailableSettings.SOME_CONFIGURATION_PROPERTY, value = "SOME_VALUE" ),
}
// Add your own settings that are a part of your quarkus configuration:
@Setting( name = AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.bugs.MyConnectionProvider"),
}
)
@SessionFactory
class ORMUnitTestCase {

// Add your tests, using standard JUnit 5.
@Test
void hhh123Test(SessionFactoryScope scope) throws Exception {
scope.inTransaction( session -> {
// Do stuff...
} );
}
// Add your tests, using standard JUnit 5.
@Test
void hhh123Test(SessionFactoryScope scope) throws Exception {
scope.inTransaction(session -> {
session.persist(new Foo());
});
}

@Entity
static class Foo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
}
}
3 changes: 3 additions & 0 deletions orm/hibernate-orm-6/src/test/resources/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Root logger level
rootLogger.level = info

logger.0.name = org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl
logger.0.level = debug

# Root logger referring to console appender
rootLogger.appenderRef.stdout.ref = consoleLogger