From 18eb955a6ffd937d4807f68679600c4bc4ae1bfc Mon Sep 17 00:00:00 2001 From: Mohammed Abourass Date: Wed, 19 Aug 2026 14:55:10 +0100 Subject: [PATCH] [WFLY-22003] Replace JPA-based DB initialization with JDBC startup bean --- servlet-security/README-source.adoc | 2 +- servlet-security/pom.xml | 6 - .../servlet_security/DatabaseInitializer.java | 145 ++++++++++++++++++ .../servlet_security/DummyEntity.java | 33 ---- .../main/resources/META-INF/persistence.xml | 35 ----- .../src/main/resources/import.sql | 29 ---- 6 files changed, 146 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..42b7165bea --- /dev/null +++ b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/DatabaseInitializer.java @@ -0,0 +1,145 @@ +/* + * 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.ResultSet; +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 if they don't already exist. + * + * @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 { + createTables(); + insertTestData(); + 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() throws SQLException { + try (Connection conn = dataSource.getConnection(); + Statement stmt = conn.createStatement()) { + + // Create USERS table if not exists + stmt.executeUpdate( + "CREATE TABLE IF NOT EXISTS USERS (" + + "ID INT, " + + "USERNAME VARCHAR(20), " + + "PASSWORD VARCHAR(20))" + ); + + // Create ROLES table if not exists + stmt.executeUpdate( + "CREATE TABLE IF NOT EXISTS ROLES (" + + "ID INT, " + + "NAME VARCHAR(20))" + ); + + // Create USERS_ROLES junction table if not exists + stmt.executeUpdate( + "CREATE TABLE IF NOT EXISTS USERS_ROLES (" + + "USER_ID INT, " + + "ROLE_ID INT)" + ); + + LOGGER.info("Database tables created or verified"); + } + } + + private void insertTestData() throws SQLException { + try (Connection conn = dataSource.getConnection()) { + + // Check if data already exists (avoid duplicates on redeployment) + if (userExists(conn, "quickstartUser")) { + LOGGER.info("Test data already exists, skipping insertion"); + return; + } + + // Insert users + 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(); + } + + // Insert roles + 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(); + } + + // Insert user-role mappings + 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"); + } + } + + private boolean userExists(Connection conn, String username) throws SQLException { + try (PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(*) FROM USERS WHERE USERNAME = ?")) { + stmt.setString(1, username); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt(1) > 0; + } + return false; + } + } + } +} 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);