From 9b4e1f9584e32ba26ad323c42a07f5f66d7bcd49 Mon Sep 17 00:00:00 2001 From: Mohammed Abourass Date: Thu, 15 Oct 2026 13:12:02 +0100 Subject: [PATCH] [WFLY-22003] Replace JPA-based DB initialization with JDBC startup bean Drop and recreate tables on startup instead of using CREATE IF NOT EXISTS, ensuring clean test data. All schema creation and data insertion run in a single transaction for atomicity. --- servlet-security/README-source.adoc | 2 +- servlet-security/pom.xml | 6 - .../servlet_security/DatabaseInitializer.java | 126 ++++++++++++++++++ .../servlet_security/DummyEntity.java | 33 ----- .../main/resources/META-INF/persistence.xml | 35 ----- .../src/main/resources/import.sql | 29 ---- 6 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DatabaseInitializer.java delete mode 100644 servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DummyEntity.java delete mode 100644 servlet-security/src/main/resources/META-INF/persistence.xml delete mode 100644 servlet-security/src/main/resources/import.sql diff --git a/servlet-security/README-source.adoc b/servlet-security/README-source.adoc index db880f6104..f3daaeadbf 100644 --- a/servlet-security/README-source.adoc +++ b/servlet-security/README-source.adoc @@ -18,7 +18,7 @@ The `servlet-security` quickstart demonstrates the use of Jakarta EE declarative The `servlet-security` quickstart demonstrates the use of Jakarta EE declarative security to control access to Servlets and Security in {productNameFull}. -When you deploy this example, two users are automatically created for you: user `quickstartUser` with password `quickstartPwd1!` and user `guest` with password `guestPwd1!`. This data is located in the `src/main/resources/import.sql` file. +When you deploy this example, two users are automatically created for you: user `quickstartUser` with password `quickstartPwd1!` and user `guest` with password `guestPwd1!`. This data is initialized by the `DatabaseInitializer` CDI bean on application startup. This quickstart takes the following steps to implement Servlet security: diff --git a/servlet-security/pom.xml b/servlet-security/pom.xml index 0b8709cee2..7d3dfe88ee 100644 --- a/servlet-security/pom.xml +++ b/servlet-security/pom.xml @@ -92,12 +92,6 @@ provided - - jakarta.persistence - jakarta.persistence-api - provided - - org.junit.jupiter diff --git a/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DatabaseInitializer.java b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DatabaseInitializer.java new file mode 100644 index 0000000000..d7fd669e89 --- /dev/null +++ b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DatabaseInitializer.java @@ -0,0 +1,126 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.jboss.as.quickstarts.servlet_security; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.sql.DataSource; + +import jakarta.annotation.Resource; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; + +/** + * Initializes the database schema and data for Elytron JDBC realm authentication. + * This CDI bean runs at application startup to create tables and populate + * test user credentials. + * + * @author Mohammed Abourass mouhammedmax@hotmail.com + */ +@ApplicationScoped +public class DatabaseInitializer { + + private static final Logger LOGGER = Logger.getLogger(DatabaseInitializer.class.getName()); + + @Resource(lookup = "java:jboss/datasources/ServletSecurityDS") + private DataSource dataSource; + + public void initializeDatabase(@Observes @Initialized(ApplicationScoped.class) Object init) { + LOGGER.info("Initializing database schema for servlet-security..."); + + try (Connection conn = dataSource.getConnection()) { + conn.setAutoCommit(false); + try { + createTables(conn); + insertTestData(conn); + conn.commit(); + } catch (SQLException e) { + conn.rollback(); + throw e; + } + LOGGER.info("Database initialization completed successfully."); + } catch (SQLException e) { + LOGGER.log(Level.SEVERE, "Failed to initialize database", e); + throw new RuntimeException("Database initialization failed", e); + } + } + + private void createTables(Connection conn) throws SQLException { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("DROP TABLE IF EXISTS USERS_ROLES"); + stmt.executeUpdate("DROP TABLE IF EXISTS ROLES"); + stmt.executeUpdate("DROP TABLE IF EXISTS USERS"); + + stmt.executeUpdate( + "CREATE TABLE USERS (" + + "ID INT, " + + "USERNAME VARCHAR(20), " + + "PASSWORD VARCHAR(20))" + ); + + stmt.executeUpdate( + "CREATE TABLE ROLES (" + + "ID INT, " + + "NAME VARCHAR(20))" + ); + + stmt.executeUpdate( + "CREATE TABLE USERS_ROLES (" + + "USER_ID INT, " + + "ROLE_ID INT)" + ); + + LOGGER.info("Database tables created"); + } + } + + private void insertTestData(Connection conn) throws SQLException { + try (PreparedStatement insertStmt = conn.prepareStatement( + "INSERT INTO USERS (ID, USERNAME, PASSWORD) VALUES (?, ?, ?)")) { + + insertStmt.setInt(1, 1); + insertStmt.setString(2, "quickstartUser"); + insertStmt.setString(3, "quickstartPwd1!"); + insertStmt.executeUpdate(); + + insertStmt.setInt(1, 2); + insertStmt.setString(2, "guest"); + insertStmt.setString(3, "guestPwd1!"); + insertStmt.executeUpdate(); + } + + try (PreparedStatement insertStmt = conn.prepareStatement( + "INSERT INTO ROLES (ID, NAME) VALUES (?, ?)")) { + + insertStmt.setInt(1, 1); + insertStmt.setString(2, "quickstarts"); + insertStmt.executeUpdate(); + + insertStmt.setInt(1, 2); + insertStmt.setString(2, "guest"); + insertStmt.executeUpdate(); + } + + try (PreparedStatement insertStmt = conn.prepareStatement( + "INSERT INTO USERS_ROLES (USER_ID, ROLE_ID) VALUES (?, ?)")) { + + insertStmt.setInt(1, 1); + insertStmt.setInt(2, 1); + insertStmt.executeUpdate(); + + insertStmt.setInt(1, 2); + insertStmt.setInt(2, 2); + insertStmt.executeUpdate(); + } + + LOGGER.info("Test data inserted successfully"); + } +} diff --git a/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DummyEntity.java b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DummyEntity.java deleted file mode 100644 index 2d7ff2dfc5..0000000000 --- a/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DummyEntity.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2022, Red Hat, Inc. and/or its affiliates, and individual - * contributors by the @authors tag. See the copyright.txt in the - * distribution for a full listing of individual contributors. - * - * 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 org.jboss.as.quickstarts.servlet_security; - -import java.io.Serializable; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; - -@SuppressWarnings("serial") -@Entity -// This class should be removed once https://issues.redhat.com/browse/WFLY-16871 is resolved -public class DummyEntity implements Serializable { - - @Id - @GeneratedValue - private Long id; -} diff --git a/servlet-security/src/main/resources/META-INF/persistence.xml b/servlet-security/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index 548be6c5f4..0000000000 --- a/servlet-security/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - java:jboss/datasources/ServletSecurityDS - - - - - - - diff --git a/servlet-security/src/main/resources/import.sql b/servlet-security/src/main/resources/import.sql deleted file mode 100644 index 815550dc78..0000000000 --- a/servlet-security/src/main/resources/import.sql +++ /dev/null @@ -1,29 +0,0 @@ --- --- JBoss, Home of Professional Open Source --- Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual --- contributors by the @authors tag. See the copyright.txt in the --- distribution for a full listing of individual contributors. --- --- 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 USERS (ID INT, USERNAME VARCHAR(20), PASSWORD VARCHAR(20)); -CREATE TABLE ROLES (ID INT, NAME VARCHAR(20)); -CREATE TABLE USERS_ROLES (USER_ID INT, ROLE_ID INT); - -INSERT INTO USERS (ID, USERNAME, PASSWORD) VALUES (1, 'quickstartUser', 'quickstartPwd1!'); -INSERT INTO USERS (ID, USERNAME, PASSWORD) VALUES (2, 'guest', 'guestPwd1!'); - -INSERT INTO ROLES (ID, NAME) VALUES (1, 'quickstarts'); -INSERT INTO ROLES (ID, NAME) VALUES (2, 'guest'); - -INSERT INTO USERS_ROLES (USER_ID, ROLE_ID) VALUES (1,1); -INSERT INTO USERS_ROLES (USER_ID, ROLE_ID) VALUES (2,2);