diff --git a/jpalite-quarkus-extension/deployment/lombok.config b/jpalite-quarkus-extension/deployment/lombok.config
new file mode 100644
index 0000000..2066d75
--- /dev/null
+++ b/jpalite-quarkus-extension/deployment/lombok.config
@@ -0,0 +1 @@
+lombok.log.fieldName=LOG
diff --git a/jpalite-quarkus-extension/deployment/pom.xml b/jpalite-quarkus-extension/deployment/pom.xml
index 4c26882..4741807 100644
--- a/jpalite-quarkus-extension/deployment/pom.xml
+++ b/jpalite-quarkus-extension/deployment/pom.xml
@@ -16,7 +16,8 @@
~ limitations under the License.
-->
-
4.0.0
@@ -59,6 +60,10 @@
jpalite-extension
${project.version}
+
+ org.projectlombok
+ lombok
+
diff --git a/jpalite-quarkus-extension/deployment/src/main/java/io/jpalite/extension/deployment/JPALiteExtensionProcessor.java b/jpalite-quarkus-extension/deployment/src/main/java/io/jpalite/extension/deployment/JPALiteExtensionProcessor.java
index fb58fc6..babc5b6 100644
--- a/jpalite-quarkus-extension/deployment/src/main/java/io/jpalite/extension/deployment/JPALiteExtensionProcessor.java
+++ b/jpalite-quarkus-extension/deployment/src/main/java/io/jpalite/extension/deployment/JPALiteExtensionProcessor.java
@@ -17,15 +17,38 @@
package io.jpalite.extension.deployment;
-import io.jpalite.agroal.AgroalDataSourceProvider;
-import io.jpalite.extension.PropertyPersistenceUnitProvider;
+import io.jpalite.*;
+import io.jpalite.extension.JPALiteConfigMapping;
+import io.jpalite.extension.JPALiteRecorder;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Default;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.transaction.TransactionManager;
+import jakarta.transaction.TransactionSynchronizationRegistry;
+import org.jboss.jandex.ClassType;
+import org.jboss.jandex.DotName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;
class JPALiteExtensionProcessor
{
+ private static final DotName ENTITY_MANAGER_FACTORY = DotName.createSimple("jakarta.persistence.EntityManagerFactory");
+ public static final DotName ENTITY_MANAGER = DotName.createSimple("jakarta.persistence.EntityManager");
+ private static final Logger LOG = LoggerFactory.getLogger(JPALiteExtensionProcessor.class);
+
+ private static final String DEFAULT_NAME = "";
private static final String FEATURE = "jpalite-extension";
@@ -46,8 +69,102 @@ NativeImageResourceBuildItem nativeImageResourceBuildItem()
@BuildStep
ReflectiveClassBuildItem reflection()
{
- return ReflectiveClassBuildItem.builder(AgroalDataSourceProvider.class,
- PropertyPersistenceUnitProvider.class)
+ return ReflectiveClassBuildItem.builder(DataSourceProvider.class,
+ PersistenceUnitProvider.class,
+ FieldConvertType.class,
+ EntityMetaDataManager.class)
.build();
}
+
+ @Record(RUNTIME_INIT)
+ @BuildStep
+ void generateJPABeans(JPALiteRecorder recorder,
+ JPALiteConfigMapping jpaConfigMapping,
+ BuildProducer syntheticBeanBuildItemBuildProducer)
+ {
+ if (jpaConfigMapping.defaultPersistenceUnit() != null) {
+ //Define the default EntityManagerFactory producer
+ syntheticBeanBuildItemBuildProducer
+ .produce(createSyntheticBean(DEFAULT_NAME,
+ false,
+ EntityManagerFactory.class,
+ List.of(ENTITY_MANAGER_FACTORY)
+ , true)
+ .createWith(recorder.entityManagerFactorySupplier(DEFAULT_NAME))
+ .done());
+
+ //Define the default EntityManager producer
+ syntheticBeanBuildItemBuildProducer
+ .produce(createSyntheticBean(DEFAULT_NAME,
+ false,
+ EntityManager.class,
+ List.of(ENTITY_MANAGER)
+ , true)
+ .createWith(recorder.entityManagerSupplier(DEFAULT_NAME))
+ .addInjectionPoint(ClassType.create(DotName.createSimple(TransactionManager.class)))
+ .addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSynchronizationRegistry.class)))
+ .done());
+ }//if
+
+
+ if (jpaConfigMapping.namedPersistenceUnits() != null) {
+ for (String unitName : jpaConfigMapping.namedPersistenceUnits().keySet()) {
+ //Define the named EntityManagerFactory producer
+ syntheticBeanBuildItemBuildProducer
+ .produce(createSyntheticBean(unitName,
+ true,
+ EntityManagerFactory.class,
+ List.of(ENTITY_MANAGER_FACTORY)
+ , false)
+ .createWith(recorder.entityManagerFactorySupplier(unitName))
+ .done());
+
+ //Define the named EntityManager producer
+ syntheticBeanBuildItemBuildProducer
+ .produce(createSyntheticBean(unitName,
+ true,
+ EntityManager.class,
+ List.of(ENTITY_MANAGER)
+ , false)
+ .createWith(recorder.entityManagerSupplier(unitName))
+ .addInjectionPoint(ClassType.create(DotName.createSimple(TransactionManager.class)))
+ .addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSynchronizationRegistry.class)))
+ .done());
+
+ }
+ }//if
+ }
+
+ private static SyntheticBeanBuildItem.ExtendedBeanConfigurator createSyntheticBean(String persistenceUnitName,
+ boolean isNamedPersistenceUnit,
+ Class type,
+ List allExposedTypes,
+ boolean defaultBean)
+ {
+ LOG.info("Creating Synthetic Bean for {}(\"{}\")", type.getSimpleName(), persistenceUnitName);
+ SyntheticBeanBuildItem.ExtendedBeanConfigurator configurator = SyntheticBeanBuildItem
+ .configure(type)
+ .scope(ApplicationScoped.class)
+ .unremovable()
+ .setRuntimeInit();
+
+ for (DotName exposedType : allExposedTypes) {
+ configurator.addType(exposedType);
+ }
+
+ if (defaultBean) {
+ configurator.defaultBean();
+ }
+
+ if (isNamedPersistenceUnit) {
+// configurator.addQualifier(Default.class);
+ configurator.addQualifier().annotation(PersistenceUnit.class).addValue("value", persistenceUnitName).done();
+ }
+ else {
+ configurator.addQualifier(Default.class);
+ configurator.addQualifier().annotation(PersistenceUnit.class).done();
+ }
+
+ return configurator;
+ }
}
diff --git a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/PersistenceUnit.java b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/PersistenceUnit.java
index 511e3ff..db5f4e6 100644
--- a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/PersistenceUnit.java
+++ b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/PersistenceUnit.java
@@ -38,7 +38,7 @@
@SuppressWarnings("ClassExplicitlyAnnotation")
- class PersistenceUnitLiteral extends AnnotationLiteral implements PersistenceUnit
+ final class PersistenceUnitLiteral extends AnnotationLiteral implements PersistenceUnit
{
private final String name;
diff --git a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteConfigMapping.java b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteConfigMapping.java
index 8a2b327..878a346 100644
--- a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteConfigMapping.java
+++ b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteConfigMapping.java
@@ -32,7 +32,7 @@
import java.util.Map;
@ConfigMapping(prefix = "jpalite.persistenceUnit")
-@ConfigRoot(phase = ConfigPhase.RUN_TIME)
+@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public interface JPALiteConfigMapping
{
/**
diff --git a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteRecorder.java b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteRecorder.java
new file mode 100644
index 0000000..d25730f
--- /dev/null
+++ b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/JPALiteRecorder.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.jpalite.extension;
+
+import io.quarkus.arc.SyntheticCreationalContext;
+import io.quarkus.runtime.annotations.Recorder;
+import jakarta.inject.Inject;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Persistence;
+import jakarta.transaction.TransactionManager;
+import jakarta.transaction.TransactionSynchronizationRegistry;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+
+@Slf4j
+@Recorder
+public class JPALiteRecorder
+{
+ private final Map entityManagerFactoryList = new ConcurrentHashMap<>();
+
+ @Inject
+ TransactionManager transactionManager;
+
+ @Inject
+ TransactionSynchronizationRegistry transactionSynchronizationRegistry;
+
+ public Function, EntityManagerFactory> entityManagerFactorySupplier(String persistenceUnitName)
+ {
+ return context -> entityManagerFactoryList.computeIfAbsent(persistenceUnitName, Persistence::createEntityManagerFactory);
+ }
+
+ public EntityManager getEntityManager(String persistenceUnit)
+ {
+ EntityManagerFactory factory = entityManagerFactoryList.computeIfAbsent(persistenceUnit, Persistence::createEntityManagerFactory);
+ return new TransactionScopedEntityManagerImpl(factory,
+ transactionManager,
+ transactionSynchronizationRegistry);
+ }//getEntityManager
+
+ public Function, EntityManager> entityManagerSupplier(String persistenceUnitName)
+ {
+ return context -> {
+ TransactionManager transactionManager = context.getInjectedReference(TransactionManager.class);
+ TransactionSynchronizationRegistry transactionSynchronizationRegistry = context.getInjectedReference(TransactionSynchronizationRegistry.class);
+ EntityManagerFactory factory = entityManagerFactoryList.computeIfAbsent(persistenceUnitName, Persistence::createEntityManagerFactory);
+ return new TransactionScopedEntityManagerImpl(factory,
+ transactionManager,
+ transactionSynchronizationRegistry);
+ };
+ }
+}
diff --git a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/PersistenceProducer.java b/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/PersistenceProducer.java
deleted file mode 100644
index a00783f..0000000
--- a/jpalite-quarkus-extension/runtime/src/main/java/io/jpalite/extension/PersistenceProducer.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.jpalite.extension;
-
-import io.jpalite.PersistenceUnit;
-import io.quarkus.arc.Unremovable;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.inject.Produces;
-import jakarta.enterprise.inject.spi.InjectionPoint;
-import jakarta.inject.Inject;
-import jakarta.persistence.EntityManager;
-import jakarta.persistence.EntityManagerFactory;
-import jakarta.persistence.Persistence;
-import jakarta.transaction.TransactionManager;
-import jakarta.transaction.TransactionSynchronizationRegistry;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.ConfigProvider;
-
-import java.lang.annotation.Annotation;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-
-@Unremovable
-@ApplicationScoped
-@Slf4j
-public class PersistenceProducer
-{
- private final Map entityManagerFactoryList = new ConcurrentHashMap<>();
-
- @Inject
- TransactionManager transactionManager;
-
- @Inject
- TransactionSynchronizationRegistry transactionSynchronizationRegistry;
-
- public EntityManagerFactory getEntityManagerFactory(String persistenceUnit)
- {
-
- String persistenceUnitName = "";
- if (persistenceUnit != null && !persistenceUnit.isBlank()) {
- if (persistenceUnit.startsWith("${")) {
- String key = persistenceUnit.substring(2, persistenceUnit.lastIndexOf('}'));
- Config configProvider = ConfigProvider.getConfig();
- Optional value = configProvider.getOptionalValue(key, String.class);
- if (value.isPresent()) {
- LOG.debug("Persistence unit name is defined using a variable {} = {} ", persistenceUnitName, value.get());
- persistenceUnitName = value.get();
- }//if
- else {
- LOG.debug("Persistence unit name defined using a variable {} but variable is not defined", persistenceUnitName);
- }//else
- }//if
- else {
- persistenceUnitName = persistenceUnit;
- }
- }//if
-
- LOG.debug("Producing new Entity Manager Factory using @PersistenceUnit(\"{}\")", persistenceUnitName);
- return entityManagerFactoryList.computeIfAbsent(persistenceUnitName, Persistence::createEntityManagerFactory);
- }
-
- public EntityManager getEntityManager(String persistenceUnit)
- {
- return new TransactionScopedEntityManagerImpl(getEntityManagerFactory(persistenceUnit),
- transactionManager,
- transactionSynchronizationRegistry);
- }//getEntityManager
-
- @Unremovable
- @Produces
- @PersistenceUnit
- public EntityManagerFactory injectEntityManagerFactory(InjectionPoint injectionPoint)
- {
- String persistenceUnitName = "";
-
- Annotation qualifier = null;
- if (injectionPoint.getAnnotated() != null) {
- qualifier = injectionPoint.getAnnotated().getAnnotations()
- .stream()
- .filter(PersistenceUnit.class::isInstance)
- .findFirst()
- .orElse(null);
- }//if
-
- if (qualifier == null) {
- /**
- * If PersistenceUnit annotation is not found, check if it was not provided
- * as a qualifier
- */
- qualifier = injectionPoint.getQualifiers()
- .stream()
- .filter(PersistenceUnit.class::isInstance)
- .findFirst()
- .orElse(null);
- }//if
-
- if (qualifier instanceof PersistenceUnit persistenceUnit) {
- persistenceUnitName = persistenceUnit.value();
- }//if
-
- return getEntityManagerFactory(persistenceUnitName);
- }//getEntityManagerFactory
-
- @Unremovable
- @Produces
- @PersistenceUnit
- public EntityManager injectEntityManager(InjectionPoint injectionPoint)
- {
- return new TransactionScopedEntityManagerImpl(injectEntityManagerFactory(injectionPoint),
- transactionManager,
- transactionSynchronizationRegistry);
- }//getEntityManager
-
- @Unremovable
- @Produces
- public EntityManagerFactory injectDefaultEntityManagerFactory(InjectionPoint injectionPoint)
- {
- return injectEntityManagerFactory(injectionPoint);
- }
-
- @Unremovable
- @Produces
- public EntityManager injectDefaultEntityManager(InjectionPoint injectionPoint)
- {
- return new TransactionScopedEntityManagerImpl(injectEntityManagerFactory(injectionPoint),
- transactionManager,
- transactionSynchronizationRegistry);
- }//getEntityManager
-}
diff --git a/jpalite-repository/lombok.config b/jpalite-repository/lombok.config
new file mode 100644
index 0000000..2066d75
--- /dev/null
+++ b/jpalite-repository/lombok.config
@@ -0,0 +1 @@
+lombok.log.fieldName=LOG
diff --git a/jpalite-repository/pom.xml b/jpalite-repository/pom.xml
index a6b94e6..cba57b7 100644
--- a/jpalite-repository/pom.xml
+++ b/jpalite-repository/pom.xml
@@ -67,5 +67,9 @@
auto-service
1.1.1
+
+ org.projectlombok
+ lombok
+
diff --git a/jpalite-repository/src/main/java/io/jpalite/repository/JPALiteRepositoryProcessor.java b/jpalite-repository/src/main/java/io/jpalite/repository/JPALiteRepositoryProcessor.java
index b913659..c6acda4 100644
--- a/jpalite-repository/src/main/java/io/jpalite/repository/JPALiteRepositoryProcessor.java
+++ b/jpalite-repository/src/main/java/io/jpalite/repository/JPALiteRepositoryProcessor.java
@@ -146,12 +146,6 @@ private void addJpaRepository(PrintWriter out, DeclaredType jpaRepository)
out.println("}");
out.println("");
- out.println("public " + argType + " clone(" + argType + " entity) {");
- out.println(" EntityManager em = getEntityManager();");
- out.println(" return ((JPALiteEntityManager)em).clone(entity);");
- out.println("}");
- out.println("");
-
out.println("public void delete(" + argType + " entity) {");
out.println(" EntityManager em = getEntityManager();");
out.println(" em.remove(entity);");
@@ -408,15 +402,10 @@ private void generateRepo(TypeElement repoElement, Repository annotation) throws
out.println("import jakarta.transaction.Transactional;");
out.println("import jakarta.annotation.Generated;");
out.println("import jakarta.persistence.*;");
- out.println("import java.util.Collections;");
- out.println("import java.util.List;");
- out.println("import java.util.HashMap;");
- out.println("import java.util.Map;");
- out.println("import io.jpalite.extension.PersistenceProducer;");
- out.println("import io.jpalite.JPALiteEntityManager;");
+ out.println("import java.util.*;");
out.println("import io.jpalite.PersistenceUnit;");
out.println("import io.jpalite.repository.*;");
- out.println("import io.jpalite.EntityState;");
+// out.println("import io.jpalite.EntityState;");
out.println();
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
@@ -435,18 +424,25 @@ private void generateRepo(TypeElement repoElement, Repository annotation) throws
out.print(repoElement.getQualifiedName());
out.println(" {");
-// out.println(" @Inject");
-// out.print(" @PersistenceUnit(\"");
-// out.print(annotation.persistenceUnit());
-// out.println("\")");
-// out.println(" EntityManager em;");
+
+ if (!annotation.persistenceUnit().startsWith("${")) {
+ out.println(" @Inject");
+ out.print(" @PersistenceUnit(\"");
+ out.print(annotation.persistenceUnit());
+ out.println("\")");
+ out.println(" EntityManager em;");
+ }//if
out.println("public EntityManager getEntityManager() {");
- out.println(" PersistenceProducer producer = Arc.container().instance(PersistenceProducer.class).get();");
- out.print(" return producer.getEntityManager(\"");
- out.print(annotation.persistenceUnit());
- out.println("\");");
-// out.println(" return em;");
+ if (annotation.persistenceUnit().startsWith("${")) {
+ out.println(" io.jpalite.extension.JPALiteRecorder producer = Arc.container().instance(io.jpalite.extension.JPALiteRecorder.class).get();");
+ out.print(" return producer.getEntityManager(JpaRepositoryUtil.getPersistenceUnitName(\"");
+ out.print(annotation.persistenceUnit());
+ out.println("\"));");
+ }//if
+ else {
+ out.println(" return em;");
+ }//else
out.println("}");
repoElement.getInterfaces()
diff --git a/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepository.java b/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepository.java
index c9eaaa9..37c5b54 100644
--- a/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepository.java
+++ b/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepository.java
@@ -97,14 +97,6 @@ public interface JpaRepository extends RepositoryBase
*/
E getReference(I id);
- /**
- * Create a clone of an existing entity.
- *
- * @param entity
- * @return The new entity
- */
- E clone(E entity);
-
/**
* Delete an attached entity from the repository.
*
diff --git a/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepositoryUtil.java b/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepositoryUtil.java
new file mode 100644
index 0000000..e200ab4
--- /dev/null
+++ b/jpalite-repository/src/main/java/io/jpalite/repository/JpaRepositoryUtil.java
@@ -0,0 +1,39 @@
+package io.jpalite.repository;
+
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+import java.util.Optional;
+
+@Slf4j
+public class JpaRepositoryUtil
+{
+ private JpaRepositoryUtil()
+ {
+ //Prevent the class from being instantiated
+ }
+
+ public static String getPersistenceUnitName(String persistenceUnit)
+ {
+ String persistenceUnitName = "";
+ if (persistenceUnit != null && !persistenceUnit.isBlank()) {
+ if (persistenceUnit.startsWith("${")) {
+ String key = persistenceUnit.substring(2, persistenceUnit.lastIndexOf('}'));
+ Config configProvider = ConfigProvider.getConfig();
+ Optional value = configProvider.getOptionalValue(key, String.class);
+ if (value.isPresent()) {
+ LOG.debug("Persistence unit name is defined using a variable {} = {} ", persistenceUnitName, value.get());
+ persistenceUnitName = value.get();
+ }//if
+ else {
+ LOG.warn("Persistence unit name defined using a variable {} but variable is not defined", persistenceUnitName);
+ }//else
+ }//if
+ else {
+ persistenceUnitName = persistenceUnit;
+ }
+ }//if
+ return persistenceUnitName;
+ }
+}