From cb05a3fb504183f2c55fc75d25b5e758a303f621 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Wed, 3 Sep 2025 01:42:21 +0200 Subject: [PATCH 1/5] Jakarta Data integration - separate class graph for Persistence and NoSQL Passes Data TCK with Persistence, using the TCK runner in appserver/tests/tck/data --- appserver/featuresets/web/pom.xml | 2 +- .../persistence/jnosql-integration/pom.xml | 7 +- ...er.java => BaseGlassFishClassScanner.java} | 110 ++++++------------ ...assFishJakartaPersistenceClassScanner.java | 89 ++++++++++++++ .../GlassFishNosqlClassScanner.java | 106 +++++++++++++++++ ...akartaPersistenceIntegrationExtension.java | 4 +- .../nosql/ReflectionGroupEntityMetadata.java | 4 +- ...ng.metadata.JakartaPersistenceClassScanner | 1 + ...lipse.jnosql.mapping.metadata.ClassScanner | 2 +- ...shJakartaPersistenceClassScannerTest.java} | 6 +- appserver/pom.xml | 2 +- appserver/tests/tck/data/pom.xml | 44 +++---- appserver/tests/tck/pom.xml | 6 + 13 files changed, 276 insertions(+), 107 deletions(-) rename appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/{GlassFishClassScanner.java => BaseGlassFishClassScanner.java} (70%) create mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScanner.java create mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishNosqlClassScanner.java create mode 100644 appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner rename appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/{GlassFishClassScannerTest.java => GlassFishJakartaPersistenceClassScannerTest.java} (97%) diff --git a/appserver/featuresets/web/pom.xml b/appserver/featuresets/web/pom.xml index 1cc4240ad23..79f44bba3bf 100644 --- a/appserver/featuresets/web/pom.xml +++ b/appserver/featuresets/web/pom.xml @@ -1429,7 +1429,7 @@ org.glassfish.main.persistence - jnosql-jakarta-persistence-integration + jnosql-integration ${project.version} diff --git a/appserver/persistence/jnosql-integration/pom.xml b/appserver/persistence/jnosql-integration/pom.xml index bcc95baf158..b03148c03c8 100644 --- a/appserver/persistence/jnosql-integration/pom.xml +++ b/appserver/persistence/jnosql-integration/pom.xml @@ -25,10 +25,13 @@ 8.0.0-SNAPSHOT - jnosql-jakarta-persistence-integration + jnosql-integration glassfish-jar - Eclipse JNoSQL Jakarta Persistence Integration + Eclipse JNoSQL Integration for GlassFish + + Integration of JNoSQL, and Jakarta Data repositories for both Jakarta Persistence and NoSQL entities + diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScanner.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/BaseGlassFishClassScanner.java similarity index 70% rename from appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScanner.java rename to appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/BaseGlassFishClassScanner.java index 9e507d4e65a..e81ee6d0f0e 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScanner.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/BaseGlassFishClassScanner.java @@ -20,7 +20,6 @@ import jakarta.data.repository.DataRepository; import jakarta.data.repository.Repository; import jakarta.enterprise.inject.spi.CDI; -import jakarta.persistence.Embeddable; import jakarta.persistence.Entity; import java.util.Collection; @@ -31,8 +30,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.eclipse.jnosql.jakartapersistence.JNoSQLJakartaPersistence; -import org.eclipse.jnosql.mapping.metadata.ClassScanner; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.hk2.classmodel.reflect.AnnotationModel; @@ -45,19 +42,26 @@ import org.glassfish.internal.api.Globals; import org.glassfish.internal.deployment.Deployment; -import static java.util.stream.Collectors.toUnmodifiableSet; - /** * * @author Ondro Mihalyi */ -public class GlassFishClassScanner implements ClassScanner { +abstract public class BaseGlassFishClassScanner { + + private static final Logger LOG = Logger.getLogger(BaseGlassFishClassScanner.class.getName()); + + /** + * Whether the entity supported by this repository interface is supported by this provide (e.g. the entity class contains {@link Entity} annotation. + * @param entityType Type of the entity, analogous to the entity class + * @return True if the entity is supported, false otherwise + */ + abstract protected boolean isSupportedEntityType(ParameterizedInterfaceModel entityType); - private static final Logger LOG = Logger.getLogger(GlassFishClassScanner.class.getName()); + abstract protected String getProviderName(); /* TODO: Optimization - initialize all sets returned from methods in the CDI extension and return them directly, avoid searching for them each time */ - public Types getTypes() { + protected Types getTypes() { final ServiceLocator locator = Globals.getDefaultHabitat(); DeploymentContext deploymentContext = locator != null @@ -76,12 +80,7 @@ public Types getTypes() { } } - @Override - public Set> entities() { - return findClassesWithAnnotation(Entity.class); - } - - private Set> findClassesWithAnnotation(Class annotation) { + protected Set> findClassesWithAnnotation(Class annotation) { String annotationClassName = annotation.getName(); return getTypes().getAllTypes() .stream() @@ -92,56 +91,25 @@ private Set> findClassesWithAnnotation(Class annotation) { .collect(Collectors.toSet()); } - @Override - public Set> repositories() { - return repositoriesStream() - .collect(toUnmodifiableSet()); - } - - private Stream> repositoriesStream() { - return repositoriesStreamMatching(intfModel -> - intfModel.getParameterizedInterfaces().stream() - .anyMatch(this::isSupportedBuiltInInterface) - || DataRepository.class.isAssignableFrom(typeModelToClass(intfModel))); - } - - @Override - public Set> embeddables() { - return findClassesWithAnnotation(Embeddable.class); - } - - @Override - public > Set> repositories(Class filter) { - Objects.requireNonNull(filter, "filter is required"); - return repositoriesStream() - .filter(filter::isAssignableFrom) - .collect(toUnmodifiableSet()); - } - - @Override - public Set> repositoriesStandard() { - Predicate isSupportedBuiltInInterface = this::isSupportedBuiltInInterface; - Predicate directlyImplementsStandardInterface = this::directlyImplementsStandardInterface; - return repositoriesStreamMatching(intfModel -> intfModel.getParameterizedInterfaces().stream() - .anyMatch(isSupportedBuiltInInterface.and(directlyImplementsStandardInterface))) - .collect(toUnmodifiableSet()); + private Class typeModelToClass(ExtensibleType type) throws RuntimeException { + return classForName(type.getName()); } - @Override - public Set> customRepositories() { - return repositoriesStreamMatching(this::noneOfExtendedInterfacesIsStandard) - .collect(toUnmodifiableSet()); + private Class classForName(String name) { + try { + return Thread.currentThread().getContextClassLoader().loadClass(name); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } } - private boolean noneOfExtendedInterfacesIsStandard(InterfaceModel intfModel) { - Predicate directlyImplementsStandardInterface = this::directlyImplementsStandardInterface; - return intfModel.getParameterizedInterfaces().isEmpty() - || intfModel.getParameterizedInterfaces().stream() - .allMatch(directlyImplementsStandardInterface - .negate()); + protected Stream> repositoriesStream() { + return repositoriesStreamMatching(intfModel -> + intfModel.getParameterizedInterfaces().stream() + .anyMatch(this::isSupportedBuiltInInterface)); } - private Stream> repositoriesStreamMatching(Predicate predicate) { + protected Stream> repositoriesStreamMatching(Predicate predicate) { // TODO: Prepare a map of types per annotation on the class to avoid iteration over all types return getTypes().getAllTypes() .stream() @@ -151,7 +119,7 @@ private Stream> repositoriesStreamMatching(Predicate pr if (repositoryAnnotation != null) { String provider = repositoryAnnotation.getValue("provider", String.class); if (Objects.equals(Repository.ANY_PROVIDER, provider) - || JNoSQLJakartaPersistence.PROVIDER.equals(provider)) { + || getProviderName().equals(provider)) { return true; } } @@ -162,26 +130,22 @@ private Stream> repositoriesStreamMatching(Predicate pr .map(this::typeModelToClass); } - private Class typeModelToClass(ExtensibleType type) throws RuntimeException { - return classForName(type.getName()); - } - - private Class classForName(String name) { - try { - return Thread.currentThread().getContextClassLoader().loadClass(name); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } + protected boolean noneOfExtendedInterfacesIsStandard(InterfaceModel intfModel) { + Predicate directlyImplementsStandardInterface = this::directlyImplementsStandardInterface; + return intfModel.getParameterizedInterfaces().isEmpty() + || intfModel.getParameterizedInterfaces().stream() + .allMatch(directlyImplementsStandardInterface + .negate()); } - private boolean isSupportedBuiltInInterface(ParameterizedInterfaceModel interf) { + protected boolean isSupportedBuiltInInterface(ParameterizedInterfaceModel interf) { final Collection parameterizedTypes = interf.getParametizedTypes(); return !parameterizedTypes.isEmpty() && isSupportedEntityType(parameterizedTypes.iterator().next()) && isDataRepositoryInterface(interf); } - private boolean directlyImplementsStandardInterface(ParameterizedInterfaceModel interf) { + protected boolean directlyImplementsStandardInterface(ParameterizedInterfaceModel interf) { var types = getTypes(); Type basicRepositoryType = types.getBy(BasicRepository.class.getName()); Type crudRepositoryType = types.getBy(CrudRepository.class.getName()); @@ -199,10 +163,6 @@ private boolean isDataRepositoryInterface(ParameterizedInterfaceModel interf) { || DataRepository.class.isAssignableFrom(classForName(interf.getRawInterfaceName())); } - private boolean isSupportedEntityType(ParameterizedInterfaceModel entityType) { - return null != entityType.getRawInterface().getAnnotation(Entity.class.getName()); - } - private boolean canBeAssignedToOneOf(Class clazz, Class... assignables) { for (Class cls : assignables) { if (cls.isAssignableFrom(clazz)) { diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScanner.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScanner.java new file mode 100644 index 00000000000..49c4619cdc2 --- /dev/null +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScanner.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.main.jnosql.jakartapersistence.mapping.glassfishcontext; + +import jakarta.data.repository.DataRepository; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; + +import java.util.Objects; +import java.util.Set; +import java.util.function.Predicate; + +import org.eclipse.jnosql.jakartapersistence.JNoSQLJakartaPersistence; +import org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner; +import org.glassfish.hk2.classmodel.reflect.ParameterizedInterfaceModel; + +import static java.util.stream.Collectors.toUnmodifiableSet; + +/** + * + * @author Ondro Mihalyi + */ +public class GlassFishJakartaPersistenceClassScanner extends BaseGlassFishClassScanner implements JakartaPersistenceClassScanner { + + private boolean enabled = false; + + @Override + public Set> entities() { + return findClassesWithAnnotation(Entity.class); + } + + @Override + public Set> repositories() { + return repositoriesStream() + .collect(toUnmodifiableSet()); + } + + @Override + public Set> embeddables() { + return findClassesWithAnnotation(Embeddable.class); + } + + @Override + public > Set> repositories(Class filter) { + Objects.requireNonNull(filter, "filter is required"); + return repositoriesStream() + .filter(filter::isAssignableFrom) + .collect(toUnmodifiableSet()); + } + + @Override + public Set> repositoriesStandard() { + Predicate isSupportedBuiltInInterface = this::isSupportedBuiltInInterface; + Predicate directlyImplementsStandardInterface = this::directlyImplementsStandardInterface; + return repositoriesStreamMatching(intfModel -> intfModel.getParameterizedInterfaces().stream() + .anyMatch(isSupportedBuiltInInterface.and(directlyImplementsStandardInterface))) + .collect(toUnmodifiableSet()); + } + + @Override + public Set> customRepositories() { + return repositoriesStreamMatching(this::noneOfExtendedInterfacesIsStandard) + .collect(toUnmodifiableSet()); + } + + @Override + protected boolean isSupportedEntityType(ParameterizedInterfaceModel entityType) { + return null != entityType.getRawInterface().getAnnotation(Entity.class.getName()); + } + + @Override + protected String getProviderName() { + return JNoSQLJakartaPersistence.PROVIDER; + } + +} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishNosqlClassScanner.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishNosqlClassScanner.java new file mode 100644 index 00000000000..0853e684fbf --- /dev/null +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishNosqlClassScanner.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.main.jnosql.jakartapersistence.mapping.glassfishcontext; + +import jakarta.data.repository.DataRepository; +import jakarta.nosql.Embeddable; +import jakarta.nosql.Entity; + +import java.util.Objects; +import java.util.Set; +import java.util.function.Predicate; + +import org.eclipse.jnosql.mapping.metadata.ClassScanner; +import org.glassfish.hk2.classmodel.reflect.ParameterizedInterfaceModel; + +import static java.util.stream.Collectors.toUnmodifiableSet; + +/** + * + * @author Ondro Mihalyi + */ +public class GlassFishNosqlClassScanner extends BaseGlassFishClassScanner implements ClassScanner { + + private boolean enabled = false; + + @Override + public Set> entities() { + if (!enabled) { + return Set.of(); + } + return findClassesWithAnnotation(Entity.class); + } + + @Override + public Set> repositories() { + if (!enabled) { + return Set.of(); + } + return repositoriesStream() + .collect(toUnmodifiableSet()); + } + + @Override + public Set> embeddables() { + if (!enabled) { + return Set.of(); + } + return findClassesWithAnnotation(Embeddable.class); + } + + @Override + public > Set> repositories(Class filter) { + if (!enabled) { + return Set.of(); + } + Objects.requireNonNull(filter, "filter is required"); + return repositoriesStream() + .filter(filter::isAssignableFrom) + .collect(toUnmodifiableSet()); + } + + @Override + public Set> repositoriesStandard() { + if (!enabled) { + return Set.of(); + } + Predicate isSupportedBuiltInInterface = this::isSupportedBuiltInInterface; + Predicate directlyImplementsStandardInterface = this::directlyImplementsStandardInterface; + return repositoriesStreamMatching(intfModel -> intfModel.getParameterizedInterfaces().stream() + .anyMatch(isSupportedBuiltInInterface.and(directlyImplementsStandardInterface))) + .collect(toUnmodifiableSet()); + } + + @Override + public Set> customRepositories() { + if (!enabled) { + return Set.of(); + } + // TOTO Return NoSQL custom repositories if they are not supported by Jakarta Persistence + return Set.of(); + } + + @Override + protected boolean isSupportedEntityType(ParameterizedInterfaceModel entityType) { + return null != entityType.getRawInterface().getAnnotation(Entity.class.getName()); + } + + @Override + protected String getProviderName() { + return "Eclipse_JNoSQL"; + } + +} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java index 3d7f8babbb6..b573713851a 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java @@ -77,8 +77,8 @@ void afterBeanDiscovery(@Observes @Priority(Interceptor.Priority.LIBRARY_BEFORE) .scope(Dependent.class) // Dependent scope is OK because the state is provided via constructor .createWith(ctx -> new ApplicationContext(types)); - addBean(GlassFishClassScanner.class, afterBeanDiscovery, beanManager) - .types(ClassScanner.class, GlassFishClassScanner.class) + addBean(GlassFishJakartaPersistenceClassScanner.class, afterBeanDiscovery, beanManager) + .types(ClassScanner.class, GlassFishJakartaPersistenceClassScanner.class) .scope(ApplicationScoped.class); addBean(ReflectionGroupEntityMetadata.class, afterBeanDiscovery, beanManager) diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java index cd22351c293..df4f8215c62 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java @@ -20,8 +20,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner; import org.eclipse.jnosql.mapping.metadata.ClassConverter; -import org.eclipse.jnosql.mapping.metadata.ClassScanner; import org.eclipse.jnosql.mapping.metadata.EntityMetadata; import org.eclipse.jnosql.mapping.metadata.GroupEntityMetadata; @@ -41,7 +41,7 @@ public class ReflectionGroupEntityMetadata implements GroupEntityMetadata { @PostConstruct public void postConstruct() { var converter = ClassConverter.load(); - var scanner = ClassScanner.load(); + var scanner = JakartaPersistenceClassScanner.load(); for (Class entity : scanner.entities()) { EntityMetadata entityMetadata = converter.apply(entity); if (entityMetadata.hasEntityName()) { diff --git a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner new file mode 100644 index 00000000000..40efa7b673b --- /dev/null +++ b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner @@ -0,0 +1 @@ +org.glassfish.main.jnosql.jakartapersistence.mapping.glassfishcontext.GlassFishJakartaPersistenceClassScanner \ No newline at end of file diff --git a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassScanner b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassScanner index 28ff8034744..ec2153139fa 100644 --- a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassScanner +++ b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassScanner @@ -1 +1 @@ -org.glassfish.main.jnosql.jakartapersistence.mapping.glassfishcontext.GlassFishClassScanner \ No newline at end of file +org.glassfish.main.jnosql.jakartapersistence.mapping.glassfishcontext.GlassFishNosqlClassScanner \ No newline at end of file diff --git a/appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScannerTest.java b/appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScannerTest.java similarity index 97% rename from appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScannerTest.java rename to appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScannerTest.java index a14cff4ba29..6f0920ccc9b 100644 --- a/appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishClassScannerTest.java +++ b/appserver/persistence/jnosql-integration/src/test/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/GlassFishJakartaPersistenceClassScannerTest.java @@ -53,9 +53,9 @@ * * @author Ondro Mihalyi */ -public class GlassFishClassScannerTest { +public class GlassFishJakartaPersistenceClassScannerTest { - public GlassFishClassScannerTest() { + public GlassFishJakartaPersistenceClassScannerTest() { } @Test @@ -88,7 +88,7 @@ public void testVariousRepositories() throws URISyntaxException, IOException, In Types types = parseClasses(allClasses); configureCDI(types); - final GlassFishClassScanner scanner = new GlassFishClassScanner(); + final GlassFishJakartaPersistenceClassScanner scanner = new GlassFishJakartaPersistenceClassScanner(); final Set> repositoriesStandardResult = scanner.repositoriesStandard(); assertTrue(repositoriesStandardResult.equals(standardRepositories), "Standard repositories: " + repositoriesStandardResult); diff --git a/appserver/pom.xml b/appserver/pom.xml index cd96eb0b4e0..80ecb60d30d 100644 --- a/appserver/pom.xml +++ b/appserver/pom.xml @@ -116,7 +116,7 @@ 1.0.1 1.0.1 - 1.1.10 + 1.1.11-SNAPSHOT 3.2.0 diff --git a/appserver/tests/tck/data/pom.xml b/appserver/tests/tck/data/pom.xml index 5e856b7be54..b32817d505f 100644 --- a/appserver/tests/tck/data/pom.xml +++ b/appserver/tests/tck/data/pom.xml @@ -1,21 +1,21 @@ +~ Copyright (c) 2022,2023 Contributors to the Eclipse Foundation +~ +~ 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. +~ +~ SPDX-License-Identifier: Apache-2.0 +--> 4.0.0 @@ -33,10 +33,10 @@ Jakarta Data TCK Web Runner for GlassFish - ${glassfish.root}/glassfish${glassfish.version.main} ${project.build.directory} + ${glassfish.root}/glassfish${glassfish.version.main} ${glassfish.home}/glassfish/lib - 8.0.0-M12 + 8.0.0-SNAPSHOT 8 11.0.1 @@ -47,6 +47,7 @@ 2.3 6.0.3.Final + 2.1.1 @@ -111,7 +112,7 @@ + tests --> org.jboss.shrinkwrap shrinkwrap-api @@ -184,7 +185,7 @@ + use this to distinguish the results --> core @@ -223,6 +224,7 @@ ee.omnifish.arquillian arquillian-glassfish-server-managed + 2.1.1 test @@ -268,6 +270,7 @@ ee.omnifish.arquillian arquillian-glassfish-server-managed test + ${omnifish.arquillian.version} @@ -280,6 +283,7 @@ ee.omnifish.arquillian arquillian-glassfish-server-remote + ${omnifish.arquillian.version} diff --git a/appserver/tests/tck/pom.xml b/appserver/tests/tck/pom.xml index 9bb77209273..6ac98719d81 100644 --- a/appserver/tests/tck/pom.xml +++ b/appserver/tests/tck/pom.xml @@ -127,6 +127,12 @@ ${omnifish.arquillian.version} test + + ee.omnifish.arquillian + arquillian-glassfish-server-remote + ${omnifish.arquillian.version} + test + org.jboss.arquillian.protocol From d2d4888b999f816ea2770664774162ef2f60f090 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Fri, 5 Sep 2025 22:53:11 +0200 Subject: [PATCH 2/5] Jakarta Data integration - Cleanup Based on "Clean up" commit in jnosql-extensions. Preparation for integrating NoSQL Data repositories. --- ...akartaPersistenceIntegrationExtension.java | 12 - .../nosql/AbstractFieldMetadata.java | 148 ------ .../nosql/ConstructorComparable.java | 42 -- .../nosql/ConstructorException.java | 28 -- .../nosql/ConstructorMetadataBuilder.java | 44 -- .../nosql/DefaultArrayFieldMetadata.java | 119 ----- .../nosql/DefaultArrayParameterMetaData.java | 68 --- .../nosql/DefaultCollectionFieldMetadata.java | 136 ------ .../DefaultCollectionParameterMetaData.java | 73 --- .../nosql/DefaultConstructorMetadata.java | 30 -- .../nosql/DefaultEntitiesMetadata.java | 128 ------ .../nosql/DefaultEntityMetadata.java | 205 --------- .../nosql/DefaultFieldMetadata.java | 83 ---- .../nosql/DefaultMapFieldMetadata.java | 102 ----- .../nosql/DefaultMapParameterMetaData.java | 70 --- .../nosql/DefaultParameterMetaData.java | 108 ----- .../nosql/EmbeddedFieldMetadata.java | 67 --- .../nosql/EntityMetadataBuilder.java | 108 ----- .../reflection/nosql/FieldMappingBuilder.java | 127 ------ .../mapping/reflection/nosql/FieldReader.java | 32 -- .../mapping/reflection/nosql/FieldWriter.java | 32 -- .../reflection/nosql/InstanceSupplier.java | 24 - .../reflection/nosql/NativeMapping.java | 24 - .../nosql/ParameterMetaDataBuilder.java | 75 --- .../nosql/ReflectionClassConverter.java | 209 --------- .../nosql/ReflectionGroupEntityMetadata.java | 68 --- .../mapping/reflection/nosql/Reflections.java | 431 ------------------ .../mapping/reflection/nosql/StringUtils.java | 60 --- ...pse.jnosql.mapping.metadata.ClassConverter | 2 - ...jnosql.mapping.metadata.CollectionSupplier | 5 - 30 files changed, 2660 deletions(-) delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/AbstractFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorComparable.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorException.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorMetadataBuilder.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayParameterMetaData.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionParameterMetaData.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultConstructorMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntitiesMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntityMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapParameterMetaData.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultParameterMetaData.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EmbeddedFieldMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EntityMetadataBuilder.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldMappingBuilder.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldReader.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldWriter.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/InstanceSupplier.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/NativeMapping.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ParameterMetaDataBuilder.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionClassConverter.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/Reflections.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/StringUtils.java delete mode 100644 appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassConverter delete mode 100644 appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.CollectionSupplier diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java index b573713851a..a1c7bbe0005 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java @@ -41,14 +41,10 @@ import org.eclipse.jnosql.mapping.core.Converters; import org.eclipse.jnosql.mapping.core.spi.AbstractBean; import org.eclipse.jnosql.mapping.metadata.ClassScanner; -import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata; -import org.eclipse.jnosql.mapping.metadata.GroupEntityMetadata; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.hk2.classmodel.reflect.Types; import org.glassfish.internal.api.Globals; import org.glassfish.internal.deployment.Deployment; -import org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql.DefaultEntitiesMetadata; -import org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql.ReflectionGroupEntityMetadata; /** * TODO - consider moving to weld-integration module, following the existing @@ -81,14 +77,6 @@ void afterBeanDiscovery(@Observes @Priority(Interceptor.Priority.LIBRARY_BEFORE) .types(ClassScanner.class, GlassFishJakartaPersistenceClassScanner.class) .scope(ApplicationScoped.class); - addBean(ReflectionGroupEntityMetadata.class, afterBeanDiscovery, beanManager) - .types(GroupEntityMetadata.class) - .scope(ApplicationScoped.class); - - addBean(DefaultEntitiesMetadata.class, afterBeanDiscovery, beanManager) - .types(EntitiesMetadata.class) - .scope(ApplicationScoped.class); - addBean(GlassFishRepositoryInterceptor.class, afterBeanDiscovery, beanManager) .types(MethodInterceptor.class) .qualifiers(MethodInterceptor.Repository.INSTANCE) diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/AbstractFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/AbstractFieldMetadata.java deleted file mode 100644 index 80787e69810..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/AbstractFieldMetadata.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.NoSQLException; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; - -import org.eclipse.jnosql.communication.Value; -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -/** - * Base class to all {@link FieldMetadata} - * - * @see FieldMetadata - */ -abstract class AbstractFieldMetadata implements FieldMetadata { - - protected final MappingType mappingType; - - protected final Field field; - - protected final String name; - - protected final String fieldName; - - protected final Class> converter; - - protected final FieldReader reader; - - protected final FieldWriter writer; - - protected final Class type; - - protected final String udt; - - AbstractFieldMetadata(MappingType mappingType, Field field, String name, - Class> converter, - FieldReader reader, FieldWriter writer, String udt) { - this.mappingType = mappingType; - this.field = field; - this.name = name; - this.fieldName = field.getName(); - this.converter = converter; - this.reader = reader; - this.writer = writer; - this.type = field.getType(); - this.udt = udt; - } - - @Override - public MappingType mappingType() { - return mappingType; - } - - @Override - public String name() { - return name; - } - - @Override - public String fieldName() { - return fieldName; - } - - @Override - public Optional udt(){ - if(udt == null|| udt.isEmpty() || udt.isBlank()){ - return Optional.empty(); - } - return Optional.of(udt); - } - - @Override - public Object read(Object bean) { - Objects.requireNonNull(bean, "bean is required"); - return this.reader.read(bean); - } - - @Override - public void write(Object bean, Object value) { - Objects.requireNonNull(bean, "bean is required"); - this.writer.write(bean, value); - } - - @Override - public Class type() { - return this.type; - } - - @SuppressWarnings("unchecked") - @Override - public > Optional> converter() { - return Optional.ofNullable((Class) converter); - } - - @SuppressWarnings("unchecked") - @Override - public > Optional newConverter() { - return (Optional) Optional.ofNullable(converter).map(Reflections::newInstance); - } - - @Override - public Object value(Value value) { - return value.get(field.getType()); - } - - - @Override - public Optional value(Class type){ - Objects.requireNonNull(type, "type is required"); - Optional method = Arrays.stream(type.getDeclaredMethods()).filter(m -> "value".equals(m.getName())) - .findFirst(); - T annotation = this.field.getAnnotation(type); - if (method.isEmpty() || annotation == null) { - return Optional.empty(); - } - return method.map(m -> { - try { - Object invoke = m.invoke(annotation); - return invoke.toString(); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new NoSQLException("There is an issue invoking the method: " + m + " using the annotation: " - + type, e); - } - }); - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorComparable.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorComparable.java deleted file mode 100644 index 0e126fc9d27..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorComparable.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import java.lang.reflect.Constructor; -import java.util.Comparator; - -/** - * This Comparator defines the priority of the entity's constructor that JNoSQL will use as a priority. - * The emphasis will be on a default constructor, a non-arg-param constructor. - * - */ -enum ConstructorComparable implements Comparator> { - - INSTANCE; - - @Override - public int compare(Constructor constructorA, Constructor constructorB) { - int parameterCount = constructorA.getParameterCount(); - int parameterCountB = constructorB.getParameterCount(); - if (parameterCount == 0 && parameterCountB == 0) { - return 0; - } else if (parameterCount == 0) { - return -1; - } else if (parameterCountB == 0) { - return 1; - } - return 0; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorException.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorException.java deleted file mode 100644 index 005118adcb2..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -import jakarta.data.exceptions.MappingException; - -/** - * Get the exception when a class has a no arg constructor either public or default - */ -public class ConstructorException extends MappingException { - - public ConstructorException(Class type) { - super("This class must have a no arg with either public or default visibility: " + type.getName()); - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorMetadataBuilder.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorMetadataBuilder.java deleted file mode 100644 index bebd2b49b3a..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ConstructorMetadataBuilder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import java.lang.reflect.Constructor; -import java.util.Collections; -import java.util.List; -import java.util.stream.Stream; - -import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; -import org.eclipse.jnosql.mapping.metadata.ParameterMetaData; - -final class ConstructorMetadataBuilder { - - private final Reflections reflections; - - ConstructorMetadataBuilder(Reflections reflections) { - this.reflections = reflections; - } - - ConstructorMetadata build(Class entity) { - Constructor constructor = reflections.getConstructor(entity); - if (constructor.getParameterCount() == 0) { - return new DefaultConstructorMetadata(constructor, Collections.emptyList()); - } - - List parameters = Stream.of(constructor.getParameters()) - .map(ParameterMetaDataBuilder::of) - .toList(); - return new DefaultConstructorMetadata(constructor, parameters); - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayFieldMetadata.java deleted file mode 100644 index 07fe0918bf4..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayFieldMetadata.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import org.eclipse.jnosql.communication.TypeReference; -import org.eclipse.jnosql.communication.Value; -import org.eclipse.jnosql.mapping.metadata.ArrayFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -final class DefaultArrayFieldMetadata extends AbstractFieldMetadata implements ArrayFieldMetadata { - - private static final TypeReference> TYPE_SUPPLIER = new TypeReference<>() {}; - private final Class elementType; - private final boolean entityField; - private final boolean embeddableField; - - DefaultArrayFieldMetadata(MappingType type, Field field, String name, Class elementType, - Class> converter, - FieldReader reader, FieldWriter writer, String udt) { - super(type, field, name, converter, reader, writer, udt); - this.elementType = elementType; - this.entityField = hasFieldAnnotation(Entity.class); - this.embeddableField = hasFieldAnnotation(Embeddable.class); - } - - @Override - public Object value(Value value) { - Objects.requireNonNull(value, "value is required"); - if(value.get() instanceof Iterable) { - return value.get(TYPE_SUPPLIER).toArray(); - } else { - return Value.of(Collections.singletonList(value.get())).get(TYPE_SUPPLIER); - } - } - - @Override - public boolean isId() { - return false; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultArrayFieldMetadata that = (DefaultArrayFieldMetadata) o; - return mappingType == that.mappingType && - Objects.equals(field, that.field) && - Objects.equals(elementType, that.elementType) && - Objects.equals(name, that.name); - } - - - - @Override - public int hashCode() { - return Objects.hash(mappingType, field, name, elementType); - } - - @Override - public boolean isEmbeddable() { - return isEmbeddableField() || isEntityField(); - } - - private boolean isEntityField() { - return entityField; - } - - private boolean isEmbeddableField() { - return embeddableField; - } - - private boolean hasFieldAnnotation(Class annotation) { - return elementType.getAnnotation(annotation) != null; - } - - @Override - public Class elementType() { - return elementType; - } - - @Override - public Object arrayInstance(Collection collection) { - var array = Array.newInstance(elementType, collection.size()); - int index = 0; - for (Object item : collection) { - Array.set(array, index++, item); - } - return array; - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayParameterMetaData.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayParameterMetaData.java deleted file mode 100644 index eecceb9eb3b..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultArrayParameterMetaData.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.Collection; - -import org.eclipse.jnosql.mapping.metadata.ArrayParameterMetaData; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -class DefaultArrayParameterMetaData extends DefaultParameterMetaData implements ArrayParameterMetaData { - - - private final Class elementType; - - private final boolean embeddableField; - - DefaultArrayParameterMetaData(String name, Class type, boolean id, - Class> converter, - MappingType mappingType, Class elementType) { - super(name, type, id, converter, mappingType); - this.elementType = elementType; - this.embeddableField = hasFieldAnnotation(Embeddable.class) || hasFieldAnnotation(Entity.class); - } - - @Override - public boolean isEmbeddable() { - return embeddableField; - } - - @Override - public Class elementType() { - return elementType; - } - - @Override - public Object arrayInstance(Collection collection) { - var array = Array.newInstance(elementType, collection.size()); - int index = 0; - for (Object item : collection) { - Array.set(array, index++, item); - } - return array; - } - - private boolean hasFieldAnnotation(Class annotation) { - return this.elementType.getAnnotation(annotation) != null; - } - - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionFieldMetadata.java deleted file mode 100644 index 8fad01424e5..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionFieldMetadata.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.text.MessageFormat; -import java.util.Collection; -import java.util.Collections; -import java.util.Objects; -import java.util.ServiceLoader; - -import org.eclipse.jnosql.communication.TypeSupplier; -import org.eclipse.jnosql.communication.Value; -import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.CollectionSupplier; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -final class DefaultCollectionFieldMetadata extends AbstractFieldMetadata implements CollectionFieldMetadata { - - private final TypeSupplier typeSupplier; - private final boolean entityField; - private final boolean embeddableField; - - DefaultCollectionFieldMetadata(MappingType type, Field field, String name, TypeSupplier typeSupplier, - Class> converter, - FieldReader reader, FieldWriter writer, String udt) { - super(type, field, name, converter, reader, writer, udt); - this.typeSupplier = typeSupplier; - this.entityField = hasFieldAnnotation(Entity.class); - this.embeddableField = hasFieldAnnotation(Embeddable.class); - } - - @Override - public Object value(Value value) { - if(value.get() instanceof Iterable) { - return value.get(typeSupplier); - } else { - return Value.of(Collections.singletonList(value.get())).get(typeSupplier); - } - } - - @Override - public boolean isId() { - return false; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultCollectionFieldMetadata that = (DefaultCollectionFieldMetadata) o; - return mappingType == that.mappingType && - Objects.equals(field, that.field) && - Objects.equals(typeSupplier, that.typeSupplier) && - Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(mappingType, field, name, typeSupplier); - } - - @Override - public boolean isEmbeddable() { - return isEmbeddableField() || isEntityField(); - } - - private boolean isEntityField() { - return entityField; - } - - private boolean isEmbeddableField() { - return embeddableField; - } - - @SuppressWarnings("unchecked") - private boolean hasFieldAnnotation(Class annotation) { - ParameterizedType collectionType = Reflections.findParameterizedType(this.field.getGenericType(), Collection.class) - .orElseThrow(() -> new IllegalStateException(MessageFormat.format("Unable to find parameterized Collection implementation for {0}", this.field))); - return ((Class) collectionType - .getActualTypeArguments()[0]) - .getAnnotation(annotation) != null; - } - - @Override - public Class elementType() { - return (Class) ((ParameterizedType) this.field - .getGenericType()) - .getActualTypeArguments()[0]; - } - - @Override - public Collection collectionInstance() { - Class type = type(); - final CollectionSupplier supplier = ServiceLoader.load(CollectionSupplier.class) - .stream() - .map(ServiceLoader.Provider::get) - .map(CollectionSupplier.class::cast) - .filter(c -> c.test(type)) - .findFirst() - .orElseThrow(() -> new UnsupportedOperationException("This collection is not supported yet: " + type)); - return (Collection) supplier.get(); - } - - @Override - public String toString() { - return "DefaultCollectionFieldMetadata{" + "typeSupplier=" + typeSupplier + - ", type=" + mappingType + - ", field=" + field + - ", name='" + name + '\'' + - ", fieldName='" + fieldName + '\'' + - ", converter=" + converter + - '}'; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionParameterMetaData.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionParameterMetaData.java deleted file mode 100644 index 090e82c062a..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultCollectionParameterMetaData.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.annotation.Annotation; -import java.lang.reflect.ParameterizedType; -import java.util.Collection; -import java.util.ServiceLoader; - -import org.eclipse.jnosql.communication.TypeSupplier; -import org.eclipse.jnosql.mapping.metadata.CollectionParameterMetaData; -import org.eclipse.jnosql.mapping.metadata.CollectionSupplier; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -class DefaultCollectionParameterMetaData extends DefaultParameterMetaData implements CollectionParameterMetaData { - - private final Class elementType; - - private final boolean embeddableField; - - DefaultCollectionParameterMetaData(String name, Class type, boolean id, - Class> converter, - MappingType mappingType, TypeSupplier typeSupplier) { - super(name, type, id, converter, mappingType); - this.elementType = (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[0]; - this.embeddableField = hasFieldAnnotation(Embeddable.class) || hasFieldAnnotation(Entity.class); - } - - @Override - public boolean isEmbeddable() { - return embeddableField; - } - - @Override - public Class elementType() { - return this.elementType; - } - - @SuppressWarnings("rawtypes") - @Override - public Collection collectionInstance() { - Class type = type(); - final CollectionSupplier supplier = ServiceLoader.load(CollectionSupplier.class) - .stream() - .map(ServiceLoader.Provider::get) - .map(CollectionSupplier.class::cast) - .filter(c -> c.test(type)) - .findFirst() - .orElseThrow(() -> new UnsupportedOperationException("This collection is not supported yet: " + type)); - return (Collection) supplier.get(); - } - - private boolean hasFieldAnnotation(Class annotation) { - return this.elementType.getAnnotation(annotation) != null; - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultConstructorMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultConstructorMetadata.java deleted file mode 100644 index 0723972d680..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultConstructorMetadata.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import java.lang.reflect.Constructor; -import java.util.List; - -import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; -import org.eclipse.jnosql.mapping.metadata.ParameterMetaData; -record DefaultConstructorMetadata(Constructor constructor, - List parameters) implements ConstructorMetadata { - - @Override - public boolean isDefault() { - return parameters.isEmpty(); - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntitiesMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntitiesMetadata.java deleted file mode 100644 index d6c3d7f4861..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntitiesMetadata.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.eclipse.jnosql.mapping.metadata.ClassConverter; -import org.eclipse.jnosql.mapping.metadata.ClassInformationNotFoundException; -import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata; -import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.GroupEntityMetadata; -import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; - -/** - * The default implementation of {@link EntityMetadata}. - * It's storage the class information in a {@link ConcurrentHashMap} - */ -@ApplicationScoped -public class DefaultEntitiesMetadata implements EntitiesMetadata { - - private final Map mappings; - - private final Map, EntityMetadata> classes; - - private final Map findBySimpleName; - - private final Map findByClassName; - - - private final ClassConverter converter; - - @Inject - private GroupEntityMetadata extension; - - public DefaultEntitiesMetadata() { - this.mappings = new ConcurrentHashMap<>(); - this.classes = new ConcurrentHashMap<>(); - this.findBySimpleName = new ConcurrentHashMap<>(); - this.findByClassName = new ConcurrentHashMap<>(); - this.converter = new ReflectionClassConverter(); - } - - @PostConstruct - public void init() { - classes.putAll(extension.classes()); - extension.mappings().forEach((k, v) -> mappings.put(k.toUpperCase(Locale.US), v)); - mappings.values().forEach(r -> { - findBySimpleName.put(r.simpleName(), r); - findByClassName.put(r.className(), r); - }); - } - - EntityMetadata load(Class type) { - EntityMetadata metadata = converter.apply(type); - if (metadata.hasEntityName()) { - mappings.put(type.getName().toUpperCase(Locale.US), metadata); - } - this.findBySimpleName.put(type.getSimpleName(), metadata); - this.findByClassName.put(type.getName(), metadata); - return metadata; - } - - @Override - public EntityMetadata get(Class entity) { - return classes.computeIfAbsent(entity, this::load); - } - - @Override - public Map findByParentGroupByDiscriminatorValue(Class parent) { - Objects.requireNonNull(parent, "parent is required"); - return this.classes.values().stream() - .flatMap(c -> c.inheritance().stream()) - .filter(p -> p.isParent(parent)) - .collect(Collectors.toMap(InheritanceMetadata::discriminatorValue, Function.identity())); - } - - @Override - public EntityMetadata findByName(String name) { - Objects.requireNonNull(name, "name is required"); - return Optional.ofNullable(mappings.get(name.toUpperCase(Locale.US))) - .orElseThrow(() -> new ClassInformationNotFoundException("There is not entity found with the name: " + name)); - - } - - @Override - public Optional findBySimpleName(String name) { - Objects.requireNonNull(name, "name is required"); - return Optional.ofNullable(findBySimpleName.get(name)); - } - - @Override - public Optional findByClassName(String name) { - Objects.requireNonNull(name, "name is required"); - return Optional.ofNullable(findByClassName.get(name)); - } - - @Override - public String toString() { - return "DefaultEntitiesMetadata{" + "mappings-size=" + mappings.size() + - ", classes=" + classes + - ", classConverter=" + converter + - ", extension=" + extension + - '}'; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntityMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntityMetadata.java deleted file mode 100644 index 2c39049030e..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultEntityMetadata.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; -import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; - -import static java.util.Objects.requireNonNull; -import static java.util.Optional.ofNullable; - -class DefaultEntityMetadata implements EntityMetadata { - - - private final String name; - - private final String simpleName; - - private final String className; - - private final List fieldsName; - - private final Class type; - - private final List fields; - - private final InstanceSupplier instanceSupplier; - - private final Map javaFieldGroupedByColumn; - - private final Map fieldsGroupedByName; - - private final FieldMetadata id; - - private final InheritanceMetadata inheritance; - - private final boolean hasInheritanceAnnotation; - - private final ConstructorMetadata constructor; - - DefaultEntityMetadata(String name, List fieldsName, Class type, - List fields, - Map javaFieldGroupedByColumn, - Map fieldsGroupedByName, - InstanceSupplier instanceSupplier, - InheritanceMetadata inheritance, - ConstructorMetadata constructor, - boolean hasInheritanceAnnotation) { - this.name = name; - this.simpleName = type.getSimpleName(); - this.className = type.getName(); - this.fieldsName = fieldsName; - this.type = type; - this.fields = fields; - this.fieldsGroupedByName = fieldsGroupedByName; - this.javaFieldGroupedByColumn = javaFieldGroupedByColumn; - this.instanceSupplier = instanceSupplier; - this.id = fields.stream().filter(FieldMetadata::isId).findFirst().orElse(null); - this.inheritance = inheritance; - this.constructor = constructor; - this.hasInheritanceAnnotation = hasInheritanceAnnotation; - } - - @Override - public String name() { - return name; - } - - @Override - public String simpleName() { - return simpleName; - } - - @Override - public String className() { - return this.className; - } - - @Override - public List fieldsName() { - return fieldsName; - } - - @Override - public Class type() { - return type; - } - - @Override - public Optional inheritance() { - return ofNullable(inheritance); - } - - @Override - public boolean hasEntityName() { - return Objects.isNull(inheritance) || hasInheritanceAnnotation; - } - - @Override - public boolean isInheritance() { - return hasInheritanceAnnotation; - } - - @Override - public List fields() { - return fields; - } - - @Override - public T newInstance() { - return (T) instanceSupplier.get(); - } - - @Override - public ConstructorMetadata constructor() { - return constructor; - } - - @Override - public String columnField(String javaField) { - requireNonNull(javaField, "javaField is required"); - return ofNullable(javaFieldGroupedByColumn.get(javaField)) - .map(NativeMapping::nativeField).orElse(javaField); - - } - - @Override - public Optional fieldMapping(String javaField) { - requireNonNull(javaField, "javaField is required"); - return ofNullable(javaFieldGroupedByColumn.get(javaField)) - .map(NativeMapping::fieldMetadata); - } - - @Override - public Map fieldsGroupByName() { - return fieldsGroupedByName; - } - - @Override - public Optional id() { - return ofNullable(id); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof DefaultEntityMetadata that)) { - return false; - } - return Objects.equals(type, that.type); - } - - @Override - public int hashCode() { - return Objects.hashCode(type); - } - - @Override - public String toString() { - return "DefaultEntityMetadata{" + - "name='" + name + '\'' + - ", fieldsName=" + fieldsName + - ", classInstance=" + type + - ", fields=" + fields + - ", instanceSupplier=" + instanceSupplier + - ", javaFieldGroupedByColumn=" + javaFieldGroupedByColumn + - ", fieldsGroupedByName=" + fieldsGroupedByName + - ", id=" + id + - ", inheritance=" + inheritance + - ", hasInheritanceAnnotation=" + hasInheritanceAnnotation + - '}'; - } - - /** - * Creates a builder - * - * @return {@link EntityMetadataBuilder} - */ - static EntityMetadataBuilder builder() { - return new EntityMetadataBuilder(); - } - - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultFieldMetadata.java deleted file mode 100644 index 5d4c7037a7e..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultFieldMetadata.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -import jakarta.nosql.AttributeConverter; - -import java.lang.reflect.Field; -import java.util.Objects; -import java.util.Optional; - -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -/** - * Class that represents {@link FieldMetadata} a default field - */ -public class DefaultFieldMetadata extends AbstractFieldMetadata { - - - private final boolean id; - - DefaultFieldMetadata(MappingType type, Field field, String name, - Class> converter, boolean id, - FieldReader reader, FieldWriter writer, String udt) { - super(type, field, name, converter, reader, writer, udt); - this.id = id; - } - - @Override - public boolean isId() { - return id; - } - - @SuppressWarnings("unchecked") - @Override - public > Optional newConverter() { - return (Optional) Optional.ofNullable(Reflections.newInstance(converter)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - AbstractFieldMetadata that = (AbstractFieldMetadata) o; - return mappingType == that.mappingType && - Objects.equals(field, that.field) && - Objects.equals(name, that.name); - } - - - @Override - public int hashCode() { - return Objects.hash(mappingType, field, name); - } - - @Override - public String toString() { - return "DefaultFieldMapping{" + "id=" + id + - ", type=" + mappingType + - ", field=" + field + - ", name='" + name + '\'' + - ", fieldName='" + fieldName + '\'' + - ", converter=" + converter + - '}'; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapFieldMetadata.java deleted file mode 100644 index 4a2c46e96f3..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapFieldMetadata.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.text.MessageFormat; -import java.util.Map; -import java.util.Objects; - -import org.eclipse.jnosql.communication.TypeSupplier; -import org.eclipse.jnosql.communication.Value; -import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -final class DefaultMapFieldMetadata extends AbstractFieldMetadata implements MapFieldMetadata { - - private final TypeSupplier typeSupplier; - - private final Class keyType; - - private final Class valueType; - - private final boolean embeddableField; - - DefaultMapFieldMetadata(MappingType type, Field field, String name, TypeSupplier typeSupplier, - Class> converter, - FieldReader reader, FieldWriter writer, String udt) { - super(type, field, name, converter, reader, writer, udt); - this.typeSupplier = typeSupplier; - ParameterizedType mapType = Reflections.findParameterizedType(this.field.getGenericType(), Map.class) - .orElseThrow(() -> new IllegalStateException(MessageFormat.format("Unable to find parameterized Map implementation for {0}", this.field))); - this.keyType = (Class) mapType.getActualTypeArguments()[0]; - this.valueType = (Class) mapType.getActualTypeArguments()[1]; - this.embeddableField = hasFieldAnnotation(Embeddable.class) || hasFieldAnnotation(Entity.class); - } - - @Override - public Object value(Value value) { - return value.get(typeSupplier); - } - - @Override - public boolean isId() { - return false; - } - - - @Override - public boolean isEmbeddable() { - return embeddableField; - } - - @Override - public Class keyType() { - return keyType; - } - - @Override - public Class valueType() { - return valueType; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultMapFieldMetadata that = (DefaultMapFieldMetadata) o; - return Objects.equals(typeSupplier, that.typeSupplier) && Objects.equals(keyType, that.keyType) && Objects.equals(valueType, that.valueType); - } - - @Override - public int hashCode() { - return Objects.hash(typeSupplier, keyType, valueType); - } - - private boolean hasFieldAnnotation(Class annotation) { - return this.valueType.getAnnotation(annotation) != null; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapParameterMetaData.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapParameterMetaData.java deleted file mode 100644 index acc43743e17..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultMapParameterMetaData.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; -import jakarta.nosql.Embeddable; -import jakarta.nosql.Entity; - -import java.lang.annotation.Annotation; -import java.lang.reflect.ParameterizedType; - -import org.eclipse.jnosql.communication.TypeSupplier; -import org.eclipse.jnosql.communication.Value; -import org.eclipse.jnosql.mapping.metadata.MapParameterMetaData; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -class DefaultMapParameterMetaData extends DefaultParameterMetaData implements MapParameterMetaData { - - private final TypeSupplier typeSupplier; - private final Class keyType; - private final Class valueType; - private final boolean embeddableField; - - DefaultMapParameterMetaData(String name, Class type, boolean id, - Class> converter, - MappingType mappingType, TypeSupplier typeSupplier) { - super(name, type, id, converter, mappingType); - this.typeSupplier = typeSupplier; - this.keyType = (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[0]; - this.valueType = (Class) ((ParameterizedType) typeSupplier.get()).getActualTypeArguments()[1]; - this.embeddableField = hasFieldAnnotation(Embeddable.class) || hasFieldAnnotation(Entity.class); - } - - @Override - public boolean isEmbeddable() { - return embeddableField; - } - - @Override - public Class keyType() { - return this.keyType; - } - - @Override - public Class valueType() { - return this.valueType; - } - - @Override - public Object value(Value value) { - return value.get(typeSupplier); - } - - private boolean hasFieldAnnotation(Class annotation) { - return this.valueType.getAnnotation(annotation) != null; - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultParameterMetaData.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultParameterMetaData.java deleted file mode 100644 index 2c87432253e..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/DefaultParameterMetaData.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; - -import java.util.Objects; -import java.util.Optional; - -import org.eclipse.jnosql.mapping.metadata.MappingType; -import org.eclipse.jnosql.mapping.metadata.ParameterMetaData; - -class DefaultParameterMetaData implements ParameterMetaData { - - private final String name; - - private final Class type; - - private final boolean id; - - private final MappingType mappingType; - - private final Class> converter; - - DefaultParameterMetaData(String name, - Class type, boolean id, - Class> converter, - MappingType mappingType) { - this.name = name; - this.type = type; - this.id = id; - this.converter = converter; - this.mappingType = mappingType; - } - - @Override - public MappingType mappingType() { - return mappingType; - } - - @Override - public String name() { - return name; - } - - @Override - public Class type() { - return type; - } - - @Override - public boolean isId() { - return id; - } - - @SuppressWarnings("unchecked") - @Override - public > Optional> converter() { - return Optional.ofNullable((Class)converter); - } - - @SuppressWarnings("unchecked") - @Override - public > Optional newConverter() { - return Optional.ofNullable(converter).map(c -> (T) Reflections.newInstance(c)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultParameterMetaData that = (DefaultParameterMetaData) o; - return id == that.id && Objects.equals(name, that.name) - && Objects.equals(type, that.type) - && Objects.equals(converter, that.converter); - } - - @Override - public int hashCode() { - return Objects.hash(name, type, id, converter); - } - - @Override - public String toString() { - return "ParameterMetaData{" + - "name='" + name + '\'' + - ", type=" + type + - ", id=" + id + - ", converter=" + converter + - '}'; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EmbeddedFieldMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EmbeddedFieldMetadata.java deleted file mode 100644 index b484f623af7..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EmbeddedFieldMetadata.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import java.lang.reflect.Field; -import java.util.Objects; - -import org.eclipse.jnosql.mapping.metadata.MappingType; - -final class EmbeddedFieldMetadata extends AbstractFieldMetadata { - - private final String entityName; - - public EmbeddedFieldMetadata(MappingType type, Field field, String name, String entityName, - FieldReader reader, FieldWriter writer, String udt) { - super(type, field, name, null, reader, writer, udt); - this.entityName = entityName; - } - - @Override - public boolean isId() { - return false; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - EmbeddedFieldMetadata that = (EmbeddedFieldMetadata) o; - return mappingType == that.mappingType && - Objects.equals(field, that.field) && - Objects.equals(entityName, that.entityName) && - Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(mappingType, field, name, entityName); - } - - @Override - public String toString() { - return "EmbeddedFieldMapping{" + "entityName='" + entityName + '\'' + - ", type=" + mappingType + - ", field=" + field + - ", name='" + name + '\'' + - ", fieldName='" + fieldName + '\'' + - ", converter=" + converter + - '}'; - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EntityMetadataBuilder.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EntityMetadataBuilder.java deleted file mode 100644 index 40a1859416c..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/EntityMetadataBuilder.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata; -import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; - -import static java.util.Collections.emptyMap; - -class EntityMetadataBuilder { - - private String name; - - private List fieldsName = Collections.emptyList(); - - private Class type; - - private List fields = Collections.emptyList(); - - private Map javaFieldGroupedByColumn = emptyMap(); - - private Map fieldsGroupedByName = emptyMap(); - - private InstanceSupplier instanceSupplier; - - private InheritanceMetadata inheritance; - - private boolean hasInheritanceAnnotation; - - private ConstructorMetadata constructor; - - - public EntityMetadataBuilder name(String name) { - this.name = name; - return this; - } - - public EntityMetadataBuilder fieldsName(List fieldsName) { - this.fieldsName = fieldsName; - return this; - } - - public EntityMetadataBuilder type(Class type) { - this.type = type; - return this; - } - - public EntityMetadataBuilder fields(List fields) { - this.fields = fields; - return this; - } - - public EntityMetadataBuilder javaFieldGroupedByColumn(Map javaFieldGroupedByColumn) { - this.javaFieldGroupedByColumn = javaFieldGroupedByColumn; - return this; - } - - public EntityMetadataBuilder fieldsGroupedByName(Map fieldsGroupedByName) { - this.fieldsGroupedByName = fieldsGroupedByName; - return this; - } - - public EntityMetadataBuilder instanceSupplier(InstanceSupplier instanceSupplier) { - this.instanceSupplier = instanceSupplier; - return this; - } - - public EntityMetadataBuilder inheritance(InheritanceMetadata inheritance) { - this.inheritance = inheritance; - return this; - } - - public EntityMetadataBuilder hasInheritanceAnnotation(boolean hasInheritanceAnnotation) { - this.hasInheritanceAnnotation = hasInheritanceAnnotation; - return this; - } - - public EntityMetadataBuilder constructor(ConstructorMetadata constructor) { - this.constructor = constructor; - return this; - } - - - public EntityMetadata build() { - return new DefaultEntityMetadata(name, fieldsName, type, fields, - javaFieldGroupedByColumn, fieldsGroupedByName, instanceSupplier, inheritance, - constructor, hasInheritanceAnnotation); - } -} \ No newline at end of file diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldMappingBuilder.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldMappingBuilder.java deleted file mode 100644 index 773cd126fd4..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldMappingBuilder.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.AttributeConverter; - -import java.lang.reflect.Field; - -import org.eclipse.jnosql.communication.TypeSupplier; -import org.eclipse.jnosql.mapping.metadata.ArrayFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MapFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -class FieldMappingBuilder { - - private MappingType type; - - private Field field; - - private String name; - - private String entityName; - - private TypeSupplier typeSupplier; - - private Class> converter; - - private boolean id; - - private FieldReader reader; - - private FieldWriter writer; - - private String udt; - - private Class elementType; - - - public FieldMappingBuilder type(MappingType type) { - this.type = type; - return this; - } - - public FieldMappingBuilder field(Field field) { - this.field = field; - return this; - } - - public FieldMappingBuilder name(String name) { - this.name = name; - return this; - } - - public FieldMappingBuilder typeSupplier(TypeSupplier typeSupplier) { - this.typeSupplier = typeSupplier; - return this; - } - - public FieldMappingBuilder entityName(String entityName) { - this.entityName = entityName; - return this; - } - - public FieldMappingBuilder converter(Class> converter) { - this.converter = converter; - return this; - } - - public FieldMappingBuilder id(boolean id) { - this.id = id; - return this; - } - - public FieldMappingBuilder writer(FieldWriter writer) { - this.writer = writer; - return this; - } - - public FieldMappingBuilder udt(String udt) { - this.udt = udt; - return this; - } - - public FieldMappingBuilder reader(FieldReader reader) { - this.reader = reader; - return this; - } - - public FieldMappingBuilder elementType(Class elementType) { - this.elementType = elementType; - return this; - } - - public DefaultFieldMetadata buildDefault() { - return new DefaultFieldMetadata(type, field, name, converter, id, reader, writer, udt); - } - - public CollectionFieldMetadata buildCollection() { - return new DefaultCollectionFieldMetadata(type, field, name, typeSupplier, converter, reader, writer, udt); - } - - public MapFieldMetadata buildMap() { - return new DefaultMapFieldMetadata(type, field, name, typeSupplier, converter, reader, writer, udt); - } - - public EmbeddedFieldMetadata buildEmbedded() { - return new EmbeddedFieldMetadata(type, field, name, entityName, reader, writer, udt); - } - - public ArrayFieldMetadata buildArray() { - return new DefaultArrayFieldMetadata(type, field, name, elementType, converter, reader, writer, udt); - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldReader.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldReader.java deleted file mode 100644 index 67c3f2f2aa9..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldReader.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -/** - * A piece of operations within a class. - * This class does the getter operation in a {@link java.lang.reflect.Field} in a class from a Field. - */ -public interface FieldReader { - - /** - * Reads the entity bean, it will read the respective field and return the value. - * - * @param bean the entity that has the field - * @return the field value from the entity - * @throws NullPointerException when bean is null - */ - Object read(Object bean); -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldWriter.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldWriter.java deleted file mode 100644 index 7d0475ed4d6..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/FieldWriter.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - - -/** - * A piece of operations within a class. - * This class does the setter operation in a {@link java.lang.reflect.Field} in a class from a Field. - */ -public interface FieldWriter { - - /** - * From the entity bean, it will write the respective field and return the value. - * - * @param bean the entity that has the field - * @param value the value to the field - * @throws NullPointerException when there is null parameter - */ - void write(Object bean, Object value); -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/InstanceSupplier.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/InstanceSupplier.java deleted file mode 100644 index bc73260fb9e..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/InstanceSupplier.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import java.util.function.Supplier; - -/** - * A piece of operations within a class. This class does the new instance creation. - */ -public interface InstanceSupplier extends Supplier { - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/NativeMapping.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/NativeMapping.java deleted file mode 100644 index 78443443c3c..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/NativeMapping.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; - -record NativeMapping (String nativeField, FieldMetadata fieldMetadata) { - - public static NativeMapping of(String nativeField, FieldMetadata field) { - return new NativeMapping(nativeField, field); - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ParameterMetaDataBuilder.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ParameterMetaDataBuilder.java deleted file mode 100644 index 68802352774..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ParameterMetaDataBuilder.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.Column; -import jakarta.nosql.Convert; -import jakarta.nosql.Id; - -import java.lang.reflect.Parameter; -import java.util.Objects; -import java.util.Optional; - -import org.eclipse.jnosql.mapping.metadata.MappingType; -import org.eclipse.jnosql.mapping.metadata.ParameterMetaData; - -class ParameterMetaDataBuilder { - - private final Parameter parameter; - - private ParameterMetaDataBuilder(Parameter parameter) { - this.parameter = parameter; - } - - ParameterMetaData build() { - Id id = parameter.getAnnotation(Id.class); - Column column = parameter.getAnnotation(Column.class); - Convert convert = parameter.getAnnotation(Convert.class); - Class type = parameter.getType(); - String name = Optional.ofNullable(id) - .map(Id::value) - .or(() -> Optional.ofNullable(column).map(Column::value)) - .orElse(null); - if ((Objects.isNull(name) || name.isBlank()) - && parameter.getDeclaringExecutable().getDeclaringClass().isRecord()) { - name = parameter.getName(); - } - MappingType mappingType = MappingType.of(parameter.getType()); - return switch (mappingType) { - case COLLECTION -> new DefaultCollectionParameterMetaData(name, type, - id != null, - Optional.ofNullable(convert).map(Convert::value).orElse(null), - mappingType, parameter::getParameterizedType); - case ARRAY -> new DefaultArrayParameterMetaData(name, type, - id != null, - Optional.ofNullable(convert).map(Convert::value).orElse(null), - mappingType, parameter.getType().getComponentType()); - case MAP -> new DefaultMapParameterMetaData(name, type, - id != null, - Optional.ofNullable(convert).map(Convert::value).orElse(null), - mappingType, parameter::getParameterizedType); - default -> new DefaultParameterMetaData(name, type, - id != null, - Optional.ofNullable(convert).map(Convert::value).orElse(null), - mappingType); - }; - - } - - public static ParameterMetaData of(Parameter parameter) { - ParameterMetaDataBuilder builder = new ParameterMetaDataBuilder(parameter); - return builder.build(); - } -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionClassConverter.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionClassConverter.java deleted file mode 100644 index 95fa4361aaa..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionClassConverter.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.nosql.Convert; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import org.eclipse.jnosql.mapping.metadata.ClassConverter; -import org.eclipse.jnosql.mapping.metadata.CollectionFieldMetadata; -import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.FieldMetadata; -import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; -import org.eclipse.jnosql.mapping.metadata.MappingType; - -import static java.util.Objects.nonNull; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; - -public final class ReflectionClassConverter implements ClassConverter { - - private static final Logger LOGGER = Logger.getLogger(ReflectionClassConverter.class.getName()); - - private final Reflections reflections; - private final ConstructorMetadataBuilder constructorMetadataBuilder; - - public ReflectionClassConverter() { - this.reflections = new Reflections(); - this.constructorMetadataBuilder = new ConstructorMetadataBuilder(reflections); - } - - - @Override - public EntityMetadata apply(Class entity) { - - long start = System.currentTimeMillis(); - String entityName = reflections.getEntityName(entity); - - List fields = reflections.getFields(entity) - .stream().map(this::to).collect(toList()); - - List fieldsName = fields.stream().map(FieldMetadata::name).collect(toList()); - - Map nativeFieldGroupByJavaField = - getNativeFieldGroupByJavaField(fields, "", ""); - - Map fieldsGroupedByName = fields.stream() - .collect(collectingAndThen(toMap(FieldMetadata::name, - Function.identity()), Collections::unmodifiableMap)); - - - Constructor constructor = Reflections.getConstructor(entity); - InstanceSupplier instanceSupplier = () -> Reflections.newInstance(constructor); - InheritanceMetadata inheritance = reflections.getInheritance(entity).orElse(null); - boolean hasInheritanceAnnotation = reflections.hasInheritanceAnnotation(entity); - - EntityMetadata mapping = DefaultEntityMetadata.builder().name(entityName) - .type(entity) - .fields(fields) - .fieldsName(fieldsName) - .instanceSupplier(instanceSupplier) - .javaFieldGroupedByColumn(nativeFieldGroupByJavaField) - .fieldsGroupedByName(fieldsGroupedByName) - .inheritance(inheritance) - .hasInheritanceAnnotation(hasInheritanceAnnotation) - .constructor(constructorMetadataBuilder.build(entity)) - .build(); - - long end = System.currentTimeMillis() - start; - LOGGER.finest(String.format("Scanned the entity %s loaded with time of %d ms", entity.getName(), end)); - return mapping; - } - - private Map getNativeFieldGroupByJavaField(List fields, - String javaField, String nativeField) { - - Map nativeFieldGroupByJavaField = new HashMap<>(); - - for (FieldMetadata field : fields) { - appendValue(nativeFieldGroupByJavaField, field, javaField, nativeField); - } - - return nativeFieldGroupByJavaField; - } - - private void appendValue(Map nativeFieldGroupByJavaField, FieldMetadata field, - String javaField, String nativeField) { - - - switch (field.mappingType()) { - case ENTITY -> appendFields(nativeFieldGroupByJavaField, field, javaField, - appendPreparePrefix(nativeField, field.name())); - case EMBEDDED -> appendFields(nativeFieldGroupByJavaField, field, javaField, nativeField); - case COLLECTION -> { - if (((CollectionFieldMetadata) field).isEmbeddable()) { - Class type = ((CollectionFieldMetadata) field).elementType(); - String nativeFieldAppended = appendPreparePrefix(nativeField, field.name()); - appendFields(nativeFieldGroupByJavaField, field, javaField, nativeFieldAppended, type); - return; - } - appendDefaultField(nativeFieldGroupByJavaField, field, javaField, nativeField); - } - default -> appendDefaultField(nativeFieldGroupByJavaField, field, javaField, nativeField); - } - - } - - private void appendDefaultField(Map nativeFieldGroupByJavaField, - FieldMetadata field, String javaField, String nativeField) { - - nativeFieldGroupByJavaField.put(javaField.concat(field.fieldName()), - NativeMapping.of(nativeField.concat(field.name()), field)); - } - - private void appendFields(Map nativeFieldGroupByJavaField, - FieldMetadata field, - String javaField, String nativeField) { - - Class type = field.type(); - appendFields(nativeFieldGroupByJavaField, field, javaField, nativeField, type); - } - - private void appendFields(Map nativeFieldGroupByJavaField, - FieldMetadata field, String javaField, String nativeField, - Class type) { - - Map entityMap = getNativeFieldGroupByJavaField( - reflections.getFields(type) - .stream().map(this::to).collect(toList()), - appendPreparePrefix(javaField, field.fieldName()), nativeField); - - String nativeElement = entityMap.values().stream().map(NativeMapping::nativeField) - .collect(Collectors.joining(",")); - - nativeFieldGroupByJavaField.put(appendPrefix(javaField, field.fieldName()), NativeMapping.of(nativeElement, field)); - nativeFieldGroupByJavaField.putAll(entityMap); - } - - private String appendPreparePrefix(String prefix, String field) { - return appendPrefix(prefix, field).concat("."); - } - - private String appendPrefix(String prefix, String field) { - if (prefix.isEmpty()) { - return field; - } else { - return prefix.concat(field); - } - } - - - private FieldMetadata to(Field field) { - MappingType mappingType = MappingType.of(field.getType()); - reflections.makeAccessible(field); - Convert convert = field.getAnnotation(Convert.class); - boolean id = reflections.isIdField(field); - String columnName = id ? reflections.getIdName(field) : reflections.getColumnName(field); - String udt = reflections.getUDTName(field); - FieldMappingBuilder builder = new FieldMappingBuilder().name(columnName) - .field(field).type(mappingType).id(id).udt(udt) - .reader(bean -> reflections.getValue(bean, field)) - .writer((bean, value) -> reflections.setValue(bean, field, value)); - - if (nonNull(convert)) { - builder.converter(convert.value()); - } - switch (mappingType) { - case COLLECTION -> { - builder.typeSupplier(field::getGenericType); - return builder.buildCollection(); - } - case MAP -> { - builder.typeSupplier(field::getGenericType); - return builder.buildMap(); - } - case EMBEDDED -> { - return builder.entityName(reflections.getEntityName(field.getType())).buildEmbedded(); - } - case ARRAY -> { - return builder.elementType(field.getType().getComponentType()).buildArray(); - } - default -> { - return builder.buildDefault(); - } - } - } - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java deleted file mode 100644 index df4f8215c62..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/ReflectionGroupEntityMetadata.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Maximillian Arruda - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.eclipse.jnosql.jakartapersistence.mapping.metadata.JakartaPersistenceClassScanner; -import org.eclipse.jnosql.mapping.metadata.ClassConverter; -import org.eclipse.jnosql.mapping.metadata.EntityMetadata; -import org.eclipse.jnosql.mapping.metadata.GroupEntityMetadata; - -/** - * The default implementation of {@link GroupEntityMetadata}. - * It will load all Classes and put in a {@link ConcurrentHashMap}. - * Where the key is {@link Class#getName()} and the value is {@link EntityMetadata} - * - * TODO: Replace with an impl that queries an EntityManagerFactory directly - */ -@ApplicationScoped -public class ReflectionGroupEntityMetadata implements GroupEntityMetadata { - - private final Map, EntityMetadata> classes=new ConcurrentHashMap<>(); - private final Map mappings=new ConcurrentHashMap<>(); - - @PostConstruct - public void postConstruct() { - var converter = ClassConverter.load(); - var scanner = JakartaPersistenceClassScanner.load(); - for (Class entity : scanner.entities()) { - EntityMetadata entityMetadata = converter.apply(entity); - if (entityMetadata.hasEntityName()) { - mappings.put(entityMetadata.name(), entityMetadata); - } - classes.put(entity, entityMetadata); - } - for (Class embeddable : scanner.embeddables()) { - EntityMetadata entityMetadata = converter.apply(embeddable); - classes.put(embeddable, entityMetadata); - } - } - - @Override - public Map mappings() { - return this.mappings; - } - - @Override - public Map, EntityMetadata> classes() { - return this.classes; - } - -} \ No newline at end of file diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/Reflections.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/Reflections.java deleted file mode 100644 index a8306c49b02..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/Reflections.java +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2022 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - * Maximillian Arruda - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.nosql.Column; -import jakarta.nosql.DiscriminatorColumn; -import jakarta.nosql.DiscriminatorValue; -import jakarta.nosql.Entity; -import jakarta.nosql.Id; -import jakarta.nosql.Inheritance; -import jakarta.nosql.MappedSuperclass; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Stream; - -import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata; - -import static java.util.Objects.requireNonNull; - -/** - * Utilitarian class to reflection - */ -@ApplicationScoped -public class Reflections { - - private static final Logger LOGGER = Logger.getLogger(Reflections.class.getName()); - - private static final Predicate IS_ID_ANNOTATION = Id.class.getName()::equals; - private static final Predicate IS_COLUMN_ANNOTATION = Column.class.getName()::equals; - private static final Predicate IS_NOSQL_ANNOTATION = IS_ID_ANNOTATION.or(IS_COLUMN_ANNOTATION); - - /** - * Return The Object from the Column. - * - * @param object the object - * @param field the field to return object - * @return - the field value in Object - */ - Object getValue(Object object, Field field) { - - try { - return field.get(object); - } catch (Exception exception) { - LOGGER.log(Level.FINEST, "There is an issue with returning value from this field.", exception); - } - return null; - } - - - /** - * Set the field in the Object. - * - * @param object the object - * @param field the field to return object - * @param value the value to object - * @return - if the operation was executed with success - */ - boolean setValue(Object object, Field field, Object value) { - try { - - field.set(object, value); - - } catch (Exception exception) { - LOGGER.log(Level.FINEST, "There is an issue with setting value from this field.", exception); - return false; - } - return true; - } - - /** - * Create new instance of this class. - * - * @param constructor the constructor - * @param the instance type - * @return the new instance that class - */ - public static T newInstance(Constructor constructor) { - try { - return constructor.newInstance(); - } catch (Exception exception) { - LOGGER.log(Level.FINEST, "There is an issue to creating an entity from this constructor", exception); - return null; - } - } - - - /** - * Create new instance of this class. - * - * @param type the class's type - * @param the instance type - * @return the new instance that class - */ - public static T newInstance(Class type) { - try { - Constructor constructor = getConstructor(type); - return newInstance(constructor); - } catch (Exception exception) { - LOGGER.log(Level.FINEST, "There is an issue to creating an entity from this constructor", exception); - return null; - } - } - - - /** - * Make the given field accessible, explicitly setting it accessible - * if necessary. The setAccessible(true) method is only - * called when actually necessary, to avoid unnecessary - * conflicts with a JVM SecurityManager (if active). - * - * @param field field the field to make accessible - */ - void makeAccessible(Field field) { - if ((!Modifier.isPublic(field.getModifiers()) || !Modifier - .isPublic(field.getDeclaringClass().getModifiers())) - && !field.isAccessible()) { - field.setAccessible(true); - } - } - - /** - * Make the given a constructor class accessible, explicitly setting it accessible - * if necessary. The setAccessible(true) method is only - * called when actually necessary, to avoid unnecessary - * conflicts with a JVM SecurityManager (if active). - * - * @param type the class constructor accessible - * @param the entity type - * @return the constructor class - * @throws ConstructorException when the constructor has public and default - */ - public static Constructor getConstructor(Class type) { - - final Predicate> defaultConstructorPredicate = c -> c.getParameterCount() == 0; - final Predicate> customConstructorPredicate = c -> { - for (Parameter parameter : c.getParameters()) { - if (hasNoSQLAnnotation(parameter)) { - return true; - } - } - return false; - }; - - List> constructors = Stream. - of(type.getDeclaredConstructors()) - .filter(defaultConstructorPredicate.or(customConstructorPredicate)) - .toList(); - - if (constructors.isEmpty()) { - throw new ConstructorException(type); - } - - Optional> publicConstructor = constructors - .stream() - .sorted(ConstructorComparable.INSTANCE) - .filter(c -> Modifier.isPublic(c.getModifiers())) - .findFirst(); - if (publicConstructor.isPresent()) { - return (Constructor) publicConstructor.get(); - } - - Constructor constructor = constructors.get(0); - constructor.setAccessible(true); - return (Constructor) constructor; - } - - /** - * Checks if the {@link Parameter} instance is annotated with - * Jakarta NoSQL annotations (@{@link Id} or @{@link Column}). - * - * @param parameter the parameter - * @return if the provided {@link Parameter} instance is annotated with - * Jakarta NoSQL annotations (@{@link Id} or @{@link Column}). - */ - static boolean hasNoSQLAnnotation(Parameter parameter) { - return parameter != null && Arrays.stream(parameter.getAnnotations()) - .map(Annotation::annotationType) - .map(Class::getName) - .anyMatch(IS_NOSQL_ANNOTATION); - } - - /** - * Returns the name of the entity. So it tries to read the {@link Entity} otherwise - * {@link Class#getSimpleName()} - * - * @param entity the class to read - * @return the {@link Entity} when is not blank otherwise {@link Class#getSimpleName()} - * @throws NullPointerException when entity is null - */ - String getEntityName(Class entity) { - requireNonNull(entity, "class entity is required"); - - if (isInheritance(entity)) { - return readEntity(entity.getSuperclass()); - } - return readEntity(entity); - } - - /** - * Returns the fields from the entity class - * - * @param type the entity class - * @return the list of fields that is annotated with either {@link Column} or - * {@link Id} - * @throws NullPointerException when class entity is null - */ - List getFields(Class type) { - requireNonNull(type, "class entity is required"); - - List fields = new ArrayList<>(); - - if (isMappedSuperclass(type)) { - fields.addAll(getFields(type.getSuperclass())); - } - Predicate hasColumnAnnotation = f -> f.getAnnotation(Column.class) != null; - Predicate hasIdAnnotation = f -> f.getAnnotation(Id.class) != null; - - Stream.of(type.getDeclaredFields()) - .filter(hasColumnAnnotation.or(hasIdAnnotation)) - .forEach(fields::add); - return fields; - } - - /** - * Checks if the class is annotated with {@link MappedSuperclass} or - * {@link Inheritance} - * - * @param type the entity class - * @return if the class is annotated - * @throws NullPointerException when type is null - */ - boolean isMappedSuperclass(Class type) { - requireNonNull(type, "class entity is required"); - Class superclass = type.getSuperclass(); - return superclass.getAnnotation(MappedSuperclass.class) != null - || superclass.getAnnotation(Inheritance.class) != null; - } - - /** - * Checks if the field is annotated with {@link Column} - * - * @param field the field - * @return if the field is annotated with {@link Column} - * @throws NullPointerException when the field is null - */ - boolean isIdField(Field field) { - requireNonNull(field, "field is required"); - return field.getAnnotation(Id.class) != null; - } - - /** - * Gets the name from the field, so it reads the {@link Column#value()} - * otherwise {@link Field#getName()} - * - * @param field the fields - * @return the column name - * @throws NullPointerException when the field is null - */ - String getColumnName(Field field) { - requireNonNull(field, "field is required"); - return Optional.ofNullable(field.getAnnotation(Column.class)) - .map(Column::value) - .filter(StringUtils::isNotBlank) - .orElse(field.getName()); - } - - /** - * Gets the id name, so it reads the {@link Id#value()} otherwise {@link Field#getName()} - * - * @param field the field - * @return the column name - * @throws NullPointerException when the field is null - */ - String getIdName(Field field) { - requireNonNull(field, "field is required"); - return Optional.ofNullable(field.getAnnotation(Id.class)) - .map(Id::value) - .filter(StringUtils::isNotBlank) - .orElse(field.getName()); - } - - /** - * Reads the type annotation and checks if the inheritance has an - * {@link Inheritance} annotation. - * If it has, it will return the {@link InheritanceMetadata} otherwise it will return - * {@link Optional#empty()} - * - * @param type the type class - * @return the {@link InheritanceMetadata} or {@link Optional#empty()} - * @throws NullPointerException when type is null - */ - Optional getInheritance(Class type) { - requireNonNull(type, "entity is required"); - if (isInheritance(type)) { - Class parent = type.getSuperclass(); - String discriminatorColumn = getDiscriminatorColumn(parent); - String discriminatorValue = getDiscriminatorValue(type); - return Optional.of(new InheritanceMetadata(discriminatorValue, discriminatorColumn, - parent, type)); - } else if (type.getAnnotation(Inheritance.class) != null) { - String discriminatorColumn = getDiscriminatorColumn(type); - String discriminatorValue = getDiscriminatorValue(type); - return Optional.of(new InheritanceMetadata(discriminatorValue, discriminatorColumn, - type, type)); - } - return Optional.empty(); - } - - /** - * Check if the entity has the {@link Inheritance} annotation - * - * @param entity the entity - * @return true if it has the {@link Inheritance} annotation - */ - boolean hasInheritanceAnnotation(Class entity) { - requireNonNull(entity, "entity is required"); - return entity.getAnnotation(Inheritance.class) != null; - } - - /** - * Retrieves the User-Defined Type (UDT) name associated with the given field. - * - *

- * This method retrieves the UDT name specified in the {@link Column} annotation of the provided field. - * If the field is not annotated with {@link Column}, or if the UDT name is blank or not specified, - * this method returns {@code null}. - *

- * - * @param field the field from which to retrieve the UDT name - * @return the UDT name specified in the {@link Column} annotation of the field, or {@code null} if not specified - * @throws NullPointerException if the field is null - */ - public String getUDTName(Field field) { - requireNonNull(field, "field is required"); - return Optional.ofNullable(field.getAnnotation(Column.class)) - .map(Column::udt) - .filter(StringUtils::isNotBlank) - .orElse(null); - } - - /** - * Attempts to locate the specific generic declaration of the desired type, - * walking the interface and superclass hierarchy to locate it. - * - * @param type the type to scan, such as a field's generic type - * @param parentType the type to search for, such as {@code Map} - * @return an {@link Optional} describing the found declaration, or an - * empty one if it cannot be found - * @since 1.1.5 - */ - public static Optional findParameterizedType(Type type, Class parentType) { - if(type instanceof ParameterizedType parameterizedType && parameterizedType.getRawType() instanceof Class rawClass) { - if(parentType.isAssignableFrom(rawClass)) { - return Optional.of(parameterizedType); - } - } - if(type instanceof Class classType) { - Type superType = classType.getGenericSuperclass(); - if(superType != null) { - Optional superResult = findParameterizedType(superType, parentType); - if(superResult.isPresent()) { - return superResult; - } - } - for(Type superInterface : classType.getGenericInterfaces()) { - Optional superResult = findParameterizedType(superInterface, parentType); - if(superResult.isPresent()) { - return superResult; - } - } - } - - return Optional.empty(); - } - - - private String getDiscriminatorColumn(Class parent) { - return Optional - .ofNullable(parent.getAnnotation(DiscriminatorColumn.class)) - .map(DiscriminatorColumn::value) - .orElse(DiscriminatorColumn.DEFAULT_DISCRIMINATOR_COLUMN); - } - - private String getDiscriminatorValue(Class entity) { - return Optional - .ofNullable(entity.getAnnotation(DiscriminatorValue.class)) - .map(DiscriminatorValue::value) - .orElse(entity.getSimpleName()); - } - - private String readEntity(Class entity) { - return Optional.ofNullable(entity.getAnnotation(Entity.class)) - .map(Entity::value) - .filter(StringUtils::isNotBlank) - .orElse(entity.getSimpleName()); - } - - private boolean isInheritance(Class entity) { - Class superclass = entity.getSuperclass(); - return superclass.getAnnotation(Inheritance.class) != null; - } - - -} diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/StringUtils.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/StringUtils.java deleted file mode 100644 index 1eff957bfb6..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/reflection/nosql/StringUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Apache License v2.0 which accompanies this distribution. - * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html - * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. - * - * You may elect to redistribute this code under either of these licenses. - * - * Contributors: - * - * Otavio Santana - * Maximillian Arruda - */ -package org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql; - -/** - * Utility class providing operations for working with strings and character sequences. - * This class contains methods to check for blankness (presence of whitespace or being null) - * and to perform various string-related operations. - */ -final class StringUtils { - - private StringUtils() { - // Private constructor to prevent instantiation of the utility class. - } - - /** - * Checks if the given character sequence is blank, which means it is either null or - * consists only of whitespace characters. - * - * @param cs The character sequence to be checked for blankness. - * @return {@code true} if the character sequence is blank, otherwise {@code false}. - */ - public static boolean isBlank(final CharSequence cs) { - if (cs == null || cs.isEmpty()) { - return true; - } - - for (int i = 0; i < cs.length(); i++) { - if (!Character.isWhitespace(cs.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Checks if the given character sequence is not blank, which means it is not null and - * contains at least one non-whitespace character. - * - * @param cs The character sequence to be checked for non-blankness. - * @return {@code true} if the character sequence is not blank, otherwise {@code false}. - */ - public static boolean isNotBlank(final CharSequence cs) { - return !isBlank(cs); - } -} - diff --git a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassConverter b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassConverter deleted file mode 100644 index 960c777c47c..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.ClassConverter +++ /dev/null @@ -1,2 +0,0 @@ -# This is needed only for reflection classes. Should be removed once they are replaced by GlassFish-specific solution -org.glassfish.main.jnosql.jakartapersistence.mapping.reflection.nosql.ReflectionClassConverter diff --git a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.CollectionSupplier b/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.CollectionSupplier deleted file mode 100644 index 5727dd8db80..00000000000 --- a/appserver/persistence/jnosql-integration/src/main/resources/META-INF/services/org.eclipse.jnosql.mapping.metadata.CollectionSupplier +++ /dev/null @@ -1,5 +0,0 @@ -# This is needed only for reflection classes. Should be removed once they are replaced by GlassFish-specific solution -org.eclipse.jnosql.mapping.reflection.collection.DequeSupplier -org.eclipse.jnosql.mapping.reflection.collection.ListSupplier -org.eclipse.jnosql.mapping.reflection.collection.SetSupplier -org.eclipse.jnosql.mapping.reflection.collection.TreeSetSupplier \ No newline at end of file From 2cd5aa59aff69add2435af0f00c5b7f8d2630d25 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Sat, 6 Sep 2025 11:49:58 +0200 Subject: [PATCH 3/5] Jakarta Data integration - Test case for @Transactional Implemented by changes in JNoSQL JPA driver to trigger CDI interceptors --- appserver/pom.xml | 7 ++ appserver/tests/application/pom.xml | 59 +--------- .../test/app/data/TransactionApplication.java | 30 +++++ .../main/test/app/data/TransactionEntity.java | 55 +++++++++ .../test/app/data/TransactionRepository.java | 29 +++++ .../test/app/data/TransactionResource.java | 36 ++++++ .../test/app/data/TransactionService.java | 45 +++++++ .../main/test/app/helpers/JakartaEE.java | 40 +++++++ .../main/test/app/data/persistence.xml | 29 +++++ .../app/data/TransactionalAnnotationTest.java | 111 ++++++++++++++++++ 10 files changed, 384 insertions(+), 57 deletions(-) create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionApplication.java create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionEntity.java create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionRepository.java create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionResource.java create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionService.java create mode 100644 appserver/tests/application/src/main/java/org/glassfish/main/test/app/helpers/JakartaEE.java create mode 100644 appserver/tests/application/src/main/resources/org/glassfish/main/test/app/data/persistence.xml create mode 100644 appserver/tests/application/src/test/java/org/glassfish/main/test/app/data/TransactionalAnnotationTest.java diff --git a/appserver/pom.xml b/appserver/pom.xml index 80ecb60d30d..4b68688df47 100644 --- a/appserver/pom.xml +++ b/appserver/pom.xml @@ -81,6 +81,7 @@ 11 + 11.0.0 @@ -210,6 +211,12 @@ + + jakarta.platform + jakarta.jakartaee-api + ${jakarta.platform.version} + + jakarta.faces diff --git a/appserver/tests/application/pom.xml b/appserver/tests/application/pom.xml index dc34b036015..0a6e776fb4d 100755 --- a/appserver/tests/application/pom.xml +++ b/appserver/tests/application/pom.xml @@ -68,53 +68,8 @@ - jakarta.ejb - jakarta.ejb-api - provided - - - jakarta.annotation - jakarta.annotation-api - provided - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - jakarta.enterprise.concurrent - jakarta.enterprise.concurrent-api - provided - - - jakarta.servlet.jsp - jakarta.servlet.jsp-api - provided - - - jakarta.servlet - jakarta.servlet-api - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - provided - - - jakarta.persistence - jakarta.persistence-api - provided - - - jakarta.authentication - jakarta.authentication-api - provided - - - jakarta.security.enterprise - jakarta.security.enterprise-api + jakarta.platform + jakarta.jakartaee-api provided @@ -122,16 +77,6 @@ jakarta.xml.ws-api provided - - jakarta.websocket - jakarta.websocket-api - provided - - - jakarta.websocket - jakarta.websocket-client-api - provided - jakarta.jws diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionApplication.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionApplication.java new file mode 100644 index 00000000000..4628a3c0cc0 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionApplication.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.main.test.app.data; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +import java.util.Set; + +@ApplicationPath("") +public class TransactionApplication extends Application { + @Override + public Set> getClasses() { + return Set.of(TransactionResource.class); + } +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionEntity.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionEntity.java new file mode 100644 index 00000000000..a31018a5fe3 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionEntity.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.main.test.app.data; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.PostPersist; +import jakarta.persistence.Transient; +import jakarta.transaction.TransactionSynchronizationRegistry; + +import org.glassfish.main.test.app.helpers.JakartaEE; + +@Entity +public class TransactionEntity { + @Id + private Long id; + @Transient + private String transactionKey; + + public TransactionEntity() { + setCurrentTransactionKey(); + } + + public TransactionEntity(Long id) { + this.id = id; + setCurrentTransactionKey(); + } + + @PostPersist + public void setCurrentTransactionKey() { + try { + TransactionSynchronizationRegistry registry = JakartaEE.getDefaultTransactionSynchronizationRegistry(); + this.transactionKey = String.valueOf(registry.getTransactionKey()); + } catch (Exception e) { + } + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public String getTransactionKey() { return transactionKey; } +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionRepository.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionRepository.java new file mode 100644 index 00000000000..41bfdaae407 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionRepository.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.main.test.app.data; + +import jakarta.data.repository.CrudRepository; +import jakarta.data.repository.Repository; +import jakarta.data.repository.Save; +import jakarta.transaction.Transactional; + +@Repository +@Transactional(Transactional.TxType.REQUIRES_NEW) +public interface TransactionRepository extends CrudRepository { + @Save + TransactionEntity save(TransactionEntity entity); +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionResource.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionResource.java new file mode 100644 index 00000000000..ba6f243cc89 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionResource.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.main.test.app.data; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +@Path("/transaction") +public class TransactionResource { + + @Inject + private TransactionService service; + + @GET + public String testTransaction() { + try { + return service.processTransaction(); + } catch (Exception e) { + throw e; + } + } +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionService.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionService.java new file mode 100644 index 00000000000..7e1da180524 --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/data/TransactionService.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.main.test.app.data; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.TransactionSynchronizationRegistry; +import jakarta.transaction.Transactional; + +import org.glassfish.main.test.app.helpers.JakartaEE; + + + +@ApplicationScoped +@Transactional +public class TransactionService { + + @Inject + private TransactionRepository repository; + + public String processTransaction() { + String serviceTransactionKey; + TransactionSynchronizationRegistry registry = JakartaEE.getDefaultTransactionSynchronizationRegistry(); + serviceTransactionKey = String.valueOf(registry.getTransactionKey()); + + TransactionEntity entity = repository.save(new TransactionEntity(1L)); + return serviceTransactionKey + SEPARATOR + entity.getTransactionKey(); + } + public static final String SEPARATOR = "#####"; + +} diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/helpers/JakartaEE.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/helpers/JakartaEE.java new file mode 100644 index 00000000000..12cee21f64e --- /dev/null +++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/helpers/JakartaEE.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.main.test.app.helpers; + +import jakarta.transaction.TransactionSynchronizationRegistry; + +import javax.naming.InitialContext; +import javax.naming.NamingException; + +/** + * + * @author Ondro Mihalyi + */ +public class JakartaEE { + + private JakartaEE() { + } + + public static TransactionSynchronizationRegistry getDefaultTransactionSynchronizationRegistry() { + try { + return (TransactionSynchronizationRegistry) new InitialContext().lookup("java:comp/TransactionSynchronizationRegistry"); + } catch (NamingException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/appserver/tests/application/src/main/resources/org/glassfish/main/test/app/data/persistence.xml b/appserver/tests/application/src/main/resources/org/glassfish/main/test/app/data/persistence.xml new file mode 100644 index 00000000000..cd62d0a55fe --- /dev/null +++ b/appserver/tests/application/src/main/resources/org/glassfish/main/test/app/data/persistence.xml @@ -0,0 +1,29 @@ + + + + + org.glassfish.main.test.app.data.TransactionEntity + + + + + diff --git a/appserver/tests/application/src/test/java/org/glassfish/main/test/app/data/TransactionalAnnotationTest.java b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/data/TransactionalAnnotationTest.java new file mode 100644 index 00000000000..156ede03444 --- /dev/null +++ b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/data/TransactionalAnnotationTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.main.test.app.data; + +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; + +import org.glassfish.common.util.HttpParser; +import org.glassfish.main.itest.tools.GlassFishTestEnvironment; +import org.glassfish.main.itest.tools.asadmin.Asadmin; +import org.glassfish.main.itest.tools.asadmin.AsadminResult; +import org.glassfish.main.itest.tools.asadmin.DomainPropertiesBackup; +import org.glassfish.main.test.app.helpers.JakartaEE; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.exporter.ZipExporter; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static java.lang.System.Logger.Level.INFO; +import static org.glassfish.main.itest.tools.GlassFishTestEnvironment.openConnection; +import static org.glassfish.main.itest.tools.asadmin.AsadminResultMatcher.asadminOK; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class TransactionalAnnotationTest { + + private static final System.Logger LOG = System.getLogger(TransactionalAnnotationTest.class.getName()); + private static final String WEBAPP_NAME = "transactionApp"; + private static final String WEBAPP_WAR = "transactionApp.war"; + private static final Asadmin ASADMIN = GlassFishTestEnvironment.getAsadmin(); + private static final DomainPropertiesBackup DERBYPOOL_BACKUP = DomainPropertiesBackup.backupDerbyPool(); + + @TempDir + private static File webAppDir; + + @BeforeAll + public static void deployAll() throws IOException { + GlassFishTestEnvironment.switchDerbyPoolToEmbededded(); + File webApp = createWebApp(); + AsadminResult result = ASADMIN.exec("deploy", "--contextroot", "/" + WEBAPP_NAME, "--name", WEBAPP_NAME, webApp.getAbsolutePath()); + assertThat(result, asadminOK()); + } + + @AfterAll + public static void undeployAll() { + assertThat(ASADMIN.exec("undeploy", WEBAPP_NAME), asadminOK()); + DERBYPOOL_BACKUP.restore(); + } + + @Test + public void testTransactionalRequiresNew() throws IOException { + String response = getResponse(WEBAPP_NAME, "transaction"); + String[] transactionIds = response.split(TransactionService.SEPARATOR); + + assertNotEquals(transactionIds[0], transactionIds[1], + "Transaction IDs should be different due to REQUIRES_NEW"); + } + + private String getResponse(String contextRoot, String endpoint) throws IOException { + HttpURLConnection connection = openConnection(8080, "/" + contextRoot + "/" + endpoint); + connection.setRequestMethod("GET"); + try { + int responseCode = connection.getResponseCode(); + String reason = ""; + if (responseCode != 200) { + String errorResponse = HttpParser.readResponseErrorStream(connection); + reason = ("Received response code " + responseCode + " with an error: " + errorResponse); + } + assertThat(reason, responseCode, equalTo(200)); + return HttpParser.readResponseInputStream(connection); + } finally { + connection.disconnect(); + } + } + + private static File createWebApp() { + WebArchive webArchive = ShrinkWrap.create(WebArchive.class) + .addClass(TransactionApplication.class) + .addClass(TransactionResource.class) + .addClass(TransactionService.class) + .addClass(TransactionRepository.class) + .addClass(TransactionEntity.class) + .addPackage(JakartaEE.class.getPackage()) + .addAsResource(TransactionalAnnotationTest.class.getPackage(), "persistence.xml", "META-INF/persistence.xml"); + + LOG.log(INFO, webArchive.toString(true)); + + File webApp = new File(webAppDir, WEBAPP_WAR); + webArchive.as(ZipExporter.class).exportTo(webApp, true); + return webApp; + } +} From 0111ee3b5860cf2e10b27942c0c692b3fce43462 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Sat, 6 Sep 2025 20:10:05 +0200 Subject: [PATCH 4/5] Jakarta Data integration - Document Jakarta Data in GlassFish app dev guide --- appserver/pom.xml | 2 + .../src/main/asciidoc/jakarta-data.adoc | 762 ++++++++++++++++++ .../src/main/asciidoc/jpa.adoc | 2 +- .../src/main/asciidoc/lot.adoc | 30 +- .../src/main/asciidoc/webapps.adoc | 2 +- docs/parent/pom.xml | 5 + 6 files changed, 786 insertions(+), 17 deletions(-) create mode 100644 docs/application-development-guide/src/main/asciidoc/jakarta-data.adoc diff --git a/appserver/pom.xml b/appserver/pom.xml index 4b68688df47..73747323f7f 100644 --- a/appserver/pom.xml +++ b/appserver/pom.xml @@ -116,7 +116,9 @@ 1.0.1 + 1.0 1.0.1 + 1.0.1 1.1.11-SNAPSHOT diff --git a/docs/application-development-guide/src/main/asciidoc/jakarta-data.adoc b/docs/application-development-guide/src/main/asciidoc/jakarta-data.adoc new file mode 100644 index 00000000000..bcdf587ef84 --- /dev/null +++ b/docs/application-development-guide/src/main/asciidoc/jakarta-data.adoc @@ -0,0 +1,762 @@ +type=page +status=published +title=Using Jakarta Data Repositories +next=webapps.html +prev=jpa.html +~~~~~~ + += Using Jakarta Data Repositories + +[[using-jakarta-data-repositories]] +== Using Jakarta Data Repositories + +This chapter describes how to use Jakarta Data repositories in {productName} applications. Jakarta Data provides a standard API for data access that simplifies database operations through repository interfaces and automatic query generation. + +The following topics are addressed here: + +* xref:#overview-of-jakarta-data[Overview of Jakarta Data] +* xref:#defining-repository-interfaces[Defining Repository Interfaces] +* xref:#query-methods[Query Methods] +* xref:#custom-queries[Custom Queries] +* xref:#pagination-and-sorting[Pagination and Sorting] +* xref:#transaction-management[Transaction Management] +* xref:#jakarta-validation-support[Jakarta Validation Support] +* xref:#configuring-jakarta-data-repositories[Configuring Jakarta Data Repositories] +* xref:#integration-with-jpa[Integration with JPA] + +For more information about Jakarta Data {jakarta-data-api-version}, see the official https://jakarta.ee/specifications/data/{jakarta-data-spec-version}[Jakarta Data {jakarta-data-api-version} documentation]. + +[[overview-of-jakarta-data]] + +=== Overview of Jakarta Data + +Jakarta Data is a specification that provides a standard API for data access in Jakarta EE applications. It offers a repository-based programming model that reduces boilerplate code and provides type-safe database operations. + +Key features of Jakarta Data include: + +* Repository interfaces with automatic implementation generation +* Query derivation from method names +* Support for custom queries using JDQL or JPQL +* Built-in pagination and sorting capabilities +* Integration with Jakarta Persistence (JPA) +* Type-safe query building + +Jakarta Data repositories work by defining interfaces that may extend base repository types. The Jakarta Data provider automatically generates implementations of these interfaces at build time or runtime. + +[[defining-repository-interfaces]] + +=== Defining Repository Interfaces + +Jakarta Data repositories are defined as interfaces annotated with `@Repository` annotation (`@jakarta.data.Repository`). The interface may extend one of the base repository interfaces, which provide some ready-to-use methods: + +* `Repository` - Basic repository interface +* `CrudRepository` - Adds CRUD operations +* `PageableRepository` - Adds pagination support + + +==== Basic Repository Example + +This example shows a simple repository interface that extends `CrudRepository` for a `Product` entity. It contains methods defined in `CrudRepository` as well as custom query methods using annotations and parameters. + +[source,java] +---- +import jakarta.data.repository.CrudRepository; +import jakarta.data.repository.Repository; +import jakarta.data.repository.Find; +import jakarta.data.repository.By; +import jakarta.data.repository.OrderBy; + +@Repository +public interface ProductRepository extends CrudRepository { + + // Parameter-based queries using @Find and @By annotations + @Find + List findProducts(@By("name") String name); + + @Query("WHERE price BETWEEN :minPrice AND :maxPrice") + List findProductsByPriceRange(BigDecimal minPrice, BigDecimal maxPrice); + + @Find + Optional findProduct(@By("code") String code); + + @Find + @OrderBy("price") + List findProducts(@By("category") String category); +} +---- + +==== Alternative: Method Name-Based Queries (Deprecated) + +{productName} also supports method name-based query derivation, but this approach is deprecated and might be removed in future versions. Use the annotated approach shown above instead. + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + // Method names are automatically converted to queries (DEPRECATED) + List findByName(String name); + + List findByPriceBetween(BigDecimal minPrice, BigDecimal maxPrice); + + Optional findByCode(String code); + + List findByCategoryOrderByPriceAsc(String category); +} +---- + +==== Entity Definition + +Your entity classes should be standard JPA entities: + +[source,java] +---- +import jakarta.persistence.*; + +@Entity +@Table(name = "products") +public class Product { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String code; + + private String name; + private String category; + private BigDecimal price; + + // Constructors, getters, and setters +} +---- + +[[query-methods]] + +=== Query Methods + +Jakarta Data supports automatic query generation using annotated methods with the `@Find`, `@Count`, `@Exists`, and `@Delete` annotations combined with parameter annotations like `@By`. + +==== Supported Query Annotations + +* `@Find` - Find operations +* `@Count` - Count operations +* `@Exists` - Existence checks +* `@Delete` - Delete operations +* `@Insert` - Insert operations +* `@Update` - Update operations +* `@Save` - Save operations (insert or update) + +==== Parameter Annotations + +* `@By("propertyName")` - Query by property. Specifies the entity property to query by, which can be nested to specify properties of referenced entities (e.g., `@By("customer.address.city")`). If the application is compiled with preserving parameter names in the bytecode (e.g., with `javac -parameters`), `@By` is optional and if not present, the property name will be derived from the parameter name. + +==== Examples + +[source,java] +---- +import jakarta.data.repository.*; + +@Repository +public interface CustomerRepository extends CrudRepository { + + // Find by single property + @Find + List findCustomers(@By("lastName") String lastName); + + // Multiple conditions with And (multiple @By parameters) + @Find + List findCustomers(@By("firstName") String firstName, @By("lastName") String lastName); + + // Range queries using @Query with JDQL + @Query("WHERE age BETWEEN :minAge AND :maxAge") + List findCustomersByAgeRange(int minAge, int maxAge); + + // Comparison operators using @Query with JDQL + @Query("WHERE age > :age") + List findCustomersOlderThan(int age); + + // Pattern matching using @Query with JDQL + @Query("WHERE email LIKE :pattern") + List findCustomersByEmailPattern(String pattern); + + // Collection operations using @Query with JDQL + @Query("WHERE status IN :statuses") + List findCustomersByStatuses(Collection statuses); + + // Null checks using default methods + @Find + List findCustomers(@By("middleName") String middleName); + + default List findCustomersWithNullMiddleName() { + return findCustomers((String) null); + } + + // Counting + @Count + long countCustomers(@By("status") String status); + + // Existence checks + @Exists + boolean customerExists(@By("email") String email); + + // Delete operations + @Delete + void deleteCustomers(@By("status") String status); + + // Insert operations + @Insert + Customer insertCustomer(Customer customer); + + @Insert + List insertCustomers(List customers); + + // Update operations + @Update + Customer updateCustomer(Customer customer); + + @Update + List updateCustomers(List customers); + + // Save operations (insert or update) + @Save + Customer saveCustomer(Customer customer); + + @Save + List saveCustomers(List customers); +} +---- + +==== Alternative: Method Name-Based Queries (Deprecated) + +{productName} also supports method name-based query derivation using a standardized naming convention, but this approach may be removed in future versions. Use the annotated approach shown above instead. + +===== Supported Keywords + +* `findBy`, `getBy`, `queryBy`, `readBy` - Find operations +* `countBy` - Count operations +* `existsBy` - Existence checks +* `deleteBy`, `removeBy` - Delete operations + +===== Property Expressions + +* `And`, `Or` - Logical operators +* `Between` - Range queries +* `LessThan`, `GreaterThan` - Comparison operators +* `Like`, `NotLike` - Pattern matching +* `In`, `NotIn` - Collection membership +* `IsNull`, `IsNotNull` - Null checks +* `True`, `False` - Boolean values + +===== Examples + +[source,java] +---- +public interface CustomerRepository extends CrudRepository { + + // Find by single property + List findByLastName(String lastName); + + // Multiple conditions with And + List findByFirstNameAndLastName(String firstName, String lastName); + + // Or conditions + List findByFirstNameOrLastName(String name); + + // Comparison operators + List findByAgeGreaterThan(int age); + List findByAgeBetween(int minAge, int maxAge); + + // Pattern matching + List findByEmailLike(String pattern); + + // Collection operations + List findByStatusIn(Collection statuses); + + // Null checks + List findByMiddleNameIsNull(); + + // Counting + long countByStatus(String status); + + // Existence checks + boolean existsByEmail(String email); + + // Delete operations + void deleteByStatus(String status); +} +---- + +[[custom-queries]] + +=== Custom Queries + +For complex queries that cannot be expressed through method names, Jakarta Data supports custom queries using the `@Query` annotation. Jakarta Data specifies its own query language called JDQL (Jakarta Data Query Language), which is similar to JPQL (Java Persistence Query Language). {productName} also supports full JPQL queries. + +Examples: + +[source,java] +---- +import jakarta.data.repository.Query; + +@Repository +public interface OrderRepository extends CrudRepository { + + /* A JPQL query that selects orders by customer ID and status. JPQL allows omitting + * the "SELECT o FROM Order o" part and by default operates on the entity returned + * by the mothod (Order in this case). + */ + @Query("WHERE customer.id = :customerId AND status = :status") + List findOrdersByCustomerAndStatus(Long customerId, String status); + + /* A JPQL query that selects orders containing products from a specific category. + * JPQL requires the full "SELECT o FROM Order o" syntax. + */ + @Query("SELECT o FROM Order o JOIN o.items i WHERE i.product.category = :category") + List findOrdersWithProductCategory(String category); + + /* A JPQL query that counts orders placed since a specific date. + */ + @Query("SELECT COUNT(o) FROM Order o WHERE o.orderDate >= :startDate") + long countOrdersSince(LocalDate startDate); +} +---- + +[[pagination-and-sorting]] + +=== Pagination and Sorting + +Jakarta Data provides built-in support for pagination and sorting through the `Pageable` and `Sort` interfaces. + +==== Using Pageable + +[source,java] +---- +import jakarta.data.repository.Pageable; +import jakarta.data.repository.Page; +import jakarta.data.repository.Sort; +import jakarta.data.repository.Find; +import jakarta.data.repository.By; + +@Repository +public interface ProductRepository extends PageableRepository { + + @Find + Page findProducts(@By("category") String category, Pageable pageable); + + @Query("WHERE price > :price") + List findProductsAbovePrice(BigDecimal price, Sort sort); +} +---- + +==== Usage Example + +[source,java] +---- +@Inject +private ProductRepository productRepository; + +public void demonstratePagination() { + // Create pageable request for page 0, size 10, sorted by name + Pageable pageable = Pageable.of(0, 10, Sort.by("name").ascending()); + + Page page = productRepository.findProducts("Electronics", pageable); + + List products = page.getContent(); + long totalElements = page.getTotalElements(); + int totalPages = page.getTotalPages(); + boolean hasNext = page.hasNext(); +} +---- + +[[transaction-management]] + +=== Transaction Management + +Jakarta Data repositories integrate with Jakarta EE transaction management. Repository methods automatically participate in existing transactions or create new ones as needed. + +==== Declarative Transactions + +[source,java] +---- +import jakarta.ejb.Stateless; +import jakarta.transaction.Transactional; + +@ApplicationScoped +public class OrderService { + + @Inject + private OrderRepository orderRepository; + + @Inject + private ProductRepository productRepository; + + @Transactional + public Order createOrder(OrderRequest request) { + // All repository operations participate in the same transaction + Product product = productRepository.findById(request.getProductId()) + .orElseThrow(() -> new IllegalArgumentException("Product not found")); + + Order order = new Order(); + order.setProduct(product); + order.setQuantity(request.getQuantity()); + order.setCustomerId(request.getCustomerId()); + + return orderRepository.save(order); + } +} +---- + +==== Custom Transaction Behavior + +[source,java] +---- +@Repository +public interface AuditRepository extends CrudRepository { + + @Transactional(Transactional.TxType.REQUIRES_NEW) + AuditLog save(AuditLog auditLog); +} +---- + +By default, repository methods use `REQUIRED` transaction type, which means they will join an existing transaction or create a new one if none exists. You can override this behavior using the `@Transactional` annotation on repository methods. + +The @Transactional annotation can be applied to the repository interface or individual methods to specify custom transaction behavior. + +[[jakarta-validation-support]] + +=== Jakarta Validation Support + +Jakarta Data repositories integrate with Jakarta Validation to validate method parameters and return values. To trigger validation, repository method parameters need to be annotated with validation annotations. + +==== Parameter Validation + +For simple field validation, use annotations like `@Max`, `@Min`, `@NotNull` directly on parameters: + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + @Find + List findProducts(@By("price") @Max(1000) @Min(0) BigDecimal maxPrice); + + @Find + List findProducts(@By("category") @NotBlank String category); +} +---- + +For entities that contain validation annotations on their fields, use `@Valid` on the parameter: + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + @Insert + Product insertProduct(@Valid Product product); + + @Update + Product updateProduct(@Valid Product product); + + @Save + Product saveProduct(@Valid Product product); + + @Insert + List insertProducts(@Valid List products); +} +---- + +==== Entity Validation Annotations + +Define validation rules on your entity fields: + +[source,java] +---- +@Entity +@Table(name = "products") +public class Product { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank(message = "Product code is required") + @Size(max = 20, message = "Product code must not exceed 20 characters") + private String code; + + @NotBlank(message = "Product name is required") + @Size(max = 100, message = "Product name must not exceed 100 characters") + private String name; + + @NotNull(message = "Price is required") + @DecimalMin(value = "0.0", inclusive = false, message = "Price must be greater than 0") + private BigDecimal price; + + @Min(value = 0, message = "Stock quantity cannot be negative") + private Integer stockQuantity; + + // Constructors, getters, and setters +} +---- + +==== Method Return Value Validation + +Validation annotations can also be applied to methods to validate return values: + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + @Find + @NotNull + Optional findProduct(@By("code") String code); + + @Find + @Size(min = 1, message = "At least one product must be found") + List findProducts(@By("category") String category); +} +---- + +==== Handling Validation Errors + +Validation errors are thrown as `ConstraintViolationException`: + +[source,java] +---- +@ApplicationScoped +public class ProductService { + + @Inject + private ProductRepository productRepository; + + public Product createProduct(Product product) { + try { + return productRepository.insertProduct(product); + } catch (ConstraintViolationException e) { + Set> violations = e.getConstraintViolations(); + for (ConstraintViolation violation : violations) { + String property = violation.getPropertyPath().toString(); + String message = violation.getMessage(); + System.err.println("Validation error on " + property + ": " + message); + } + throw e; + } + } +} +---- + +[[configuring-jakarta-data-repositories]] + +=== Configuring Jakarta Data Repositories + +To use Jakarta Data repositories in your {productName} application, you need to: + +1. Add the Jakarta Data API or Jakarta EE API dependency to your project +2. Configure a Jakarta Persistence persistence unit +3. Optionally configure a data source and install a JDBC driver + +{productName} implements Jakarta Data repositories using the JNoSQL provider, which delegates to Jakarta Persistence (JPA) for database interactions. Therefpre, to use Jakarta Data repositories, you need to configure a Jakarta Persistence persistence unit. Jakarta Data {jakarta-data-spec-version} doesn't specify how repositories integrate with JPA. The documentation about integrating Jakarta Data with JPA is specific to {productName}. + +==== Adding Dependencies + +Add the Jakarta Data API dependency to your `pom.xml`: + +[source,xml,subs="specialchars,attributes"] +---- + + jakarta.data + jakarta.data-api + {jakarta-data-api-version} + +---- + +Alternatively, if you're using the full Jakarta EE platform, you can use: + +[source,xml,subs="specialchars,attributes"] +---- + + jakarta.platform + jakarta.jakartaee-api + {jakarta-platform-version} + provided + +---- + +==== Configuring Jakarta Persistence + +Configure Jakarta Data in your `persistence.xml`: + +[source,xml] +---- + + com.example.model.Product + + + + +---- + +This will use the default data source configured in {productName}, which points to an external Derby DB. Make sure that DerbyDB is running if you use the default datasource. If you want to specify a custom data source, see the next section. + +==== Data Source Configuration (Optional) + +If you need to configure a custom data source, use the {productName} administration console or the `asadmin` CLI command, with create-jdbc-connection-pool and create-jdbc-resource commands, and appropriate JDBC driver installed in {productName}: + +[source,bash] +---- +asadmin create-jdbc-connection-pool --datasourceclassname org.postgresql.ds.PGSimpleDataSource \ + --restype javax.sql.DataSource \ + --property user=myuser:password=mypassword:databaseName=mydb:serverName=localhost:port=5432 \ + MyPool + +asadmin create-jdbc-resource --connectionpoolid MyPool jdbc/MyDataSource +---- + +The above example uses PostgreSQL database. Adjust the `datasourceclassname` and properties according to your database and JDBC driver. + +Then adjust your `persistence.xml` to reference the custom data source by its JNDI name defined by the create-jdbc-resource command earlier: + +[source,xml] +---- + + jdbc/MyDataSource + com.example.model.Product + + + + +---- + +[[integration-with-jpa]] + +=== Integration with Jakarta Persistence (JPA) + +In {productName}, Jakarta Data repositories can work alongside traditional JPA EntityManager operations in the same application. Internally, Jakarta Data repositories use JPA for database interactions, so they share the same persistence context. Calling repository methods is equivalent to using EntityManager alone and you can mix them in the same application, even in the same transaction. + +==== Retrieve EntityManager in default methods + +You can access the EntityManager used by the repository using a method in the repository interface that returns EntityManager. This allows you to implement custom default repository methods that use the EntityManager directly. + +Example: + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + // Method to access the repository's EntityManager + EntityManager getEntityManager(); + + // Custom method using the repository's EntityManager + default List findProductsWithComplexLogic(String searchTerm) { + EntityManager em = getEntityManager(); + return em.createQuery( + "SELECT p FROM Product p WHERE p.name LIKE :term OR p.description LIKE :term", + Product.class) + .setParameter("term", "%" + searchTerm + "%") + .getResultList(); + } +} +---- + +==== EntityManager Configuration + +By default, Jakarta Data repositories use the default EntityManager as if it's injected via `@Inject EntityManager`. + +You can use a specific `EntityManager` by one of the following methods: + +* Specify the persistence unit name in the `@Repository` annotation +* Specify CDI qualifiers on a method to select a specific `EntityManager` +* Create a custom default method that returns an `EntityManager` + +===== Specifying Persistence Unit + +To use a specific persistence unit, set the `dataStore` attribute in the `@Repository` annotation to the name of the persistence unit defined in `persistence.xml`. + +===== Specifying CDI Qualifiers on a method + +A custom EntityManager can be specified using a repository method that returns EntityManager. Such method should be annotated by CDI qualifiers that should be used to retrieve the EntityManager. The implementation of the method will also return this EntityManager when called in the application. + +If a single repository contains several methods that return EntityManager, calling repository methods will throw an exception. + + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + // Method to access the repository's EntityManager + @CustomDB + EntityManager getEntityManager(); + +} +---- + +===== Custom method that returns EntityManager + +To specify a custom EntityManager programmatically, define a default method in the repository interface that returns an EntityManager. You can use CDI programmatically to inject the desired EntityManager. + +[source,java] +---- +@Repository +public interface ProductRepository extends CrudRepository { + + // Method to provide a custom EntityManager to the repository + default EntityManager getEntityManager() { + return CDI.current().select(EntityManager.class, new CustomDB.Literal()).get(); + } + +} +---- + +==== Mixing repositories and JPA EntityManager + +The following cases will use the same persistence context: + +* Calling repository methods that reuse the existing transaction +* Using EntityManager retrieved from the repository +* Using an injected EntityManager for the same persistence unit + +You can freely mix Jakarta Data repository methods and direct EntityManager operations in the same application, even in the same transaction. As long as the EntityMangers are for the same persistence unit, they will share the same persistence context. If they are for different persistence units, they will operate independently and will require XA datasources if used in the same transaction. + +[source,java] +---- +@ApplicationScoped +@Transactional +public class CustomerService { + + @Inject + private EntityManager entityManager; + + @Inject + private CustomerRepository customerRepository; + + public Customer updateCustomerWithAudit(Long customerId, CustomerUpdate update) { + + EntityManager repositoryEntityManager = customerRepository.getEntityManager(); + + // Use repository for simple operations + Customer customer = customerRepository.findById(customerId) + .orElseThrow(() -> new EntityNotFoundException("Customer not found")); + + // Use EntityManager for complex operations + AuditLog audit = new AuditLog(); + audit.setAction("UPDATE_CUSTOMER"); + audit.setEntityId(customerId); + audit.setTimestamp(LocalDateTime.now()); + entityManager.persist(audit); + + // Alternatively, use the repository's EntityManager to ensure the same persistence context + repositoryEntityManager.flush(); + + // Update using repository + customer.setName(update.getName()); + customer.setEmail(update.getEmail()); + + return customerRepository.save(customer); + } +} +---- diff --git a/docs/application-development-guide/src/main/asciidoc/jpa.adoc b/docs/application-development-guide/src/main/asciidoc/jpa.adoc index 3321d7de4cf..0c2a51f5d65 100644 --- a/docs/application-development-guide/src/main/asciidoc/jpa.adoc +++ b/docs/application-development-guide/src/main/asciidoc/jpa.adoc @@ -1,7 +1,7 @@ type=page status=published title=Configuring the Java Persistence Provider -next=webapps.html +next=jakarta-data.html prev=webservices.html ~~~~~~ diff --git a/docs/application-development-guide/src/main/asciidoc/lot.adoc b/docs/application-development-guide/src/main/asciidoc/lot.adoc index 12b32b0894c..c33d157036b 100644 --- a/docs/application-development-guide/src/main/asciidoc/lot.adoc +++ b/docs/application-development-guide/src/main/asciidoc/lot.adoc @@ -15,18 +15,18 @@ prev=loe.html * xref:securing-apps.adoc#message-security-provider-props[4-2 Message Security Provider Properties] * xref:jpa.adoc#gbwlr[6-1 The asadmin deploy and asadmin deploydir Generation Options] * xref:jpa.adoc#gbwmm[6-2 The asadmin undeploy Generation Options] -* xref:webapps.adoc#fvygg[7-1 The cache Attributes] -* xref:webapps.adoc#fvyep[7-2 The flush Attributes] -* xref:webapps.adoc#fvyem[7-3 Object Types Supported for Jakarta EE Web Application Session State Failover] -* xref:webapps.adoc#gheoy[7-4 SSIServlet init-param Values] -* xref:webapps.adoc#ghern[7-5 CGIServlet init-param Values] -* xref:ejb.adoc#fvyed[8-1 Object Types Supported for Jakarta EE Stateful Session Bean State Failover] -* xref:container_managed-persistence.adoc#fvyaq[9-1 Java Type to JDBC Type Mappings for CMP] -* xref:container_managed-persistence.adoc#fvymp[9-2 Mappings of JDBC Types to Database Vendor Specific Types for CMP] -* xref:container_managed-persistence.adoc#fvymo[9-3 The glassfish-ejb-jar.xml Generation Elements] -* xref:container_managed-persistence.adoc#fvymn[9-4 The asadmin deploy and asadmin deploydir Generation Options for CMP] -* xref:container_managed-persistence.adoc#fvymt[9-5 The asadmin undeploy Generation Options for CMP] -* xref:java-clients.adoc#gkmbk[10-1 Owned JNLP File Content] -* xref:java-clients.adoc#gkmci[10-2 Defaulted JNLP File Content] -* xref:java-clients.adoc#gkmcc[10-3 Merged JNLP File Content] -* xref:transaction-service.adoc#fvyoi[15-1 Transaction Isolation Levels] +* xref:webapps.adoc#fvygg[8-1 The cache Attributes] +* xref:webapps.adoc#fvyep[8-2 The flush Attributes] +* xref:webapps.adoc#fvyem[8-3 Object Types Supported for Jakarta EE Web Application Session State Failover] +* xref:webapps.adoc#gheoy[8-4 SSIServlet init-param Values] +* xref:webapps.adoc#ghern[8-5 CGIServlet init-param Values] +* xref:ejb.adoc#fvyed[9-1 Object Types Supported for Jakarta EE Stateful Session Bean State Failover] +* xref:container_managed-persistence.adoc#fvyaq[10-1 Java Type to JDBC Type Mappings for CMP] +* xref:container_managed-persistence.adoc#fvymp[10-2 Mappings of JDBC Types to Database Vendor Specific Types for CMP] +* xref:container_managed-persistence.adoc#fvymo[10-3 The glassfish-ejb-jar.xml Generation Elements] +* xref:container_managed-persistence.adoc#fvymn[10-4 The asadmin deploy and asadmin deploydir Generation Options for CMP] +* xref:container_managed-persistence.adoc#fvymt[10-5 The asadmin undeploy Generation Options for CMP] +* xref:java-clients.adoc#gkmbk[11-1 Owned JNLP File Content] +* xref:java-clients.adoc#gkmci[11-2 Defaulted JNLP File Content] +* xref:java-clients.adoc#gkmcc[11-3 Merged JNLP File Content] +* xref:transaction-service.adoc#fvyoi[16-1 Transaction Isolation Levels] diff --git a/docs/application-development-guide/src/main/asciidoc/webapps.adoc b/docs/application-development-guide/src/main/asciidoc/webapps.adoc index beec6fd7a56..1f72630c42f 100644 --- a/docs/application-development-guide/src/main/asciidoc/webapps.adoc +++ b/docs/application-development-guide/src/main/asciidoc/webapps.adoc @@ -2,7 +2,7 @@ type=page status=published title=Developing Web Applications next=ejb.html -prev=jpa.html +prev=jakarta-data.html ~~~~~~ = Developing Web Applications diff --git a/docs/parent/pom.xml b/docs/parent/pom.xml index 0d6b5de9571..16bd1683fce 100644 --- a/docs/parent/pom.xml +++ b/docs/parent/pom.xml @@ -33,6 +33,8 @@ true 3.2.0 2.3.19 + false + false DRAFT Eclipse GlassFish @@ -120,6 +122,7 @@ process-asciidoc + ${asciidoc.html.skip} html ${bookDirectory} book.adoc @@ -147,6 +150,7 @@ process-asciidoc + ${asciidoc.pdf.skip} pdf ${bookDirectory} book.adoc @@ -203,6 +207,7 @@ attach-artifact + ${asciidoc.pdf.skip} ${project.build.directory}/pdf/${pdf.fileName} From 686c734d8dff447cec07e60084d9d57810d8b685 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Mon, 8 Sep 2025 15:23:58 +0200 Subject: [PATCH 5/5] Jakarta Data integration - Adjust to recent changes in JNoSQL PersistenceDatabaseManager is no longer a CDI bean. Instead, PersistenceDatabaseManagerProvider is a bean that creates PersistenceDatabaseManager instances per EntityManager --- .../JakartaPersistenceIntegrationExtension.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java index a1c7bbe0005..3d2ae19034c 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/mapping/glassfishcontext/JakartaPersistenceIntegrationExtension.java @@ -34,7 +34,7 @@ import java.util.logging.Logger; import org.eclipse.jnosql.jakartapersistence.communication.EntityManagerProvider; -import org.eclipse.jnosql.jakartapersistence.communication.PersistenceDatabaseManager; +import org.eclipse.jnosql.jakartapersistence.communication.PersistenceDatabaseManagerProvider; import org.eclipse.jnosql.jakartapersistence.mapping.EnsureTransactionInterceptor; import org.eclipse.jnosql.jakartapersistence.mapping.repository.AbstractRepositoryPersistenceBean; import org.eclipse.jnosql.jakartapersistence.mapping.spi.MethodInterceptor; @@ -106,9 +106,11 @@ private void defineJNoSqlBeans(AfterBeanDiscovery afterBeanDiscovery, BeanManage addBean(Converters.class, afterBeanDiscovery, beanManager) .scope(ApplicationScoped.class); - addBean(PersistenceDatabaseManager.class, afterBeanDiscovery, beanManager) + addBean(PersistenceDatabaseManagerProvider.class, afterBeanDiscovery, beanManager) .scope(ApplicationScoped.class); + // TODO: Extend this to inject EM by unit name via @PesistenceContext mechanism, + // even if not qualifier is defined for the persistence unit addBean(EntityManagerProvider.class, afterBeanDiscovery, beanManager) .scope(ApplicationScoped.class);