Merge pull request #1164 from DataDog/tyler/jdbc-error-handling

Better error handling for getClientInfo in JDBCDecorator
This commit is contained in:
Tyler Benson 2020-01-09 09:20:46 -08:00 committed by GitHub
commit 6b9c92eefa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1292 additions and 18 deletions

View File

@ -69,7 +69,12 @@ public class JDBCDecorator extends DatabaseClientDecorator<DBInfo> {
final DatabaseMetaData metaData = connection.getMetaData();
final String url = metaData.getURL();
if (url != null) {
dbInfo = JDBCConnectionUrlParser.parse(url, connection.getClientInfo());
try {
dbInfo = JDBCConnectionUrlParser.parse(url, connection.getClientInfo());
} catch (final Exception ex) {
// getClientInfo is likely not allowed.
dbInfo = JDBCConnectionUrlParser.parse(url, null);
}
} else {
dbInfo = DBInfo.DEFAULT;
}

View File

@ -30,13 +30,16 @@ public abstract class JDBCUtils {
connection = connection.unwrap(Connection.class);
}
} catch (final Exception | AbstractMethodError e) {
// Attempt to work around c3po delegating to an connection that doesn't support unwrapping.
final Class<? extends Connection> connectionClass = connection.getClass();
if (connectionClass.getName().equals("com.mchange.v2.c3p0.impl.NewProxyConnection")) {
final Field inner = connectionClass.getDeclaredField("inner");
inner.setAccessible(true);
c3poField = inner;
return (Connection) c3poField.get(connection);
if (connection != null) {
// Attempt to work around c3po delegating to an connection that doesn't support
// unwrapping.
final Class<? extends Connection> connectionClass = connection.getClass();
if (connectionClass.getName().equals("com.mchange.v2.c3p0.impl.NewProxyConnection")) {
final Field inner = connectionClass.getDeclaredField("inner");
inner.setAccessible(true);
c3poField = inner;
return (Connection) c3poField.get(connection);
}
}
// perhaps wrapping isn't supported?

View File

@ -10,6 +10,8 @@ import org.h2.Driver
import org.hsqldb.jdbc.JDBCDriver
import spock.lang.Shared
import spock.lang.Unroll
import test.TestConnection
import test.TestStatement
import javax.sql.DataSource
import java.sql.CallableStatement
@ -475,7 +477,6 @@ class JDBCInstrumentationTest extends AgentTestRunner {
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE PS_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
}
@Unroll
@ -485,7 +486,7 @@ class JDBCInstrumentationTest extends AgentTestRunner {
when:
try {
connection = new DummyThrowingConnection()
connection = new TestConnection(true)
} catch (Exception e) {
connection = driverClass.connect(url, null)
}
@ -549,6 +550,52 @@ class JDBCInstrumentationTest extends AgentTestRunner {
false | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
}
def "test getClientInfo exception"() {
setup:
Connection connection = new TestConnection(false)
when:
Statement statement = null
runUnderTrace("parent") {
statement = connection.createStatement()
return statement.executeQuery(query)
}
then:
assertTraces(1) {
trace(0, 2) {
basicSpan(it, 0, "parent")
span(1) {
operationName "${database}.query"
serviceName database
resourceName query
spanType DDSpanTypes.SQL
childOf span(0)
errored false
tags {
"$Tags.COMPONENT" "java-jdbc-statement"
"$Tags.SPAN_KIND" Tags.SPAN_KIND_CLIENT
"$Tags.DB_TYPE" database
"span.origin.type" TestStatement.name
defaultTags()
}
}
}
}
cleanup:
if (statement != null) {
statement.close()
}
if (connection != null) {
connection.close()
}
where:
database = "testdb"
query = "testing 123"
}
@Unroll
def "#connectionPoolName connections should be cached in case of wrapped connections"() {
setup:

View File

@ -1,3 +1,5 @@
package test
import java.sql.Array
import java.sql.Blob
import java.sql.CallableStatement
@ -17,16 +19,19 @@ import java.util.concurrent.Executor
/**
* A JDBC connection class that throws an exception in the constructor, used to test
* A JDBC connection class that optionally throws an exception in the constructor, used to test
*/
class DummyThrowingConnection implements Connection {
DummyThrowingConnection() {
throw new RuntimeException("Dummy exception")
class TestConnection implements Connection {
TestConnection(boolean throwException) {
if (throwException) {
throw new RuntimeException("connection exception")
}
}
@Override
Statement createStatement() throws SQLException {
return null
return new TestStatement(this)
}
@Override
@ -76,7 +81,7 @@ class DummyThrowingConnection implements Connection {
@Override
DatabaseMetaData getMetaData() throws SQLException {
return null
return new TestDatabaseMetaData()
}
@Override
@ -241,12 +246,12 @@ class DummyThrowingConnection implements Connection {
@Override
String getClientInfo(String name) throws SQLException {
return null
throw new UnsupportedOperationException("Test 123")
}
@Override
Properties getClientInfo() throws SQLException {
return null
throw new UnsupportedOperationException("Test 123")
}
@Override

View File

@ -0,0 +1,889 @@
package test
import java.sql.Connection
import java.sql.DatabaseMetaData
import java.sql.ResultSet
import java.sql.RowIdLifetime
import java.sql.SQLException
class TestDatabaseMetaData implements DatabaseMetaData {
@Override
boolean allProceduresAreCallable() throws SQLException {
return false
}
@Override
boolean allTablesAreSelectable() throws SQLException {
return false
}
@Override
String getURL() throws SQLException {
return "jdbc:testdb://localhost"
}
@Override
String getUserName() throws SQLException {
return null
}
@Override
boolean isReadOnly() throws SQLException {
return false
}
@Override
boolean nullsAreSortedHigh() throws SQLException {
return false
}
@Override
boolean nullsAreSortedLow() throws SQLException {
return false
}
@Override
boolean nullsAreSortedAtStart() throws SQLException {
return false
}
@Override
boolean nullsAreSortedAtEnd() throws SQLException {
return false
}
@Override
String getDatabaseProductName() throws SQLException {
return null
}
@Override
String getDatabaseProductVersion() throws SQLException {
return null
}
@Override
String getDriverName() throws SQLException {
return null
}
@Override
String getDriverVersion() throws SQLException {
return null
}
@Override
int getDriverMajorVersion() {
return 0
}
@Override
int getDriverMinorVersion() {
return 0
}
@Override
boolean usesLocalFiles() throws SQLException {
return false
}
@Override
boolean usesLocalFilePerTable() throws SQLException {
return false
}
@Override
boolean supportsMixedCaseIdentifiers() throws SQLException {
return false
}
@Override
boolean storesUpperCaseIdentifiers() throws SQLException {
return false
}
@Override
boolean storesLowerCaseIdentifiers() throws SQLException {
return false
}
@Override
boolean storesMixedCaseIdentifiers() throws SQLException {
return false
}
@Override
boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
return false
}
@Override
boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
return false
}
@Override
boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
return false
}
@Override
boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
return false
}
@Override
String getIdentifierQuoteString() throws SQLException {
return null
}
@Override
String getSQLKeywords() throws SQLException {
return null
}
@Override
String getNumericFunctions() throws SQLException {
return null
}
@Override
String getStringFunctions() throws SQLException {
return null
}
@Override
String getSystemFunctions() throws SQLException {
return null
}
@Override
String getTimeDateFunctions() throws SQLException {
return null
}
@Override
String getSearchStringEscape() throws SQLException {
return null
}
@Override
String getExtraNameCharacters() throws SQLException {
return null
}
@Override
boolean supportsAlterTableWithAddColumn() throws SQLException {
return false
}
@Override
boolean supportsAlterTableWithDropColumn() throws SQLException {
return false
}
@Override
boolean supportsColumnAliasing() throws SQLException {
return false
}
@Override
boolean nullPlusNonNullIsNull() throws SQLException {
return false
}
@Override
boolean supportsConvert() throws SQLException {
return false
}
@Override
boolean supportsConvert(int fromType, int toType) throws SQLException {
return false
}
@Override
boolean supportsTableCorrelationNames() throws SQLException {
return false
}
@Override
boolean supportsDifferentTableCorrelationNames() throws SQLException {
return false
}
@Override
boolean supportsExpressionsInOrderBy() throws SQLException {
return false
}
@Override
boolean supportsOrderByUnrelated() throws SQLException {
return false
}
@Override
boolean supportsGroupBy() throws SQLException {
return false
}
@Override
boolean supportsGroupByUnrelated() throws SQLException {
return false
}
@Override
boolean supportsGroupByBeyondSelect() throws SQLException {
return false
}
@Override
boolean supportsLikeEscapeClause() throws SQLException {
return false
}
@Override
boolean supportsMultipleResultSets() throws SQLException {
return false
}
@Override
boolean supportsMultipleTransactions() throws SQLException {
return false
}
@Override
boolean supportsNonNullableColumns() throws SQLException {
return false
}
@Override
boolean supportsMinimumSQLGrammar() throws SQLException {
return false
}
@Override
boolean supportsCoreSQLGrammar() throws SQLException {
return false
}
@Override
boolean supportsExtendedSQLGrammar() throws SQLException {
return false
}
@Override
boolean supportsANSI92EntryLevelSQL() throws SQLException {
return false
}
@Override
boolean supportsANSI92IntermediateSQL() throws SQLException {
return false
}
@Override
boolean supportsANSI92FullSQL() throws SQLException {
return false
}
@Override
boolean supportsIntegrityEnhancementFacility() throws SQLException {
return false
}
@Override
boolean supportsOuterJoins() throws SQLException {
return false
}
@Override
boolean supportsFullOuterJoins() throws SQLException {
return false
}
@Override
boolean supportsLimitedOuterJoins() throws SQLException {
return false
}
@Override
String getSchemaTerm() throws SQLException {
return null
}
@Override
String getProcedureTerm() throws SQLException {
return null
}
@Override
String getCatalogTerm() throws SQLException {
return null
}
@Override
boolean isCatalogAtStart() throws SQLException {
return false
}
@Override
String getCatalogSeparator() throws SQLException {
return null
}
@Override
boolean supportsSchemasInDataManipulation() throws SQLException {
return false
}
@Override
boolean supportsSchemasInProcedureCalls() throws SQLException {
return false
}
@Override
boolean supportsSchemasInTableDefinitions() throws SQLException {
return false
}
@Override
boolean supportsSchemasInIndexDefinitions() throws SQLException {
return false
}
@Override
boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
return false
}
@Override
boolean supportsCatalogsInDataManipulation() throws SQLException {
return false
}
@Override
boolean supportsCatalogsInProcedureCalls() throws SQLException {
return false
}
@Override
boolean supportsCatalogsInTableDefinitions() throws SQLException {
return false
}
@Override
boolean supportsCatalogsInIndexDefinitions() throws SQLException {
return false
}
@Override
boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
return false
}
@Override
boolean supportsPositionedDelete() throws SQLException {
return false
}
@Override
boolean supportsPositionedUpdate() throws SQLException {
return false
}
@Override
boolean supportsSelectForUpdate() throws SQLException {
return false
}
@Override
boolean supportsStoredProcedures() throws SQLException {
return false
}
@Override
boolean supportsSubqueriesInComparisons() throws SQLException {
return false
}
@Override
boolean supportsSubqueriesInExists() throws SQLException {
return false
}
@Override
boolean supportsSubqueriesInIns() throws SQLException {
return false
}
@Override
boolean supportsSubqueriesInQuantifieds() throws SQLException {
return false
}
@Override
boolean supportsCorrelatedSubqueries() throws SQLException {
return false
}
@Override
boolean supportsUnion() throws SQLException {
return false
}
@Override
boolean supportsUnionAll() throws SQLException {
return false
}
@Override
boolean supportsOpenCursorsAcrossCommit() throws SQLException {
return false
}
@Override
boolean supportsOpenCursorsAcrossRollback() throws SQLException {
return false
}
@Override
boolean supportsOpenStatementsAcrossCommit() throws SQLException {
return false
}
@Override
boolean supportsOpenStatementsAcrossRollback() throws SQLException {
return false
}
@Override
int getMaxBinaryLiteralLength() throws SQLException {
return 0
}
@Override
int getMaxCharLiteralLength() throws SQLException {
return 0
}
@Override
int getMaxColumnNameLength() throws SQLException {
return 0
}
@Override
int getMaxColumnsInGroupBy() throws SQLException {
return 0
}
@Override
int getMaxColumnsInIndex() throws SQLException {
return 0
}
@Override
int getMaxColumnsInOrderBy() throws SQLException {
return 0
}
@Override
int getMaxColumnsInSelect() throws SQLException {
return 0
}
@Override
int getMaxColumnsInTable() throws SQLException {
return 0
}
@Override
int getMaxConnections() throws SQLException {
return 0
}
@Override
int getMaxCursorNameLength() throws SQLException {
return 0
}
@Override
int getMaxIndexLength() throws SQLException {
return 0
}
@Override
int getMaxSchemaNameLength() throws SQLException {
return 0
}
@Override
int getMaxProcedureNameLength() throws SQLException {
return 0
}
@Override
int getMaxCatalogNameLength() throws SQLException {
return 0
}
@Override
int getMaxRowSize() throws SQLException {
return 0
}
@Override
boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
return false
}
@Override
int getMaxStatementLength() throws SQLException {
return 0
}
@Override
int getMaxStatements() throws SQLException {
return 0
}
@Override
int getMaxTableNameLength() throws SQLException {
return 0
}
@Override
int getMaxTablesInSelect() throws SQLException {
return 0
}
@Override
int getMaxUserNameLength() throws SQLException {
return 0
}
@Override
int getDefaultTransactionIsolation() throws SQLException {
return 0
}
@Override
boolean supportsTransactions() throws SQLException {
return false
}
@Override
boolean supportsTransactionIsolationLevel(int level) throws SQLException {
return false
}
@Override
boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
return false
}
@Override
boolean supportsDataManipulationTransactionsOnly() throws SQLException {
return false
}
@Override
boolean dataDefinitionCausesTransactionCommit() throws SQLException {
return false
}
@Override
boolean dataDefinitionIgnoredInTransactions() throws SQLException {
return false
}
@Override
ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
return null
}
@Override
ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException {
return null
}
@Override
ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException {
return null
}
@Override
ResultSet getSchemas() throws SQLException {
return null
}
@Override
ResultSet getCatalogs() throws SQLException {
return null
}
@Override
ResultSet getTableTypes() throws SQLException {
return null
}
@Override
ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
return null
}
@Override
ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException {
return null
}
@Override
ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
return null
}
@Override
ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException {
return null
}
@Override
ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
return null
}
@Override
ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
return null
}
@Override
ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
return null
}
@Override
ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
return null
}
@Override
ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
return null
}
@Override
ResultSet getTypeInfo() throws SQLException {
return null
}
@Override
ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {
return null
}
@Override
boolean supportsResultSetType(int type) throws SQLException {
return false
}
@Override
boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
return false
}
@Override
boolean ownUpdatesAreVisible(int type) throws SQLException {
return false
}
@Override
boolean ownDeletesAreVisible(int type) throws SQLException {
return false
}
@Override
boolean ownInsertsAreVisible(int type) throws SQLException {
return false
}
@Override
boolean othersUpdatesAreVisible(int type) throws SQLException {
return false
}
@Override
boolean othersDeletesAreVisible(int type) throws SQLException {
return false
}
@Override
boolean othersInsertsAreVisible(int type) throws SQLException {
return false
}
@Override
boolean updatesAreDetected(int type) throws SQLException {
return false
}
@Override
boolean deletesAreDetected(int type) throws SQLException {
return false
}
@Override
boolean insertsAreDetected(int type) throws SQLException {
return false
}
@Override
boolean supportsBatchUpdates() throws SQLException {
return false
}
@Override
ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
return null
}
@Override
Connection getConnection() throws SQLException {
return null
}
@Override
boolean supportsSavepoints() throws SQLException {
return false
}
@Override
boolean supportsNamedParameters() throws SQLException {
return false
}
@Override
boolean supportsMultipleOpenResults() throws SQLException {
return false
}
@Override
boolean supportsGetGeneratedKeys() throws SQLException {
return false
}
@Override
ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
return null
}
@Override
ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
return null
}
@Override
ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException {
return null
}
@Override
boolean supportsResultSetHoldability(int holdability) throws SQLException {
return false
}
@Override
int getResultSetHoldability() throws SQLException {
return 0
}
@Override
int getDatabaseMajorVersion() throws SQLException {
return 0
}
@Override
int getDatabaseMinorVersion() throws SQLException {
return 0
}
@Override
int getJDBCMajorVersion() throws SQLException {
return 0
}
@Override
int getJDBCMinorVersion() throws SQLException {
return 0
}
@Override
int getSQLStateType() throws SQLException {
return 0
}
@Override
boolean locatorsUpdateCopy() throws SQLException {
return false
}
@Override
boolean supportsStatementPooling() throws SQLException {
return false
}
@Override
RowIdLifetime getRowIdLifetime() throws SQLException {
return null
}
@Override
ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
return null
}
@Override
boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
return false
}
@Override
boolean autoCommitFailureClosesAllResultSets() throws SQLException {
return false
}
@Override
ResultSet getClientInfoProperties() throws SQLException {
return null
}
@Override
ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
return null
}
@Override
ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {
return null
}
@Override
ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
return null
}
@Override
boolean generatedKeyAlwaysReturned() throws SQLException {
return false
}
@Override
def <T> T unwrap(Class<T> iface) throws SQLException {
return null
}
@Override
boolean isWrapperFor(Class<?> iface) throws SQLException {
return false
}
}

