diff --git a/CHANGELOG.md b/CHANGELOG.md index 37b17b85d..bef4b6fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Link performance test in table of contents. See [Documentation Table of Contents](https://github.com/awslabs/aws-advanced-jdbc-wrapper/blob/main/docs/Documentation.md). - Cluster URLs are not internally pooled. See [Using Read Write Splitting Plugin Internal Connection Pooling](https://github.com/awslabs/aws-advanced-jdbc-wrapper/blob/main/docs/using-the-jdbc-driver/using-plugins/UsingTheReadWriteSplittingPlugin.md#internal-connection-pooling). - The `leastConnections` strategy in the [Using Read Write Splitting Plugin Internal Connection Pooling](https://github.com/awslabs/aws-advanced-jdbc-wrapper/blob/main/docs/using-the-jdbc-driver/using-plugins/UsingTheReadWriteSplittingPlugin.md#internal-connection-pooling) at point #3. +- Sample code and tutorial for using the driver with: + - [Spring and Hibernate](./examples/SpringHibernateExample/README.md) + - [Spring and Wildfly](./examples/SpringWildflyExample/README.md) ### :bug: Fixed - Pruned null connections in connection tracker plugins ([PR #461](https://github.com/awslabs/aws-advanced-jdbc-wrapper/pull/461)) diff --git a/docs/using-the-jdbc-driver/FailoverConfigurationGuide.md b/docs/using-the-jdbc-driver/FailoverConfigurationGuide.md index af40c1d63..1418261e9 100644 --- a/docs/using-the-jdbc-driver/FailoverConfigurationGuide.md +++ b/docs/using-the-jdbc-driver/FailoverConfigurationGuide.md @@ -24,7 +24,7 @@ A failover time profile refers to a specific combination of failover parameters | `failoverClusterTopologyRefreshRateMs` | `2000` | ### Writer Cluster Endpoints After Failover -Connecting to a writer cluster endpoint after failover can result in a faulty connection because DNS causes a delay in changing the writer cluster. On the AWS DNS server, this change is updated usually between 15-20 seconds, but the other DNS servers sitting between the application and the AWS DNS server may not be updated in time. Using this stale DNS data will most likely cause problems for users, so it is important to keep this is mind. +Connecting to a writer cluster endpoint after failover can result in a faulty connection because DNS causes a delay in changing the writer cluster. On the AWS DNS server, this change is updated usually between 15-20 seconds, but the other DNS servers sitting between the application and the AWS DNS server may not be updated in time. Using the stale DNS data will most likely cause problems for users, so it is important to keep this is mind. ### 2-Node Clusters Using failover with a 2-node cluster is not beneficial because during the failover process involving one writer node and one reader node, the two nodes simply switch roles; the reader becomes the writer and the writer becomes the reader. If failover is triggered because one of the nodes has a problem, this problem will persist because there aren't any extra nodes to take the responsibility of the one that is broken. Three or more database nodes are recommended to improve the stability of the cluster. diff --git a/examples/SpringHibernateExample/README.md b/examples/SpringHibernateExample/README.md new file mode 100644 index 000000000..fbb63845f --- /dev/null +++ b/examples/SpringHibernateExample/README.md @@ -0,0 +1,179 @@ +# Tutorial: Getting Started with the AWS Advanced JDBC Driver, Spring Boot and Hibernate + +In this tutorial, you will set up a Spring Boot and Hibernate application with the AWS Advanced JDBC Driver, and use the IAM Authentication plugin to fetch some data from an Aurora PostgreSQL database. + +> Note: this tutorial was written using the following technologies: +> - Spring Boot 2.7.1 +> - Hibernate +> - AWS Advanced JDBC Driver 2.2.0 +> - Postgresql 42.5.4 +> - Gradle 7 +> - Java 11 + +You will progress through the following sections: +1. Create a Gradle Spring Boot project +2. Add the required Gradle dependencies +3. Configure the AWS Advanced JDBC Driver + +## Pre-requisites +- A database with IAM authentication enabled. This tutorial uses the Aurora PostgreSQL database. For information on how to enable IAM database authentication for Aurora databases, please see the [AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html). + +## Step 1: Create a Gradle Project +Create a Gradle project with the following project hierarchy: + +``` +└───src + ├───main + ├───java + │ └───example + | ├───data + | ├───Example.java + | └───ExampleRepository.java + │ └───SpringHibernateExampleApplication.java + └───resources + └───application.yml +``` + +> Note: this sample code assumes the target database contains a table named Example that can be generated using the SQL queries provided in `src/main/resources/example.sql`. + +`SpringHibernateExampleApplication.java` contains the following the code: + +```java +@SpringBootApplication +public class SpringHibernateExampleApplication implements CommandLineRunner { + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Autowired + ExampleRepository repository; + + @Override + public void run(String... args) { + LOGGER.info("Example -> {}", repository.findAll()); + } + + public static void main(String[] args) { + SpringApplication.run(SpringHibernateExampleApplication.class, args); + } +} +``` + +`Example.java` contains the following code: + +```java +package example.data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Example { + + @Id + @GeneratedValue + private int id; + + private int status; + + public Example() { + super(); + } + + public Example(int id, int status) { + super(); + this.id = id; + this.status = status; + } + + public Example(int status) { + super(); + this.status = status; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int name) { + this.status = name; + } + + @Override + public String toString() { + return String.format("Example [id=%s, status=%s]", id, status); + } +} +``` +Lastly, `ExampleRepository.java` contains the following code: + +```java +package example.data; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ExampleRepository extends JpaRepository { + +} +``` + +## Step 2: Add the required Gradle Dependencies +In your `build.gradle.kts`, add the following dependencies. + +``` +dependencies { + implementation("org.springframework.boot:spring-boot-starter-jdbc") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.postgresql:postgresql") + implementation("software.amazon.jdbc:aws-advanced-jdbc-wrapper") +} +``` + +## Step 3: Configure Spring and Hibernate +Configure Spring to use the AWS Advanced JDBC Driver as the default datasource. + +1. In the `application.yml`, add a new datasource for Spring: + ```yaml + datasource: + url: jdbc:aws-wrapper:postgresql://db-identifier.cluster-XYZ.us-east-2.rds.amazonaws.com:5432/db + username: jane_doe + driver-class-name: software.amazon.jdbc.Driver + hikari: + data-source-properties: + wrapperPlugins: iam,failover,efm + iamRegion: us-east-2 + iamExpiration: 1320 + exception-override-class-name: software.amazon.jdbc.util.HikariCPSQLException + max-lifetime: 1260000 + ``` + Since Spring 2+ uses Hikari to manage datasources, to configure the driver we would need to specify the `data-source-properties` under `hikari`. + Whenever Hikari is used, we also need to ensure failover exceptions are handled correctly so connections will not be discarded from the pool after failover has occurred. This can be done by overriding the exception handling class. For more information on this, please see [the documentation on HikariCP](../../docs/using-the-jdbc-driver/using-plugins/UsingTheFailoverPlugin.md#hikaricp). + + This example contains some very simple configurations for the IAM Authentication plugin, if you are interested in other configurations related to failover, please visit [the documentation for failover parameters](../../docs/using-the-jdbc-driver/using-plugins/UsingTheFailoverPlugin.md#failover-parameters) +2. Configure Hibernate dialect: + ```properties + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + ``` +3. [Optional] You can enable driver logging by adding the following to `application.yml`: + ```yaml + logging: + level: + software: + amazon: + jdbc: TRACE + ``` + +Start the application by running `./gradlew :springhibernate:bootRun` in the terminal. You should see the application making a connection to the database and fetching data from the Example table. + +# Summary +This tutorial walks through the steps required to add and configure the AWS Advanced JDBC Driver to a simple Spring Boot and Hibernate application. diff --git a/examples/SpringHibernateExample/build.gradle.kts b/examples/SpringHibernateExample/build.gradle.kts new file mode 100644 index 000000000..defd0e6c9 --- /dev/null +++ b/examples/SpringHibernateExample/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("org.springframework.boot") version "2.7.0" + id("io.spring.dependency-management") version "1.1.0" +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.postgresql:postgresql:42.5.4") + implementation("software.amazon.awssdk:rds:2.20.49") + implementation(project(":aws-advanced-jdbc-wrapper")) +} diff --git a/examples/SpringHibernateExample/gradle.properties b/examples/SpringHibernateExample/gradle.properties new file mode 100644 index 000000000..dc802102f --- /dev/null +++ b/examples/SpringHibernateExample/gradle.properties @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not publish the Jar file for this subproject +nexus.publish=false diff --git a/examples/SpringHibernateExample/src/main/java/example/SpringHibernateExampleApplication.java b/examples/SpringHibernateExample/src/main/java/example/SpringHibernateExampleApplication.java new file mode 100644 index 000000000..501f980a5 --- /dev/null +++ b/examples/SpringHibernateExample/src/main/java/example/SpringHibernateExampleApplication.java @@ -0,0 +1,42 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import example.data.ExampleRepository; + +@SpringBootApplication +public class SpringHibernateExampleApplication implements CommandLineRunner { + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Autowired + ExampleRepository repository; + + @Override + public void run(String... args) { + LOGGER.info("Example -> {}", repository.findAll()); + } + + public static void main(String[] args) { + SpringApplication.run(SpringHibernateExampleApplication.class, args); + } +} diff --git a/examples/SpringHibernateExample/src/main/java/example/data/Example.java b/examples/SpringHibernateExample/src/main/java/example/data/Example.java new file mode 100644 index 000000000..92165b640 --- /dev/null +++ b/examples/SpringHibernateExample/src/main/java/example/data/Example.java @@ -0,0 +1,67 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example.data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Example { + + @Id + @GeneratedValue + private int id; + + private int status; + + public Example() { + super(); + } + + public Example(int id, int status) { + super(); + this.id = id; + this.status = status; + } + + public Example(int status) { + super(); + this.status = status; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int name) { + this.status = name; + } + + @Override + public String toString() { + return String.format("Example [id=%s, status=%s]", id, status); + } +} diff --git a/examples/SpringHibernateExample/src/main/java/example/data/ExampleRepository.java b/examples/SpringHibernateExample/src/main/java/example/data/ExampleRepository.java new file mode 100644 index 000000000..7fd92f11b --- /dev/null +++ b/examples/SpringHibernateExample/src/main/java/example/data/ExampleRepository.java @@ -0,0 +1,23 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example.data; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ExampleRepository extends JpaRepository { + +} diff --git a/examples/SpringHibernateExample/src/main/resources/application.yml b/examples/SpringHibernateExample/src/main/resources/application.yml new file mode 100644 index 000000000..4872404f2 --- /dev/null +++ b/examples/SpringHibernateExample/src/main/resources/application.yml @@ -0,0 +1,23 @@ +spring: + datasource: + url: jdbc:aws-wrapper:postgresql://db-identifier.cluster-XYZ.us-east-2.rds.amazonaws.com:5432/db + username: jane_doe + driver-class-name: software.amazon.jdbc.Driver + hikari: + data-source-properties: + wrapperPlugins: iam,failover,efm + iamRegion: us-east-2 + iamExpiration: 1320 + exception-override-class-name: software.amazon.jdbc.util.HikariCPSQLException + max-lifetime: 1260000 + + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + +logging: + level: + software: + amazon: + jdbc: TRACE diff --git a/examples/SpringHibernateExample/src/main/resources/example.sql b/examples/SpringHibernateExample/src/main/resources/example.sql new file mode 100644 index 000000000..c5ac40c81 --- /dev/null +++ b/examples/SpringHibernateExample/src/main/resources/example.sql @@ -0,0 +1,17 @@ +-- Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"). +-- You may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +CREATE TABLE IF NOT EXISTS example (status int, id int); + +INSERT INTO example (status, id) VALUES (66608, 104), (754, 148); diff --git a/examples/SpringWildflyExample/README.md b/examples/SpringWildflyExample/README.md new file mode 100644 index 000000000..2146ec755 --- /dev/null +++ b/examples/SpringWildflyExample/README.md @@ -0,0 +1,199 @@ +# Tutorial: Getting Started with the AWS Advanced JDBC Driver, Spring Boot and Wildfly + +In this tutorial, you will set up a Wildfly and Spring Boot application with the AWS Advanced JDBC Driver, and use the wrapper to execute some simple database operations. + +> Note: this tutorial was written using the following technologies: +> - Spring Boot 2.7.1 +> - Wildfly 26.1.1 Final +> - AWS Advanced JDBC Wrapper 2.2.0 +> - Postgresql 42.5.4 +> - Gradle 7 +> - Java 11 + +You will progress through the following sections: +1. Create a Gradle Spring Boot project +2. Add the required Gradle dependencies +3. Configure the AWS Advanced JDBC Wrapper in Wildfly +4. Use JDBCTemplate to perform some simple database operations + +## Step 1: Create a Gradle Project +Create a Gradle project with the following project hierarchy: + +``` +├───build.gradle.kts +├───spring + └───src + ├───main + ├───java + │ └───example + | │───Example.java + | └───SpringWildflyExampleApplication.java + └───resources + │ └───application.properties +└───wildfly + └───modules + ├───software + ├───amazon + │ └───jdbc + │ └───main + │ │ │───module.xml + │ │ │───postgresql-42.5.4.jar + │ │ └───aws-advanced-jdbc-wrapper-2.2.0.jar + └───standalone + ├───configuration + ├───amazon + │ └───standalone.xml +``` +> Note: The wildfly directory will contain all the files you have downloaded in step 3. For simplicity, the diagram above only shows the files requiring modifications or need to be added. + +The file `Example.java` contains the following: +```java +package example; + +public class Example { + + int status; + int id; + + public Example(int status, int id) { + this.status = status; + this.id = id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public String toString() { + return "Example{" + + "status=" + status + + ", id='" + id + + '}'; + } +} +``` + +## Step 2: Add the required Gradle Dependencies +In your `build.gradle.kts`, add the following dependencies. + +``` +dependencies { + implementation("org.springframework.boot:spring-boot-starter-jdbc") + implementation("org.springframework.boot:spring-boot-starter-web") + runtimeOnly("org.springframework.boot:spring-boot-devtools") + implementation("org.postgresql:postgresql") + implementation("software.amazon.jdbc:aws-advanced-jdbc-wrapper") +} +``` + +## Step 3: Configure Wildfly +> Note: for simplicity, this repository does not contain the entire wildfly application, and instead only contains the modified files. + +Download the Wildfly 26.1.1 Servlet-Only Distribution from the [Wildfly website](https://www.wildfly.org/downloads/). +In the Wildfly `standalone/configuration/standalone.xml` file, configure the AWS Advanced JDBC Driver as your datasource by adding the following to the `` section. + +```xml + + jdbc:aws-wrapper:postgresql://db-identifier.cluster-XYZ.us-east-2.rds.amazonaws.com:5432/db + wrapper + + foo + bar + + +``` + +If you would like to configure any additional properties for the wrapper, such as the [failover timeouts](../../docs/using-the-jdbc-driver/FailoverConfigurationGuide.md), you can do so through ``: +```xml +180000 +2000 +30000 +2000 +``` + +You also need to add a new module in the `modules` directory. +To add a new module, you need to add a `module.xml` and provide the required driver JAR files. +The folder containing the `module.xml` needs to match the module name, in this example, the module name is `software.amazon.jdbc`. +Since this example uses the PostgreSQL JDBC driver as the target driver, you need to add the AWS Advanced JDBC Driver JAR file as well as the PostgreSQL JDBC driver JAR file in the same directory as the `module.xml`. + +```xml + + + + + + + +``` + +## Step 4: Configure Spring to use the AWS Advanced JDBC Driver +To configure Spring to use the datasource specified in Wildfly, add an `application.properties` file in `spring/main/resources` with the `jndi-name` property: +```properties +spring.datasource.jndi-name=java:jboss/datasources/AWSWrapper +``` +The `jndi-name` needs to match the JNDI name specified in the Wildfly `standalone.xml` file. + +## Step 4: Use JDBCTemplate to perform some simple operations + +In `spring/src/main/java/example/SpringWildflyExampleApplication.java`, use `JdbcTemplate` to query data from the database. + +> Note: this sample code assumes the target database contains a table named Example that can be generated using the SQL queries provided in `src/main/resources/example.sql`. + +```java +package example; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootApplication +public class SpringWildflyExampleApplication implements CommandLineRunner { + + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Autowired + JdbcTemplate jdbcTemplate; + + @Override + public void run(String... args) { + LOGGER.info("Example -> {}", jdbcTemplate.query( + "SELECT * FROM example LIMIT 10", + (rs, rowNum) -> + new Example( + rs.getInt("status"), + rs.getInt("id") + ) + )); + } + + public static void main(String[] args) { + SpringApplication.run(SpringWildflyExampleApplication.class, args); + } +} +``` + +Start the application by +1. Starting the Wildfly server with `./wildfly/bin/standalone.sh`, and +2. Running `./gradlew :springhibernate:bootRun` in the terminal. + +3. You should see the Spring application making a connection to the database and fetching data from the Example table. + +# Summary +This tutorial walks through the steps required to add and configure the AWS Advanced JDBC Driver to a simple Spring Boot and Wildfly application. diff --git a/examples/SpringWildflyExample/gradle.properties b/examples/SpringWildflyExample/gradle.properties new file mode 100644 index 000000000..dc802102f --- /dev/null +++ b/examples/SpringWildflyExample/gradle.properties @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not publish the Jar file for this subproject +nexus.publish=false diff --git a/examples/SpringWildflyExample/spring/build.gradle.kts b/examples/SpringWildflyExample/spring/build.gradle.kts new file mode 100644 index 000000000..b11fb2096 --- /dev/null +++ b/examples/SpringWildflyExample/spring/build.gradle.kts @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("org.springframework.boot") version "2.7.0" + id("io.spring.dependency-management") version "1.1.0" +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-jdbc") + implementation("org.springframework.boot:spring-boot-starter-web") + runtimeOnly("org.springframework.boot:spring-boot-devtools") + implementation("org.postgresql:postgresql:42.5.4") + implementation("software.amazon.awssdk:rds:2.20.49") + implementation(project(":aws-advanced-jdbc-wrapper")) +} diff --git a/examples/SpringWildflyExample/spring/src/main/java/example/Example.java b/examples/SpringWildflyExample/spring/src/main/java/example/Example.java new file mode 100644 index 000000000..ef856148c --- /dev/null +++ b/examples/SpringWildflyExample/spring/src/main/java/example/Example.java @@ -0,0 +1,52 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +public class Example { + + int status; + int id; + + public Example(int status, int id) { + this.status = status; + this.id = id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public String toString() { + return "Example{" + + "status=" + status + + ", id='" + id + + '}'; + } +} diff --git a/examples/SpringWildflyExample/spring/src/main/java/example/SpringWildflyExampleApplication.java b/examples/SpringWildflyExample/spring/src/main/java/example/SpringWildflyExampleApplication.java new file mode 100644 index 000000000..a4eb86c2b --- /dev/null +++ b/examples/SpringWildflyExample/spring/src/main/java/example/SpringWildflyExampleApplication.java @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package example; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootApplication +public class SpringWildflyExampleApplication implements CommandLineRunner { + + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Autowired + JdbcTemplate jdbcTemplate; + + @Override + public void run(String... args) { + LOGGER.info("Example -> {}", jdbcTemplate.query( + "SELECT * FROM example LIMIT 10", + (rs, rowNum) -> + new Example( + rs.getInt("status"), + rs.getInt("id") + ) + )); + } + + public static void main(String[] args) { + SpringApplication.run(SpringWildflyExampleApplication.class, args); + } +} diff --git a/examples/SpringWildflyExample/spring/src/main/resources/application.properties b/examples/SpringWildflyExample/spring/src/main/resources/application.properties new file mode 100644 index 000000000..cbdd3309b --- /dev/null +++ b/examples/SpringWildflyExample/spring/src/main/resources/application.properties @@ -0,0 +1,17 @@ +# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +spring.datasource.jndi-name=java:jboss/datasources/AWSWrapper diff --git a/examples/SpringWildflyExample/spring/src/main/resources/example.sql b/examples/SpringWildflyExample/spring/src/main/resources/example.sql new file mode 100644 index 000000000..c5ac40c81 --- /dev/null +++ b/examples/SpringWildflyExample/spring/src/main/resources/example.sql @@ -0,0 +1,17 @@ +-- Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"). +-- You may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +CREATE TABLE IF NOT EXISTS example (status int, id int); + +INSERT INTO example (status, id) VALUES (66608, 104), (754, 148); diff --git a/examples/SpringWildflyExample/wildfly/modules/software/amazon/jdbc/main/module.xml b/examples/SpringWildflyExample/wildfly/modules/software/amazon/jdbc/main/module.xml new file mode 100644 index 000000000..ddbf34869 --- /dev/null +++ b/examples/SpringWildflyExample/wildfly/modules/software/amazon/jdbc/main/module.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/examples/SpringWildflyExample/wildfly/standalone/configuration/standalone.xml b/examples/SpringWildflyExample/wildfly/standalone/configuration/standalone.xml new file mode 100644 index 000000000..01cb99a57 --- /dev/null +++ b/examples/SpringWildflyExample/wildfly/standalone/configuration/standalone.xml @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=${wildfly.h2.compatibility.mode:REGULAR} + h2 + + sa + sa + + + + + org.h2.jdbcx.JdbcDataSource + + + + jdbc:aws-wrapper:postgresql://db-identifier.cluster-XYZ.us-east-2.rds.amazonaws.com:5432/db + wrapper + 180000 + 2000 + 30000 + 2000 + + foo + bar + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index c045631a6..43bb5a02a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,13 +21,17 @@ include( "benchmarks", "hibernate", "hikari", - "driverexample" + "driverexample", + "springhibernate", + "springwildfly" ) project(":aws-advanced-jdbc-wrapper").projectDir = file("wrapper") project(":hibernate").projectDir = file("examples/HibernateExample") project(":hikari").projectDir = file("examples/HikariExample") project(":driverexample").projectDir = file("examples/AWSDriverExample") +project(":springhibernate").projectDir = file("examples/SpringHibernateExample") +project(":springwildfly").projectDir = file("examples/SpringWildflyExample/spring") pluginManagement { plugins { diff --git a/wrapper/build.gradle.kts b/wrapper/build.gradle.kts index 302482dd6..944e60137 100644 --- a/wrapper/build.gradle.kts +++ b/wrapper/build.gradle.kts @@ -55,9 +55,9 @@ dependencies { testImplementation("software.amazon.awssdk:rds:2.20.49") testImplementation("software.amazon.awssdk:ec2:2.20.61") testImplementation("software.amazon.awssdk:secretsmanager:2.20.49") - testImplementation("org.testcontainers:testcontainers:1.17.4") - testImplementation("org.testcontainers:mysql:1.18.0") - testImplementation("org.testcontainers:postgresql:1.17.5") + testImplementation("org.testcontainers:testcontainers:1.18.3") + testImplementation("org.testcontainers:mysql:1.18.3") + testImplementation("org.testcontainers:postgresql:1.18.3") testImplementation("org.testcontainers:mariadb:1.18.3") testImplementation("org.testcontainers:junit-jupiter:1.17.4") testImplementation("org.testcontainers:toxiproxy:1.17.5") diff --git a/wrapper/src/test/java/integration/util/ContainerHelper.java b/wrapper/src/test/java/integration/util/ContainerHelper.java index 62af047e9..6e91ca0d2 100644 --- a/wrapper/src/test/java/integration/util/ContainerHelper.java +++ b/wrapper/src/test/java/integration/util/ContainerHelper.java @@ -49,7 +49,7 @@ public class ContainerHelper { private static final String MYSQL_CONTAINER_IMAGE_NAME = "mysql:latest"; private static final String POSTGRES_CONTAINER_IMAGE_NAME = "postgres:latest"; - private static final String MARIADB_CONTAINER_IMAGE_NAME = "mariadb:latest"; + private static final String MARIADB_CONTAINER_IMAGE_NAME = "mariadb:10"; private static final DockerImageName TOXIPROXY_IMAGE = DockerImageName.parse("shopify/toxiproxy:2.1.4");