diff --git a/ecosystem/testcontainers-example/README.md b/ecosystem/testcontainers-example/README.md index 07c7e0d..f0ddb22 100644 --- a/ecosystem/testcontainers-example/README.md +++ b/ecosystem/testcontainers-example/README.md @@ -1,13 +1,13 @@ # Sample Project for Testcontainers This is a sample application generated by the Payara Starter. -It aims to be tested using Testcontainers. +It aims to be tested using WeldInitiator, Arquillian and Testcontainer. ## Getting Started ### Prerequisites -- [Java SE 11+](https://adoptium.net/temurin/releases?version=11&os=any&arch=any ) +- [Java SE 21+](https://www.azul.com/downloads/?version=java-21-lts#zulu ) - [Maven](https://maven.apache.org/download.cgi ) ## Running the Application @@ -34,12 +34,68 @@ To run the tests for the application locally, follow these steps: 2. Make sure you have the appropriate Java version installed. -3. Execute the following command: - -``` -./mvn clean verify -``` - +3. Make sure [Docker](https://www.docker.com/products/docker-desktop/) is installed and running. The integration + tests (`*IT.java`) use [Testcontainers](https://testcontainers.com/) to start a real Payara Micro instance with + the application deployed, so Docker needs to be reachable from the JVM running the tests. If you hit + `Could not find a valid Docker environment` on Windows even though `docker` works fine from the shell, see + [Testcontainers' Windows troubleshooting guide](https://java.testcontainers.org/supported_docker_environment/windows/). + +4. The first time you run the tests (or any time after `mvn clean`), install the local test tooling and run + everything in one go: + + ``` + ./mvn clean verify -Pinstall-deps + ``` + + This installs the Playwright Chromium browser binary (for the `*UiIT` tests) and the Payara Micro jar the + Arquillian test launches directly (see `BookServiceArquillianIT` below). Both are behind the opt-in + `install-deps` Maven profile rather than running automatically, since Playwright's browser install can + prompt for (or require) `sudo` to install missing system libraries on some machines/OSes — not something + this build should force on you every time, especially if you don't have or don't want to grant those + permissions. + +5. On later runs, once those are in place, the plain command works and reuses what's already installed: + + ``` + ./mvn verify + ``` + + `mvn test` (just the `*Test` unit tests) never needs `-Pinstall-deps` at all — it doesn't touch Docker, + Playwright, or Payara Micro. Skipping `-Pinstall-deps` on a `verify` after a `clean` will fail the `*UiIT` + and `BookServiceArquillianIT` tests specifically (no browser binary / no Payara Micro jar to launch), while + the `*ServiceIT` REST tests are unaffected either way. + +### What gets tested + +- `*Test` (`fish.payara.examples.service`) — CDI unit tests using [`weld-junit5`](https://github.com/weld/weld-junit)'s + `WeldInitiator`. Boots a real (but minimal) Weld container for a single service bean with a mocked + `EntityManager` — no Docker, no app server, runs in milliseconds as part of `mvn test`. +- `*ServiceIT` (`fish.payara.examples.service`) — REST API tests hitting the deployed application directly with a + JAX-RS client. +- `*UiIT` (`fish.payara.examples.ui`) — browser tests driving the JSF pages (Book, Patron, Librarian, Loan) end to + end with [Playwright](https://playwright.dev/java/). The Playwright Chromium browser binary is installed by the + `exec-maven-plugin` execution in the `install-deps` profile (see above) — run with `-Pinstall-deps` at least + once (or again after `mvn clean`). +- `BookServiceArquillianIT` (`fish.payara.examples.arquillian`) — an [Arquillian](https://arquillian.org/) in-container + test using the Payara Micro Managed connector (`fish.payara.arquillian:arquillian-payara-micro-managed`). Unlike + the black-box `*ServiceIT`/`*UiIT` tests, this one gets `BookService` `@Inject`ed straight into the test class, + running inside a real, separately-launched Payara Micro instance. It covers `AbstractService#count()`, + `#findRange(int, int)`, and the named-query lookups (`#findByNamedQuery`/`#findSingleByNamedQuery`) — the one + corner of the codebase nothing else exercises, since no REST endpoint exposes pagination/counting/named queries + and the `*Test` classes mock the `EntityManager` away entirely. See the class Javadoc for the full comparison + with the other two testing approaches. + + **This one needs more than Docker.** The Payara Micro Managed adapter launches Payara Micro as a plain OS + process rather than a Docker container, so it needs an actual runnable Payara Micro jar on disk — the + `maven-dependency-plugin` execution in the `install-deps` profile (see above) resolves one to + `target/payara-micro-${payara.version}.jar` before the integration-test phase runs. Also note the + `arquillian-payara-micro-managed` version pinned in `pom.xml` could not be verified against Maven Central from + the environment this was drafted in (no network access) — double-check it resolves before relying on this in CI. + +Both sets of Testcontainers-based IT tests (`*ServiceIT`, `*UiIT`) share a single Payara Micro Testcontainer for +the whole test run (see `fish.payara.examples.testcontainers.AbstractContainerIT`), so it's started once instead +of once per test class. `BookServiceArquillianIT` is separate: it launches its own Payara Micro instance, scoped +to just that one test class. diff --git a/ecosystem/testcontainers-example/pom.xml b/ecosystem/testcontainers-example/pom.xml index 807133d..3f58643 100644 --- a/ecosystem/testcontainers-example/pom.xml +++ b/ecosystem/testcontainers-example/pom.xml @@ -13,7 +13,18 @@ UTF-8 11 10.0.0 - 6.2025.11 + 7.2026.6 + 1.10.1.Final + 4.0.alpha4 + + 4.0.2 @@ -61,14 +72,14 @@ org.testcontainers junit-jupiter - 1.21.1 + 1.21.4 test jar org.jboss.weld weld-junit5 - 4.0.5.Final + 5.0.3.Final test @@ -81,13 +92,19 @@ org.glassfish.jersey.core jersey-client - 3.1.11.payara-p2 + ${jersey.version} test org.glassfish.jersey.inject jersey-hk2 - 3.1.11.payara-p2 + ${jersey.version} + test + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey.version} test @@ -97,10 +114,39 @@ test - org.glassfish.jersey.media - jersey-media-json-jackson + org.jboss.arquillian.junit5 + arquillian-junit5-container + ${arquillian.version} test + + fish.payara.arquillian + arquillian-payara-micro-managed + ${arquillian-payara-micro-managed.version} + test + + + org.jboss.weld + * + + + org.jboss.weld.se + * + + + + + fish.payara.extras + payara-micro + ${payara.version} + test + + + * + * + + + @@ -118,11 +164,10 @@ false - fish.payara.maven.plugins payara-micro-maven-plugin - 2.5.2 + 2.6.0 ${payara.version} true @@ -146,10 +191,12 @@ wget - true + false https://github.com/swagger-api/swagger-ui/archive/master.tar.gz true ${project.build.directory} + 60000 + 5 @@ -201,6 +248,8 @@ ${project.build.directory}/payara-micro-${payara.version}.jar + ${payara.version} + ${project.build.directory}/${project.build.finalName}.war @@ -209,19 +258,76 @@ - - - payara-nexus-artifacts - https://nexus.dev.payara.fish/repository/payara-artifacts - - true - - - false - - - - + + install-deps + + + + + org.codehaus.mojo + exec-maven-plugin + 3.6.3 + + + install-playwright-browsers + generate-test-resources + + exec + + + java + test + + -classpath + + com.microsoft.playwright.CLI + install + chromium + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.7.1 + + + copy-payara-micro-jar + generate-test-resources + + copy + + + + + fish.payara.extras + payara-micro + ${payara.version} + payara-micro-${payara.version}.jar + + + ${project.build.directory} + + + + + + + diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/BookConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/BookConverter.java index 7c6456e..74d2ab1 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/BookConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/BookConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LibrarianConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LibrarianConverter.java index efe8f99..c18a2c8 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LibrarianConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LibrarianConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LoanConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LoanConverter.java index 4c67196..1ec62a3 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LoanConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LoanConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateConverter.java index 48da22a..2ec4d14 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateTimeConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateTimeConverter.java index 151d7bb..2fd359b 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateTimeConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/LocalDateTimeConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/PatronConverter.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/PatronConverter.java index 38b3876..7a307f1 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/PatronConverter.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/converter/PatronConverter.java @@ -1,3 +1,42 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.converter; import jakarta.faces.component.UIComponent; diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Book.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Book.java index 8420f65..2899776 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Book.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Book.java @@ -1,9 +1,49 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.domain; import jakarta.persistence.*; import java.util.Objects; import java.util.List; +import java.util.UUID; import jakarta.json.bind.annotation.JsonbTransient; @NamedQueries({ @@ -15,10 +55,23 @@ @Entity public class Book { + // Plain @Id, no @GeneratedValue, with an isBlank() check in @PrePersist: + // see Librarian.assignId() for the full explanation - book.xhtml's + // "Isbn:" field is a plain h:inputText bound directly to isbn, so saving + // it blank submits "" (not null) for this String property, which needs + // the same isBlank() guard to avoid persisting a literal empty-string id. + // Note: this is a generated surrogate key, not a real ISBN - the field + // name predates this fix. @Id - @GeneratedValue(strategy = GenerationType.AUTO) private String isbn; + @PrePersist + private void assignId() { + if (isbn == null || isbn.isBlank()) { + isbn = UUID.randomUUID().toString(); + } + } + private String title; private String author; @@ -30,6 +83,33 @@ public class Book { private List loans; + @Override + public int hashCode() { + int hash = 3; + hash = 97 * hash + Objects.hashCode(this.isbn); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Book other = (Book) obj; + return Objects.equals(this.isbn, other.isbn); + } + + @Override + public String toString() { + return String.valueOf(title); + } + // Getters and setters public String getIsbn() { @@ -72,31 +152,4 @@ public void setLoans(List loans) { this.loans = loans; } - @Override - public int hashCode() { - int hash = 3; - hash = 97 * hash + Objects.hashCode(this.isbn); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Book other = (Book) obj; - return Objects.equals(this.isbn, other.isbn); - } - - @Override - public String toString() { - return String.valueOf(title); - } - } diff --git a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Librarian.java b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Librarian.java index 749d69c..3f2755c 100644 --- a/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Librarian.java +++ b/ecosystem/testcontainers-example/src/main/java/fish/payara/examples/domain/Librarian.java @@ -1,9 +1,49 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2026 Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ package fish.payara.examples.domain; import jakarta.persistence.*; import java.util.Objects; import java.util.List; +import java.util.UUID; import jakarta.json.bind.annotation.JsonbTransient; @NamedQueries({ @@ -14,10 +54,33 @@ @Entity public class Librarian { + // Plain @Id, no @GeneratedValue: JPA's generation strategies (IDENTITY/ + // SEQUENCE/TABLE/AUTO) target numeric surrogate keys; for a String @Id + // we assign it ourselves in @PrePersist instead. Checking isBlank() (not + // just null) matters: librarian.xhtml's "Librarian ID:" field is a plain + // h:inputText bound directly to this property, and unlike a numeric + // property (where JSF's implicit converter turns an empty submission into + // null), a String property gets the submitted value verbatim - so saving + // the form with that field left blank sets librarianID to "" rather than + // null. That empty string is not null, so it silently passed the create/ + // edit check as "already has an id" and, before this fix, also passed + // this method's null check unchanged - persisting the row with a literal + // empty-string id. It looked fine in this page's own list (name/actions + // still worked), but broke anything that keyed off "does this entity have + // an id yet": the loan.xhtml dropdown's converter treats "" the same as + // "no id" and renders it as an empty