View File

@ -0,0 +1,45 @@
package test
import java.sql.Connection
import java.sql.Driver
import java.sql.DriverPropertyInfo
import java.sql.SQLException
import java.sql.SQLFeatureNotSupportedException
import java.util.logging.Logger
class TestDriver implements Driver {
@Override
Connection connect(String url, Properties info) throws SQLException {
return new TestConnection("connectException=true" == url)
}
@Override
boolean acceptsURL(String url) throws SQLException {
return false
}
@Override
DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
return new DriverPropertyInfo[0]
}
@Override
int getMajorVersion() {
return 0
}
@Override
int getMinorVersion() {
return 0
}
@Override
boolean jdbcCompliant() {
return false
}
@Override
Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null
}
}

View File

@ -0,0 +1,235 @@
package test
import java.sql.Connection
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.SQLWarning
import java.sql.Statement
class TestStatement implements Statement {
final Connection connection
TestStatement(Connection connection) {
this.connection = connection
}
@Override
ResultSet executeQuery(String sql) throws SQLException {
return null
}
@Override
int executeUpdate(String sql) throws SQLException {
return 0
}
@Override
void close() throws SQLException {
}
@Override
int getMaxFieldSize() throws SQLException {
return 0
}
@Override
void setMaxFieldSize(int max) throws SQLException {
}
@Override
int getMaxRows() throws SQLException {
return 0
}
@Override
void setMaxRows(int max) throws SQLException {
}
@Override
void setEscapeProcessing(boolean enable) throws SQLException {
}
@Override
int getQueryTimeout() throws SQLException {
return 0
}
@Override
void setQueryTimeout(int seconds) throws SQLException {
}
@Override
void cancel() throws SQLException {
}
@Override
SQLWarning getWarnings() throws SQLException {
return null
}
@Override
void clearWarnings() throws SQLException {
}
@Override
void setCursorName(String name) throws SQLException {
}
@Override
boolean execute(String sql) throws SQLException {
return false
}
@Override
ResultSet getResultSet() throws SQLException {
return null
}
@Override
int getUpdateCount() throws SQLException {
return 0
}
@Override
boolean getMoreResults() throws SQLException {
return false
}
@Override
void setFetchDirection(int direction) throws SQLException {
}
@Override
int getFetchDirection() throws SQLException {
return 0
}
@Override
void setFetchSize(int rows) throws SQLException {
}
@Override
int getFetchSize() throws SQLException {
return 0
}
@Override
int getResultSetConcurrency() throws SQLException {
return 0
}
@Override
int getResultSetType() throws SQLException {
return 0
}
@Override
void addBatch(String sql) throws SQLException {
}
@Override
void clearBatch() throws SQLException {
}
@Override
int[] executeBatch() throws SQLException {
return new int[0]
}
@Override
Connection getConnection() throws SQLException {
return connection
}
@Override
boolean getMoreResults(int current) throws SQLException {
return false
}
@Override
ResultSet getGeneratedKeys() throws SQLException {
return null
}
@Override
int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return 0
}
@Override
int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
return 0
}
@Override
int executeUpdate(String sql, String[] columnNames) throws SQLException {
return 0
}
@Override
boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return false
}
@Override
boolean execute(String sql, int[] columnIndexes) throws SQLException {
return false
}
@Override
boolean execute(String sql, String[] columnNames) throws SQLException {
return false
}
@Override
int getResultSetHoldability() throws SQLException {
return 0
}
@Override
boolean isClosed() throws SQLException {
return false
}
@Override
void setPoolable(boolean poolable) throws SQLException {
}
@Override
boolean isPoolable() throws SQLException {
return false
}
@Override
void closeOnCompletion() throws SQLException {
}
@Override
boolean isCloseOnCompletion() throws SQLException {
return false
}
@Override
def <T> T unwrap(Class<T> iface) throws SQLException {
return null
}
@Override
boolean isWrapperFor(Class<?> iface) throws SQLException {
return false
}
}

