Skip to content
Merged
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
61 changes: 0 additions & 61 deletions .github/workflows/java-pgjdbc-hikaricp-integ-tests.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/python-psycopg2-integ-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,4 @@ jobs:
pip list
echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O root.pem
python src/example.py
pytest
2 changes: 1 addition & 1 deletion .github/workflows/python-psycopg3-integ-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ jobs:
pip list
echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O root.pem
python src/example.py
pytest

20 changes: 19 additions & 1 deletion java/pgjdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,36 @@
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mainClass>org.example.Example</mainClass>
<mainClass>org.example.ExamplePreferred</mainClass>
<connector.version>1.2.0</connector.version>
<hikaricp.version>5.1.0</hikaricp.version>
<aws.sdk.version>2.31.32</aws.sdk.version>
<junit.version>5.10.0</junit.version>
<trimStackTrace>false</trimStackTrace>
</properties>

<dependencies>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.dsql</groupId>
<artifactId>aurora-dsql-jdbc-connector</artifactId>
<version>${connector.version}</version>
</dependency>
<!-- AWS SDK dependencies for SDK-only example (ExampleWithNoConnector) -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dsql</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.7</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
* <li>Production-ready configuration with connection validation</li>
* </ul>
*/
public class Example {
public class ExamplePreferred {

private final HikariDataSource dataSource;

public Example(String endpoint, String user) {
public ExamplePreferred(String endpoint, String user) {
this.dataSource = initializeConnectionPool(endpoint, user);
}

Expand Down Expand Up @@ -122,7 +122,7 @@ public static void main(String[] args) throws SQLException {
assert clusterUser != null : "CLUSTER_USER environment variable is not set";

System.out.println("Initializing Aurora DSQL example...");
Example example = new Example(clusterEndpoint, clusterUser);
ExamplePreferred example = new ExamplePreferred(clusterEndpoint, clusterUser);
System.out.println("Example initialized!");
System.out.println();

Expand Down
22 changes: 22 additions & 0 deletions java/pgjdbc/src/main/java/org/example/alternatives/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Alternative Examples

The recommended approach is `ExamplePreferred.java` in the parent directory, which uses HikariCP connection pool with the Aurora DSQL JDBC Connector.

## Why Connection Pooling with the Connector?

Aurora DSQL has specific connection characteristics:
- **60-minute max connection lifetime** - connections are terminated after 1 hour
- **15-minute token expiry** - IAM auth tokens must be refreshed
- **Optimized for concurrency** - more concurrent connections with smaller batches yields better throughput

The connector + pool combination handles this automatically:
- Generates fresh IAM tokens per connection
- Recycles connections before the 60-minute limit (via `maxLifetime < 3600000`)
- Reuses warmed connections for better performance

## Alternatives

### `no_connection_pool/`
Examples without pooling:
- `ExampleWithNoConnectionPool.java` - Single connection with connector
- `ExampleWithNoConnector.java` - SDK-only, for environments where the connector cannot be used (requires manual token management)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.example;
package org.example.alternatives.no_connection_pool;


import java.sql.Connection;
Expand All @@ -8,7 +8,7 @@
import java.sql.Statement;
import java.util.Properties;

public class Example {
public class ExampleWithNoConnectionPool {

// Get a connection to Aurora DSQL.
public static Connection getConnection(String endpoint, String user) throws SQLException {
Expand All @@ -33,7 +33,7 @@ public static void main(String[] args) throws SQLException {
String clusterUser = System.getenv("CLUSTER_USER");
assert clusterUser != null : "CLUSTER_USER environment variable is not set";

try (Connection conn = Example.getConnection(clusterEndpoint, clusterUser)) {
try (Connection conn = ExampleWithNoConnectionPool.getConnection(clusterEndpoint, clusterUser)) {
if (!clusterUser.equals("admin")) {
Statement setSchema = conn.createStatement();
setSchema.execute("SET search_path=myschema");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package org.example.alternatives.no_connection_pool;

import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.services.dsql.DsqlUtilities;
import software.amazon.awssdk.services.dsql.model.GenerateAuthTokenRequest;
import software.amazon.awssdk.regions.Region;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class ExampleWithNoConnector {

// Get a connection to Aurora DSQL.
public static Connection getConnection(String endpoint, String user, String region) throws SQLException {
DsqlUtilities utilities = DsqlUtilities.builder()
.region(Region.of(region))
.credentialsProvider(DefaultCredentialsProvider.create())
.build();

// The token expiration time is optional, and the default value is 900 seconds
GenerateAuthTokenRequest tokenGenerator = GenerateAuthTokenRequest.builder()
.hostname(endpoint)
.region(Region.of(region))
.build();

// Generate a fresh password token for each connection, to ensure the token is
// not expired when the connection is established
String password;
if (user.equals("admin")) {
password = utilities.generateDbConnectAdminAuthToken(tokenGenerator);
} else {
password = utilities.generateDbConnectAuthToken(tokenGenerator);
}

Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
// Use the DefaultJavaSSLFactory so that Java's default trust store can be used
// to verify the server's root cert.
props.setProperty("sslmode", "verify-full");
props.setProperty("sslfactory", "org.postgresql.ssl.DefaultJavaSSLFactory");
props.setProperty("sslNegotiation", "direct");

String url = "jdbc:postgresql://" + endpoint + ":5432/postgres";

return DriverManager.getConnection(url, props);
}

public static void main(String[] args) throws SQLException {
String clusterEndpoint = System.getenv("CLUSTER_ENDPOINT");
assert clusterEndpoint != null : "CLUSTER_ENDPOINT environment variable is not set";

String clusterUser = System.getenv("CLUSTER_USER");
assert clusterUser != null : "CLUSTER_USER environment variable is not set";

String region = System.getenv("REGION");
assert region != null : "REGION environment variable is not set";

try (Connection conn = ExampleWithNoConnector.getConnection(clusterEndpoint, clusterUser, region)) {
if (!clusterUser.equals("admin")) {
Statement setSchema = conn.createStatement();
setSchema.execute("SET search_path=myschema");
setSchema.close();
}
// Create a new table named owner
Statement create = conn.createStatement();
create.executeUpdate("""
CREATE TABLE IF NOT EXISTS owner(
id uuid NOT NULL DEFAULT gen_random_uuid(),
name varchar(30) NOT NULL,
city varchar(80) NOT NULL,
telephone varchar(20) DEFAULT NULL,
PRIMARY KEY (id))""");
create.close();

// Insert some data
Statement insert = conn.createStatement();
insert.executeUpdate(
"INSERT INTO owner (name, city, telephone) VALUES ('John Doe', 'Anytown', '555-555-1999')");
insert.close();

// Read back the data and assert they are present
String selectSQL = "SELECT * FROM owner";
Statement read = conn.createStatement();
ResultSet rs = read.executeQuery(selectSQL);
while (rs.next()) {
assert rs.getString("id") != null;
assert rs.getString("name").equals("John Doe");
assert rs.getString("city").equals("Anytown");
assert rs.getString("telephone").equals("555-555-1999");
}

// Delete some data
String deleteSql = String.format("DELETE FROM owner where name='John Doe'");
Statement delete = conn.createStatement();
delete.executeUpdate(deleteSql);
delete.close();
}
System.out.println("Connection exercised successfully");
}
}
12 changes: 0 additions & 12 deletions java/pgjdbc/src/test/java/org/example/DsqlExampleTest.java

This file was deleted.

12 changes: 12 additions & 0 deletions java/pgjdbc/src/test/java/org/example/ExamplePreferredTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.example;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

public class ExamplePreferredTest {
@Test
public void testExamplePreferred() {
assertAll(() -> ExamplePreferred.main(new String[]{}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.example.alternatives.no_connection_pool;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

public class ExampleWithNoConnectionPoolTest {
@Test
public void testExampleWithNoConnectionPool() {
assertAll(() -> ExampleWithNoConnectionPool.main(new String[]{}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.example.alternatives.no_connection_pool;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

public class ExampleWithNoConnectorTest {
@Test
public void testExampleWithNoConnector() {
assertAll(() -> ExampleWithNoConnector.main(new String[]{}));
}
}
Loading
Loading