Connecting to a DB - PART 1: Docker Image
In this guide, we will extend the example created in WildFly Java Microservice - PART 1: Docker Image and add Database connectivity.
Prerequisites
To complete this guide, you need:
Database
PostgreSQL
We will use PostgreSQL in this guide in its containerized version: see PostgreSQL Official Image.
Start PostgreSQL:
podman network create demo-network
podman run --rm --network=demo-network --name my-postgres \
-p 5432:5432 \
-e POSTGRES_PASSWORD=admin \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
docker.io/library/postgres
Note
|
we started the container with the --rm flag: this way it is disposed of automatically when we stop it
|
Note
|
We created the demo-network network and started the my-postgres container with the --network=demo-network option: later in this guide, this will allow us to connect to the my-postgres container from the my-jaxrs-app-db container
|
Maven Project
You will extend the sample application you created in WildFly Java Microservice - PART 1: Docker Image by adding the wildfly-datasources-galleon-pack.
The wildfly-datasources-galleon-pack will:
-
install the JDBC Driver for the PostgreSQL Database into WildFly
-
add a database connection to PostgreSQL in WildFly
pom.xml
dependencies
Add the following dependencies to the pom-xml
file dependencies
section:
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.transaction</groupId>
<artifactId>jakarta.transaction-api</artifactId>
<scope>provided</scope>
</dependency>
wildfly-maven-plugin
Add the wildfly-datasources-galleon-pack
feature-pack and the postgresql-datasource
layer to the wildfly-maven-plugin
configuration.
You should end up with the wildfly-maven-plugin configured like in the following:
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>5.0.0.Final</version>
<configuration>
<feature-packs>
<feature-pack>
<location>org.wildfly:wildfly-galleon-pack:32.0.0.Final</location>
</feature-pack>
<feature-pack>
<location>org.wildfly.cloud:wildfly-cloud-galleon-pack:7.0.0.Final</location>
</feature-pack>
<feature-pack>
<location>org.wildfly:wildfly-datasources-galleon-pack:8.0.0.Final</location>
</feature-pack>
</feature-packs>
<layers>
<layer>cloud-server</layer>
<layer>postgresql-datasource</layer>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
Java Classes
Add the following classes to the project:
package org.wildfly.examples.test_table;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import java.util.Objects;
import static jakarta.persistence.GenerationType.IDENTITY;
@Entity
public class TestTable {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String field1;
private String field2;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestTable testTable = (TestTable) o;
return Objects.equals(id, testTable.id) && Objects.equals(field1, testTable.field1) && Objects.equals(field2, testTable.field2);
}
@Override
public int hashCode() {
return Objects.hash(id, field1, field2);
}
}
package org.wildfly.examples.test_table;
import jakarta.enterprise.context.RequestScoped;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;
import java.util.List;
@RequestScoped
@Path("/test-table")
public class TestTableResource {
@PersistenceContext(unitName = "primary")
private EntityManager em;
public void createOrUpdateRow(TestTable row) {
if (!em.contains(row)) {
row = em.merge(row);
}
em.persist(row);
}
public List<TestTable> getAllRows() {
return em.createQuery("SELECT t FROM TestTable t", TestTable.class).getResultList();
}
@Transactional
@POST
@Produces({"application/json"})
@Path("{field1}/{field2}")
public Response insertIntoTestTable(
@PathParam("field1") @DefaultValue("some data 1") String field1,
@PathParam("field2") @DefaultValue("some data 2") String field2) throws Exception {
TestTable testTable = null;
try {
testTable = new TestTable();
testTable.setField1(field1);
testTable.setField2(field2);
createOrUpdateRow(testTable);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return Response.ok(testTable).build();
}
@GET
@Produces({"application/json"})
public List<TestTable> getAllRowsFromTestTable() {
try {
List<TestTable> allRows = getAllRows();
return allRows;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
persistence.xml
Add the src/main/resources/META-INF/persistence.xml
file to the project with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" >
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/PostgreSQLDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Build the application
$ mvn clean package
...
[INFO] Copy deployment /home/tborgato/Documents/WildFly-Mini-Serie/getting-started/target/ROOT.war to /home/tborgato/Documents/WildFly-Mini-Serie/getting-started/target/server/standalone/deployments/ROOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.830 s
[INFO] Finished at: 2024-05-07T16:18:22+02:00
[INFO] ------------------------------------------------------------------------
Docker Image
Build the Docker Image
Build the Docker Image with the following command:
$ podman build -t my-jaxrs-app-db:latest .
STEP 1/3: FROM quay.io/wildfly/wildfly-runtime:latest
STEP 2/3: COPY --chown=jboss:root target/server $JBOSS_HOME
-→ 4609f8ed0c7f
STEP 3/3: RUN chmod -R ug+rwX $JBOSS_HOME
COMMIT my-jaxrs-app:latest
-→ db4677f5bf4f
Successfully tagged localhost/my-jaxrs-app:latest
db4677f5bf4f471f5624bd63a21fce3d91b7b3b93e985d3e86a8a4b0682d85cd
Run the Docker Image
Note that, when running the my-jaxrs-app-db:latest
Docker Image, we specify some environment variables used by WildFly to connect to the PostgreSQL database:
podman run --rm --network=demo-network -p 8080:8080 -p 9990:9990 \
-e POSTGRESQL_USER=postgres \
-e POSTGRESQL_PASSWORD=admin \
-e POSTGRESQL_HOST=my-postgres \
-e POSTGRESQL_PORT=5432 \
-e POSTGRESQL_DATABASE=postgres \
-e POSTGRESQL_JNDI=java:jboss/datasources/PostgreSQLDS \
--name=my-jaxrs-app-db \
my-jaxrs-app-db:latest
Note
|
We started the my-jaxrs-app-db container with the --network=demo-network option just like we did when we started the my-postgres container: the two containers now run in the same demo-network network and we can connect to the my-postgres container from the my-jaxrs-app-db container using the my-postgres DNS name;
|
Check the application
Hit the following URLs, using a utility like curl
:
$ curl -X POST http://localhost:8080/hello/test-table/somedata1/somedata2
{"field1":"somedata1","field2":"somedata2","id":1}
$ curl http://localhost:8080/hello/test-table
[{"field1":"somedata1","field2":"somedata2","id":1}]
Stop the Docker containers
Stop the running container:
podman stop my-jaxrs-app-db
podman stop my-postgres