View File

@ -640,4 +640,49 @@ class JSPInstrumentationBasicTests extends AgentTestRunner {
"normal" | "compileError.jsp" | "compileError_jsp" | ""
"forward" | "forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards."
}
def "direct static file reference"() {
setup:
String reqUrl = baseUrl + "/$staticFile"
def req = new Request.Builder().url(new URL(reqUrl)).get().build()
when:
Response res = client.newCall(req).execute()
then:
res.code() == HttpStatus.OK_200
assertTraces(1) {
trace(0, 1) {
span(0) {
parent()
serviceName jspWebappContext
operationName "servlet.request"
// FIXME: this is not a great resource name for serving static content.
resourceName "GET /$jspWebappContext/$staticFile"
spanType DDSpanTypes.HTTP_SERVER
errored false
tags {
"$Tags.COMPONENT" "java-web-servlet"
"$Tags.SPAN_KIND" Tags.SPAN_KIND_SERVER
"$Tags.PEER_HOSTNAME" "127.0.0.1"
"$Tags.PEER_HOST_IPV4" "127.0.0.1"
"$Tags.PEER_PORT" Integer
"$Tags.HTTP_URL" "http://localhost:$port/$jspWebappContext/$staticFile"
"$Tags.HTTP_METHOD" "GET"
"$Tags.HTTP_STATUS" 200
"span.origin.type" "org.apache.catalina.core.ApplicationFilterChain"
"servlet.context" "/$jspWebappContext"
"servlet.path" "/$staticFile"
defaultTags()
}
}
}
}
cleanup:
res.close()
where:
staticFile = "common/hello.html"
}
}