From 62a886a49dc8521a5d5ab43342d56ac9b8d65f75 Mon Sep 17 00:00:00 2001 From: Rudy De Busscher Date: Fri, 12 May 2023 13:59:03 +0200 Subject: [PATCH 1/2] Integration for Quarkus 3.x. Fixes #564 --- .../misc/pages/integrations/quarkus.adoc | 11 + integrations/pom.xml | 1 + integrations/quarkus3/deployment/pom.xml | 64 ++++ .../MicrostreamExtensionProcessor.java | 172 ++++++++++ .../deployment/StorageBeanBuildItem.java | 70 ++++ .../quarkus/deployment/CleanupUtil.java | 37 +++ .../ExtensionFoundationCustomizerTest.java | 66 ++++ .../deployment/ExtensionRootBeanTest.java | 70 ++++ .../ExtensionStorageInitializerTest.java | 69 ++++ ...ExtensionStorageManagerNotStartedTest.java | 63 ++++ .../ExtensionStorageManagerProducerTest.java | 68 ++++ .../deployment/MultipleRootErrorTest.java | 71 ++++ .../deployment/test/OtherRootWithStorage.java | 40 +++ .../deployment/test/SomeCustomizer.java | 36 ++ .../deployment/test/SomeInitializer.java | 43 +++ .../test/SomeInitializerForStorage.java | 41 +++ .../quarkus/deployment/test/SomeRoot.java | 34 ++ .../deployment/test/SomeRootWithStorage.java | 40 +++ .../test/StorageManagerController.java | 44 +++ integrations/quarkus3/pom.xml | 103 ++++++ integrations/quarkus3/runtime/pom.xml | 67 ++++ .../integrations/quarkus/types/Storage.java | 46 +++ .../EmbeddedStorageFoundationCustomizer.java | 29 ++ .../config/StorageManagerInitializer.java | 29 ++ .../types/impl/BeanCreatorParameterNames.java | 30 ++ .../impl/ConfigurationCoreProperties.java | 307 ++++++++++++++++++ .../quarkus/types/impl/ReflectionUtils.java | 51 +++ .../quarkus/types/impl/RootCreator.java | 101 ++++++ .../quarkus/types/impl/StorageBean.java | 39 +++ .../types/impl/StorageBeanCreator.java | 47 +++ .../quarkus/types/impl/StorageClassInfo.java | 65 ++++ .../types/impl/StorageManagerProducer.java | 117 +++++++ .../src/main/resources/META-INF/beans.xml | 7 + .../resources/META-INF/quarkus-extension.yaml | 8 + 34 files changed, 2086 insertions(+) create mode 100644 integrations/quarkus3/deployment/pom.xml create mode 100644 integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/MicrostreamExtensionProcessor.java create mode 100644 integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/StorageBeanBuildItem.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/CleanupUtil.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionFoundationCustomizerTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionRootBeanTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageInitializerTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerNotStartedTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerProducerTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/MultipleRootErrorTest.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/OtherRootWithStorage.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeCustomizer.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializer.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializerForStorage.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRoot.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRootWithStorage.java create mode 100644 integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/StorageManagerController.java create mode 100644 integrations/quarkus3/pom.xml create mode 100644 integrations/quarkus3/runtime/pom.xml create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/Storage.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/EmbeddedStorageFoundationCustomizer.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/StorageManagerInitializer.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/BeanCreatorParameterNames.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ConfigurationCoreProperties.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ReflectionUtils.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/RootCreator.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBean.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBeanCreator.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageClassInfo.java create mode 100644 integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageManagerProducer.java create mode 100644 integrations/quarkus3/runtime/src/main/resources/META-INF/beans.xml create mode 100644 integrations/quarkus3/runtime/src/main/resources/META-INF/quarkus-extension.yaml diff --git a/docs/modules/misc/pages/integrations/quarkus.adoc b/docs/modules/misc/pages/integrations/quarkus.adoc index 0529a0117..fcf9ee7f5 100644 --- a/docs/modules/misc/pages/integrations/quarkus.adoc +++ b/docs/modules/misc/pages/integrations/quarkus.adoc @@ -13,6 +13,17 @@ mvn quarkus:add-extension -Dextensions="one.microstream:microstream-quarkus-exte The extension requires Quarkus 2.11.1 as a minimal version. +The integration requires Spring Boot 2.x (with version 2.1.0.RELEASE being the minimal supported one). + +If you are running Quarkus 3, use the following dependency in your project: + +[source, shell, title="Add Quarkus 3 extension", subs=attributes+] +---- +mvn quarkus:add-extension -Dextensions="one.microstream:microstream-quarkus3-extension:09.00.00-MS-GA" +---- + +The migration from version 2 to 3 doesn't require any code changes related to the MicroStream integration classes. + == Configuration The configuration of the _StorageManager_ can be done using key/value pairs that are provided by Quarkus configuration. The configuration keys must be prefixed by `one.microstream` diff --git a/integrations/pom.xml b/integrations/pom.xml index 0a5bca0eb..8bf41f42c 100644 --- a/integrations/pom.xml +++ b/integrations/pom.xml @@ -23,6 +23,7 @@ cdi3 spring-boot quarkus + quarkus3 diff --git a/integrations/quarkus3/deployment/pom.xml b/integrations/quarkus3/deployment/pom.xml new file mode 100644 index 000000000..6a6924011 --- /dev/null +++ b/integrations/quarkus3/deployment/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + one.microstream + microstream-integrations-quarkus3-parent + 09.00.00-MS-GA-SNAPSHOT + ../pom.xml + + + microstream-quarkus3-extension-deployment + MicroStream Quarkus 3 Extension - Deployment + https://microstream.one + + + + io.quarkus + quarkus-arc-deployment + + + one.microstream + microstream-quarkus3-extension + 09.00.00-MS-GA-SNAPSHOT + + + + + io.quarkus + quarkus-junit5-internal + test + + + + io.rest-assured + rest-assured + test + + + + io.quarkus + quarkus-resteasy + test + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${quarkus.version} + + + + + + + diff --git a/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/MicrostreamExtensionProcessor.java b/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/MicrostreamExtensionProcessor.java new file mode 100644 index 000000000..d3998376f --- /dev/null +++ b/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/MicrostreamExtensionProcessor.java @@ -0,0 +1,172 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + + +import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem; +import io.quarkus.arc.deployment.SyntheticBeanBuildItem; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import one.microstream.integrations.quarkus.types.Storage; +import one.microstream.integrations.quarkus.types.impl.BeanCreatorParameterNames; +import one.microstream.integrations.quarkus.types.impl.RootCreator; +import one.microstream.integrations.quarkus.types.impl.StorageBean; +import one.microstream.integrations.quarkus.types.impl.StorageBeanCreator; +import one.microstream.integrations.quarkus.types.impl.StorageClassInfo; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.DotName; +import org.jboss.jandex.FieldInfo; +import org.jboss.jandex.IndexView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Quarkus extension processor to handle the {@link Storage} annotation. + */ +class MicrostreamExtensionProcessor +{ + + private static final Logger LOGGER = LoggerFactory.getLogger(MicrostreamExtensionProcessor.class); + + private static final DotName STORAGE_ANNOTATION = DotName.createSimple(Storage.class.getName()); + + private static final DotName INJECT_ANNOTATION = DotName.createSimple(Inject.class.getName()); + + private static final String FEATURE = "microstream-extension"; + + @BuildStep + FeatureBuildItem feature() + { + return new FeatureBuildItem(FEATURE); + } + + @BuildStep + StorageBeanBuildItem findStorageRoot(final BeanArchiveIndexBuildItem beanArchiveIndex) + { + LOGGER.debug("BuildStep for MicroStream: Find any class that is annotated with @Storage"); + final Set rootClasses = findAnnotatedClasses(beanArchiveIndex); + if (rootClasses.size() > 1) + { + throw new IllegalStateException( + "In the application you must have only one class with the Storage annotation, classes: " + + rootClasses); + } + return new StorageBeanBuildItem(rootClasses.stream() + .findAny() + .orElse(null)); + } + + @BuildStep + SyntheticBeanBuildItem rootBean(final StorageBeanBuildItem storageBeanBuildItem) + { + + final Optional> rootClass = storageBeanBuildItem.getRootClass(); + + if (rootClass.isPresent()) + { + LOGGER.debug("BuildStep for MicroStream: Configure a SyntheticBeanBuildItem for the @Storage bean"); + LOGGER.info(String.format("Processing Extension: @Storage found at %s", rootClass)); + return SyntheticBeanBuildItem.configure(rootClass.get()) + .scope(Singleton.class) + .creator(RootCreator.class) + .done(); + + } + else + { + // Quarkus is fine with returning null for a BuildItem instance. + return null; + + } + + } + + @BuildStep + SyntheticBeanBuildItem storageBean(final StorageBeanBuildItem storageBeanBuildItem) + { + LOGGER.debug("BuildStep for MicroStream: Configure a SyntheticBeanBuildItem for the bean keeping info about @Storage class"); + + final Optional> rootClass = storageBeanBuildItem.getRootClass(); + + final String fields = String.join(",", storageBeanBuildItem.getFieldsToInject()); + + // .orElse is needed due to https://github.com/quarkusio/quarkus/issues/27664 + return SyntheticBeanBuildItem.configure(StorageBean.class) + .scope(Singleton.class) + .creator(StorageBeanCreator.class) + .param(BeanCreatorParameterNames.CLASS_NAME, rootClass.orElse(Object.class)) + .param(BeanCreatorParameterNames.FIELDS, fields) + .done(); + + } + + + + private Set findAnnotatedClasses(final BeanArchiveIndexBuildItem beanArchiveIndex) + { + final Set result = new HashSet<>(); + final IndexView indexView = beanArchiveIndex.getIndex(); + final Collection storageBeans = indexView.getAnnotations(STORAGE_ANNOTATION); + + for (AnnotationInstance ann : storageBeans) + { + ClassInfo beanClassInfo = ann.target() + .asClass(); + + result.add(createStorageBeanClassInfo(beanClassInfo)); + + } + return result; + } + + private StorageClassInfo createStorageBeanClassInfo(final ClassInfo beanClassInfo) + { + try + { + Class classReference = Class.forName(beanClassInfo.name() + .toString(), false, Thread.currentThread() + .getContextClassLoader()); + + List fieldsToInject = beanClassInfo.fields() + .stream() + .filter(fi -> fi.hasAnnotation(INJECT_ANNOTATION)) + .map(FieldInfo::name) + .collect(Collectors.toList()); + + return new StorageClassInfo(classReference, fieldsToInject); + + } catch (ClassNotFoundException e) + { + throw new RuntimeException("Unable to load Class ", e); + } + } + +} diff --git a/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/StorageBeanBuildItem.java b/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/StorageBeanBuildItem.java new file mode 100644 index 000000000..44592c2df --- /dev/null +++ b/integrations/quarkus3/deployment/src/main/java/one/microstream/integrations/quarkus/deployment/StorageBeanBuildItem.java @@ -0,0 +1,70 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + + + +import io.quarkus.builder.item.SimpleBuildItem; +import one.microstream.integrations.quarkus.types.impl.StorageClassInfo; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * {@link io.quarkus.builder.item.BuildItem} that is derived from {@link io.quarkus.arc.deployment.BeanArchiveIndexBuildItem} that keep tracks + * of the class annotated with {@link one.microstream.integrations.quarkus.types.Storage}. + */ +public final class StorageBeanBuildItem extends SimpleBuildItem +{ + + private final StorageClassInfo rootClassInfo; + + public StorageBeanBuildItem(final StorageClassInfo rootClassInfo) + { + this.rootClassInfo = rootClassInfo; + } + + /** + * Return the class where {@link one.microstream.storage.types.Storage} is defined or empty optional if + * not defined by user. + * @return Class with @Storage or empty. + */ + public Optional> getRootClass() + { + return Optional.ofNullable(this.rootClassInfo).map(StorageClassInfo::getClassReference); + } + + + /** + * Returns the names of the fields that have {@link jakarta.inject.Inject} within class annotated with + * {@link one.microstream.integrations.quarkus.types.Storage}. Empty list when no annotated placed anywhere. + * @return names of the fields to Inject or empty list if nothing to inject manually. + */ + public List getFieldsToInject() + { + if (this.rootClassInfo == null) { + return Collections.emptyList(); + } else { + return this.rootClassInfo.getFieldsToInject(); + } + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/CleanupUtil.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/CleanupUtil.java new file mode 100644 index 000000000..3173dc186 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/CleanupUtil.java @@ -0,0 +1,37 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import java.io.File; + +public class CleanupUtil +{ + + public static boolean deleteDirectory(File directoryToBeDeleted) { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + return directoryToBeDeleted.delete(); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionFoundationCustomizerTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionFoundationCustomizerTest.java new file mode 100644 index 000000000..8d0b2444e --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionFoundationCustomizerTest.java @@ -0,0 +1,66 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import one.microstream.integrations.quarkus.deployment.test.SomeCustomizer; +import one.microstream.storage.types.StorageManager; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + + +public class ExtensionFoundationCustomizerTest +{ + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(SomeCustomizer.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + ); + + @AfterEach + public void cleanup() + { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Inject + StorageManager storageManager; + + @Test + public void testCustomizer() + { + Assertions.assertNotNull(storageManager); + Assertions.assertNull(storageManager.root()); + Assertions.assertTrue(storageManager.isRunning()); + Assertions.assertEquals("JUnit", storageManager.databaseName()); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionRootBeanTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionRootBeanTest.java new file mode 100644 index 000000000..b4185e09f --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionRootBeanTest.java @@ -0,0 +1,70 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import one.microstream.integrations.quarkus.deployment.test.SomeInitializerForStorage; +import one.microstream.integrations.quarkus.deployment.test.SomeRootWithStorage; +import one.microstream.storage.types.StorageManager; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + + +public class ExtensionRootBeanTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(SomeInitializerForStorage.class, SomeRootWithStorage.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + ); + + @AfterEach + public void cleanup() { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Inject + StorageManager storageManager; + + // Required to trigger creation of Root and execution of RootCreator. + @Inject + SomeRootWithStorage root; + + @Test + public void testRootBeanCreation() { + Assertions.assertNotNull(storageManager); + Assertions.assertTrue(storageManager.isRunning()); + Assertions.assertNotNull(storageManager.root()); + Assertions.assertInstanceOf(SomeRootWithStorage.class, storageManager.root()); + SomeRootWithStorage root = (SomeRootWithStorage) storageManager.root(); + Assertions.assertEquals("Initial value of Root", root.getData()); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageInitializerTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageInitializerTest.java new file mode 100644 index 000000000..5ca906be9 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageInitializerTest.java @@ -0,0 +1,69 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import one.microstream.integrations.quarkus.deployment.test.SomeInitializer; +import one.microstream.integrations.quarkus.deployment.test.SomeRoot; +import one.microstream.storage.types.StorageManager; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + + +public class ExtensionStorageInitializerTest +{ + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(SomeInitializer.class, SomeRoot.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + ); + + @AfterEach + public void cleanup() + { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Inject + StorageManager storageManager; + + @Test + public void testInitializer() + { + Assertions.assertNotNull(storageManager); + Assertions.assertTrue(storageManager.isRunning()); + Assertions.assertNotNull(storageManager.root()); + Assertions.assertInstanceOf(SomeRoot.class, storageManager.root()); + SomeRoot root = (SomeRoot) storageManager.root(); + Assertions.assertEquals("Initial value", root.getData()); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerNotStartedTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerNotStartedTest.java new file mode 100644 index 000000000..4519dc049 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerNotStartedTest.java @@ -0,0 +1,63 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import one.microstream.integrations.quarkus.deployment.test.StorageManagerController; +import one.microstream.storage.types.StorageManager; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + +public class ExtensionStorageManagerNotStartedTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(StorageManagerController.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + .add(new StringAsset("one.microstream.autoStart=false"), "application.properties") + ); + + @Inject + StorageManager storageManager; + + @AfterEach + public void cleanup() { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Test + public void testStorageManagerProducer() { + Assertions.assertNotNull(storageManager); + Assertions.assertNull(storageManager.root()); + Assertions.assertFalse(storageManager.isRunning()); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerProducerTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerProducerTest.java new file mode 100644 index 000000000..eae0aa17b --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/ExtensionStorageManagerProducerTest.java @@ -0,0 +1,68 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; +import one.microstream.integrations.quarkus.deployment.test.StorageManagerController; +import one.microstream.storage.types.StorageManager; +import org.hamcrest.Matchers; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + +public class ExtensionStorageManagerProducerTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(StorageManagerController.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + ); + + @Inject + StorageManager storageManager; + + @AfterEach + public void cleanup() { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Test + public void testInjectionIntoController() { + RestAssured.when().get("/test").then().body(Matchers.is("storageManagerRoot=true")); + } + + @Test + public void testStorageManagerProducer() { + Assertions.assertNotNull(storageManager); + Assertions.assertNull(storageManager.root()); + Assertions.assertTrue(storageManager.isRunning()); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/MultipleRootErrorTest.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/MultipleRootErrorTest.java new file mode 100644 index 000000000..b79a6877f --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/MultipleRootErrorTest.java @@ -0,0 +1,71 @@ +package one.microstream.integrations.quarkus.deployment; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.test.QuarkusUnitTest; +import one.microstream.integrations.quarkus.deployment.test.OtherRootWithStorage; +import one.microstream.integrations.quarkus.deployment.test.SomeInitializerForStorage; +import one.microstream.integrations.quarkus.deployment.test.SomeRootWithStorage; +import one.microstream.storage.types.StorageManager; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import jakarta.inject.Inject; +import java.io.File; + + +public class MultipleRootErrorTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .assertException(e -> { + Assertions.assertEquals(IllegalStateException.class, e.getClass()); + Assertions.assertTrue(e.getMessage().startsWith("In the application you must have only one class with the Storage annotation, classes: [one.microstream.integrations.quarkus.types.impl.StorageClassInfo")); + }) + .setArchiveProducer(() -> + ShrinkWrap.create(JavaArchive.class) + .addClasses(SomeInitializerForStorage.class, SomeRootWithStorage.class, + OtherRootWithStorage.class, CleanupUtil.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + ); + + @AfterEach + public void cleanup() { + CleanupUtil.deleteDirectory(new File("storage")); + } + + @Inject + StorageManager storageManager; + + // Required to trigger creation of Root and execution of RootCreator. + @Inject + SomeRootWithStorage root; + + @Test + public void testRootBeanCreation() { + Assertions.fail("Multiple classes annotated with @Storage should be detected and fail"); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/OtherRootWithStorage.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/OtherRootWithStorage.java new file mode 100644 index 000000000..8935a10ed --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/OtherRootWithStorage.java @@ -0,0 +1,40 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.Storage; + +@Storage +public class OtherRootWithStorage +{ + + private String data; + + public String getData() + { + return data; + } + + public void setData(String data) + { + this.data = data; + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeCustomizer.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeCustomizer.java new file mode 100644 index 000000000..8d08483d2 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeCustomizer.java @@ -0,0 +1,36 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.config.EmbeddedStorageFoundationCustomizer; +import one.microstream.storage.embedded.types.EmbeddedStorageFoundation; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class SomeCustomizer implements EmbeddedStorageFoundationCustomizer +{ + @Override + public void customize(EmbeddedStorageFoundation embeddedStorageFoundation) + { + embeddedStorageFoundation.setDataBaseName("JUnit"); + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializer.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializer.java new file mode 100644 index 000000000..ae324db15 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializer.java @@ -0,0 +1,43 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.config.StorageManagerInitializer; +import one.microstream.storage.types.StorageManager; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class SomeInitializer implements StorageManagerInitializer +{ + @Override + public void initialize(StorageManager storageManager) + { + Object rootObject = storageManager.root(); + if (rootObject == null) { + SomeRoot root = new SomeRoot(); + root.setData("Initial value"); + storageManager.setRoot(root); + } else { + throw new IllegalStateException("StorageManager should not have already a Root object assigned"); + } + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializerForStorage.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializerForStorage.java new file mode 100644 index 000000000..fc26f958e --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeInitializerForStorage.java @@ -0,0 +1,41 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.config.StorageManagerInitializer; +import one.microstream.storage.types.StorageManager; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class SomeInitializerForStorage implements StorageManagerInitializer +{ + @Override + public void initialize(StorageManager storageManager) + { + SomeRootWithStorage rootObject = (SomeRootWithStorage) storageManager.root(); + if (rootObject == null) { + throw new IllegalStateException("StorageManager should have already a Root object assigned"); + } else { + rootObject.setData("Initial value of Root"); + } + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRoot.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRoot.java new file mode 100644 index 000000000..b2b32b4ed --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRoot.java @@ -0,0 +1,34 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +public class SomeRoot { + + private String data; + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRootWithStorage.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRootWithStorage.java new file mode 100644 index 000000000..469be55f8 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/SomeRootWithStorage.java @@ -0,0 +1,40 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.Storage; + +@Storage +public class SomeRootWithStorage +{ + + private String data; + + public String getData() + { + return data; + } + + public void setData(String data) + { + this.data = data; + } +} diff --git a/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/StorageManagerController.java b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/StorageManagerController.java new file mode 100644 index 000000000..ef7d66262 --- /dev/null +++ b/integrations/quarkus3/deployment/src/test/java/one/microstream/integrations/quarkus/deployment/test/StorageManagerController.java @@ -0,0 +1,44 @@ +package one.microstream.integrations.quarkus.deployment.test; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Deployment + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.storage.types.StorageManager; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/test") +@Produces(MediaType.TEXT_PLAIN) +public class StorageManagerController +{ + + @Inject + StorageManager storageManager; + + @GET + public String testStorageManager() + { + return "storageManagerRoot=" + (storageManager.root() == null); + } +} diff --git a/integrations/quarkus3/pom.xml b/integrations/quarkus3/pom.xml new file mode 100644 index 000000000..0af9befdf --- /dev/null +++ b/integrations/quarkus3/pom.xml @@ -0,0 +1,103 @@ + + 4.0.0 + + + one.microstream + microstream-integrations-parent + 09.00.00-MS-GA-SNAPSHOT + ../pom.xml + + + microstream-integrations-quarkus3-parent + 09.00.00-MS-GA-SNAPSHOT + pom + + MicroStream Integrations Quarkus + MicroStream Quarkus Extension + https://microstream.one + + + deployment + runtime + + + 11 + UTF-8 + + 3.0.0.Final + + 3.11.0 + 3.0.0 + ${surefire-plugin.version} + true + + + + + + + io.quarkus + quarkus-bom + ${quarkus.version} + pom + import + + + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus.version} + + + maven-compiler-plugin + ${compiler-plugin.version} + + + -parameters + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + true + + + + + + + + run-its + + false + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + false + + org.jboss.logmanager.LogManager + ${maven.home} + ${settings.localRepository} + + + + + + + + diff --git a/integrations/quarkus3/runtime/pom.xml b/integrations/quarkus3/runtime/pom.xml new file mode 100644 index 000000000..063d23b0e --- /dev/null +++ b/integrations/quarkus3/runtime/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + + one.microstream + microstream-integrations-quarkus3-parent + 09.00.00-MS-GA-SNAPSHOT + ../pom.xml + + + microstream-quarkus3-extension + MicroStream Quarkus 3 Extension - Runtime + https://microstream.one + + + io.quarkus + quarkus-arc + + + + one.microstream + microstream-storage-embedded + 09.00.00-MS-GA-SNAPSHOT + + + one.microstream + microstream-storage-embedded-configuration + 09.00.00-MS-GA-SNAPSHOT + + + + + + io.quarkus + quarkus-extension-maven-plugin + ${quarkus.version} + + + compile + + extension-descriptor + + + ${project.groupId}:${project.artifactId}-deployment:${project.version} + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${quarkus.version} + + + + + + + diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/Storage.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/Storage.java new file mode 100644 index 000000000..c0d448243 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/Storage.java @@ -0,0 +1,46 @@ + +package one.microstream.integrations.quarkus.types; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * The Storage class in MicroStream indicates a class as a root instance. + * Object instances can be stored as simple records. + * One value after another as a trivial byte stream. + * References between objects are mapped with unique numbers, called ObjectId, or short OID. + With both combined, + * byte streams and OIDs, an object graph can be stored in a simple and quick way, + * as well as loaded, as a whole or partially. + * Ref: Root instances + *

+ * Each application must have a unique class with this annotation. + * Note: To increase performance use immutable sub-graphs as often as possible. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +public @interface Storage { +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/EmbeddedStorageFoundationCustomizer.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/EmbeddedStorageFoundationCustomizer.java new file mode 100644 index 000000000..165e8dd4c --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/EmbeddedStorageFoundationCustomizer.java @@ -0,0 +1,29 @@ +package one.microstream.integrations.quarkus.types.config; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + + +import one.microstream.storage.embedded.types.EmbeddedStorageFoundation; + +public interface EmbeddedStorageFoundationCustomizer +{ + void customize(final EmbeddedStorageFoundation embeddedStorageFoundation); +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/StorageManagerInitializer.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/StorageManagerInitializer.java new file mode 100644 index 000000000..f8aa48ab3 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/config/StorageManagerInitializer.java @@ -0,0 +1,29 @@ +package one.microstream.integrations.quarkus.types.config; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.storage.types.StorageManager; + +public interface StorageManagerInitializer +{ + + void initialize(final StorageManager storageManager); +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/BeanCreatorParameterNames.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/BeanCreatorParameterNames.java new file mode 100644 index 000000000..0b0524ad7 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/BeanCreatorParameterNames.java @@ -0,0 +1,30 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +/** + * Names in the {@link java.util.Map} passed to {@link io.quarkus.arc.BeanCreator}. + */ +public interface BeanCreatorParameterNames +{ + String CLASS_NAME = "className"; + String FIELDS = "fields"; +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ConfigurationCoreProperties.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ConfigurationCoreProperties.java new file mode 100644 index 000000000..309afbfb9 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ConfigurationCoreProperties.java @@ -0,0 +1,307 @@ + +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.storage.embedded.configuration.types.EmbeddedStorageConfigurationPropertyNames; +import org.eclipse.microprofile.config.Config; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.StreamSupport; + + +/** + * The relation with the properties from MicroStream docs: + * Configuration properties + */ +public enum ConfigurationCoreProperties +{ + /** + * The base directory of the storage in the file system. Default is "storage" in the working directory. + */ + STORAGE_DIRECTORY( + Constants.PREFIX + "storage.directory", + EmbeddedStorageConfigurationPropertyNames.STORAGE_DIRECTORY + ), + + /** + * The live file system configuration. See storage targets configuration. + */ + STORAGE_FILESYSTEM( + Constants.PREFIX + "storage.filesystem", + EmbeddedStorageConfigurationPropertyNames.STORAGE_FILESYSTEM + ), + + /** + * If configured, the storage will not delete files. Instead of deleting a file it will be moved to this directory. + */ + DELETION_DIRECTORY( + Constants.PREFIX + "deletion.directory", + EmbeddedStorageConfigurationPropertyNames.DELETION_DIRECTORY + ), + + /** + * If configured, files that will get truncated are copied into this directory. + */ + TRUNCATION_DIRECTORY( + Constants.PREFIX + "truncation.directory", + EmbeddedStorageConfigurationPropertyNames.TRUNCATION_DIRECTORY + ), + + /** + * The backup directory. + */ + BACKUP_DIRECTORY( + Constants.PREFIX + "backup.directory", + EmbeddedStorageConfigurationPropertyNames.BACKUP_DIRECTORY + ), + + /** + * The backup file system configuration. See storage targets configuration. + */ + BACKUP_FILESYSTEM( + Constants.PREFIX + "backup.filesystem", + EmbeddedStorageConfigurationPropertyNames.BACKUP_FILESYSTEM + ), + + /** + * The number of threads and number of directories used by the storage engine. Every thread has exclusive access + * to its directory. Default is 1. + */ + CHANNEL_COUNT( + Constants.PREFIX + "channel.count", + EmbeddedStorageConfigurationPropertyNames.CHANNEL_COUNT + ), + + /** + * Name prefix of the subdirectories used by the channel threads. Default is "channel_". + */ + CHANNEL_DIRECTORY_PREFIX( + Constants.PREFIX + "channel.directory.prefix", + EmbeddedStorageConfigurationPropertyNames.CHANNEL_DIRECTORY_PREFIX + ), + + /** + * Name prefix of the storage files. Default is "channel_". + */ + DATA_FILE_PREFIX( + Constants.PREFIX + "data.file.prefix", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_PREFIX + ), + + /** + * Name suffix of the storage files. Default is ".dat". + */ + DATA_FILE_SUFFIX( + Constants.PREFIX + "data.file.suffix", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_SUFFIX + ), + + /** + * Name prefix of the storage transaction file. Default is "transactions_". + */ + TRANSACTION_FILE_PREFIX( + Constants.PREFIX + "transaction.file.prefix", + EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_PREFIX + ), + + /** + * Name suffix of the storage transaction file. Default is ".sft". + */ + TRANSACTION_FILE_SUFFIX( + Constants.PREFIX + "transaction.file.suffix", + EmbeddedStorageConfigurationPropertyNames.TRANSACTION_FILE_SUFFIX + ), + + /** + * The name of the dictionary file. Default is "PersistenceTypeDictionary.ptd". + */ + TYPE_DICTIONARY_FILE_NAME( + Constants.PREFIX + "type.dictionary.file.name", + EmbeddedStorageConfigurationPropertyNames.TYPE_DICTIONARY_FILE_NAME + ), + + /** + * Name suffix of the storage rescue files. Default is ".bak". + */ + RESCUED_FILE_SUFFIX( + Constants.PREFIX + "rescued.file.suffix", + EmbeddedStorageConfigurationPropertyNames.RESCUED_FILE_SUFFIX + ), + + /** + * Name of the lock file. Default is "used.lock". + */ + LOCK_FILE_NAME( + Constants.PREFIX + "lock.file.name", + EmbeddedStorageConfigurationPropertyNames.LOCK_FILE_NAME + ), + + /** + * Interval for the housekeeping. This is work like garbage collection or cache checking. In combination with + * houseKeepingNanoTimeBudget the maximum processor time for housekeeping work can be set. Default is 1 second. + */ + HOUSEKEEPING_INTERVAL( + Constants.PREFIX + "housekeeping.interval", + EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_INTERVAL + ), + + /** + * Number of nanoseconds used for each housekeeping cycle. Default is 10 milliseconds = 0.01 seconds. + */ + HOUSEKEEPING_TIME_BUDGET( + Constants.PREFIX + "housekeeping.time.budget", + EmbeddedStorageConfigurationPropertyNames.HOUSEKEEPING_TIME_BUDGET + ), + + /** + * Abstract threshold value for the lifetime of entities in the cache. Default is 1000000000. + */ + ENTITY_CACHE_THRESHOLD( + Constants.PREFIX + "entity.cache.threshold", + EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_THRESHOLD + ), + + /** + * Timeout in milliseconds for the entity cache evaluator. If an entity wasn't + * accessed in this timespan it will be removed from the cache. Default is 1 day. + */ + ENTITY_CACHE_TIMEOUT( + Constants.PREFIX + "entity.cache.timeout", + EmbeddedStorageConfigurationPropertyNames.ENTITY_CACHE_TIMEOUT + ), + + /** + * Minimum file size for a data file to avoid cleaning it up. Default is 1024^2 = 1 MiB. + */ + DATA_FILE_MINIMUM_SIZE( + Constants.PREFIX + "data.file.minimum.size", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_SIZE + ), + + /** + * Maximum file size for a data file to avoid cleaning it up. Default is 1024^2*8 = 8 MiB. + */ + DATA_FILE_MAXIMUM_SIZE( + Constants.PREFIX + "data.file.maximum.size", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MAXIMUM_SIZE + ), + + /** + * The ratio (value in ]0.0;1.0]) of non-gap data contained in a storage file to prevent the file from being + * dissolved. Default is 0.75 (75%). + */ + DATA_FILE_MINIMUM_USE_RATIO( + Constants.PREFIX + "data.file.minimum.use.ratio", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_MINIMUM_USE_RATIO + ), + + /** + * A flag defining whether the current head file (the only file actively written to) + * shall be subjected to file cleanups as well. + */ + DATA_FILE_CLEANUP_HEAD_FILE( + Constants.PREFIX + "data.file.cleanup.head.file", + EmbeddedStorageConfigurationPropertyNames.DATA_FILE_CLEANUP_HEAD_FILE + ); + + private final String microProfile; + private final String microStream; + + ConfigurationCoreProperties(final String microProfile, final String microStream) + { + this.microProfile = microProfile; + this.microStream = microStream; + } + + public String getMicroProfile() + { + return this.microProfile; + } + + /** + * Returns the corresponding MicroStream version of the config key. It replaces the MicroProfile part + * with the MicroStream part. So the keys can be 'longer' as the value defined in the enum. A typical + * example is the 'storage filesystem' element. + * @param key The Key as defined in MicroProfile config + * @return The corresponding MicroStream version of this key. + */ + public String getMicroStream(final String key) + { + return key.replaceAll(this.microProfile, this.microStream); + } + + /** + * Returns the {@code ConfigurationCoreProperties} enum entry that corresponds with the + * MicroProfile config key value. Optional.empty() when no matching entry is found. + * + * @param value The MicroProfile config key value to look for. + * @return The enum entry if there is a matching entry or {@code Optional.empty()} + */ + public static Optional get(final String value) + { + Objects.requireNonNull(value); + return Arrays.stream(ConfigurationCoreProperties.values()) + .filter(ccp -> value.startsWith(ccp.getMicroProfile())) + .findAny(); + } + + public static Map getProperties(final Config config) + { + final Map properties = new HashMap<>(); + + StreamSupport.stream(config.getPropertyNames() + .spliterator(), false) + .filter(n -> n.startsWith(Constants.PREFIX)) + .forEach(p -> addProperty(config, properties, p)); + + return properties; + } + + private static String asMicroStreamConfigName(final String name) + { + final Optional coreProperty = ConfigurationCoreProperties.get(name); + return coreProperty.isEmpty() + ? name.substring(Constants.PREFIX.length()) + : coreProperty.get() + .getMicroStream(name); + } + + private static void addProperty( + final Config config, + final Map properties, + final String configName + ) + { + config.getOptionalValue(configName, String.class) + .ifPresent(v -> properties.put(ConfigurationCoreProperties.asMicroStreamConfigName(configName), v)) + ; + } + + public static class Constants + { + public static final String PREFIX = "one.microstream."; + } +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ReflectionUtils.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ReflectionUtils.java new file mode 100644 index 000000000..3f3a2d897 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/ReflectionUtils.java @@ -0,0 +1,51 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public final class ReflectionUtils +{ + + private ReflectionUtils() + { + } + + public static List findFields(final Class clazz, final Predicate predicate) + { + + return findAllFields(clazz).stream() + .filter(predicate) + .collect(Collectors.toList()); + } + + public static List findAllFields(final Class clazz) + { + return Arrays.stream(clazz.getDeclaredFields()) + .filter(field -> !field.isSynthetic()) + .collect(Collectors.toList()); + } + +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/RootCreator.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/RootCreator.java new file mode 100644 index 000000000..4f9aa2844 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/RootCreator.java @@ -0,0 +1,101 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.arc.Arc; +import io.quarkus.arc.ArcContainer; +import io.quarkus.arc.BeanCreator; +import io.quarkus.arc.SyntheticCreationalContext; +import one.microstream.integrations.quarkus.types.config.StorageManagerInitializer; +import one.microstream.reflect.XReflect; +import one.microstream.storage.types.StorageManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.stream.Collectors; + +public class RootCreator implements BeanCreator { + + private static final Logger LOGGER = LoggerFactory.getLogger(RootCreator.class); + + @Override + public Object create(final SyntheticCreationalContext creationalContext) { + LOGGER.debug("Create Bean: Creating bean for MicroStream Root (@Storage annotated class)"); + + final ArcContainer container = Arc.container(); + + final StorageBean storageBean = container.instance(StorageBean.class) + .get(); + + LOGGER.info(String.format("Creation of the Root Bean from %s", storageBean.getInfo() + .getClassReference())); + + final StorageManager storageManager = container + .instance(StorageManager.class) + .get(); + Object root = storageManager.root(); + if (root == null) { + LOGGER.info("No root yet, creating new instance "); + root = XReflect.defaultInstantiate(storageBean.getInfo() + .getClassReference()); + + storageManager.setRoot(root); + storageManager.storeRoot(); + } + + injectDependencies(root, storageBean); + + LOGGER.debug("Executing StorageManagerInitializer beans"); + + final List initializers = container + .select(StorageManagerInitializer.class) + .stream() + .collect(Collectors.toList()); + for (final StorageManagerInitializer initializer : initializers) { + initializer.initialize(storageManager); + } + + return root; + + } + + private void injectDependencies(final Object root, final StorageBean storageBean) { + LOGGER.debug("Injecting instances in @Storage annotated instance"); + + final List fieldNamesToInject = storageBean.getInfo() + .getFieldsToInject(); + + final List fields = ReflectionUtils.findFields(root.getClass(), f -> fieldNamesToInject.contains(f.getName())); + final ArcContainer container = Arc.container(); + for (final Field field : fields) { + final Object injectable = container.select(field.getType()) + .get(); + try { + field.setAccessible(true); // package scope also must be made accessible. + field.set(root, injectable); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBean.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBean.java new file mode 100644 index 000000000..a106d2ace --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBean.java @@ -0,0 +1,39 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +public class StorageBean +{ + private final StorageClassInfo info; + + public StorageBean(final StorageClassInfo info) { + this.info = info; + } + + public boolean isDefined() { + return this.info.getClassReference() != null; + } + + public StorageClassInfo getInfo() + { + return this.info; + } +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBeanCreator.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBeanCreator.java new file mode 100644 index 000000000..602380419 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageBeanCreator.java @@ -0,0 +1,47 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import io.quarkus.arc.BeanCreator; +import io.quarkus.arc.SyntheticCreationalContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +public class StorageBeanCreator implements BeanCreator +{ + private static final Logger LOGGER = LoggerFactory.getLogger(StorageBeanCreator.class); + + @Override + public Object create(final SyntheticCreationalContext creationalContext) + { + LOGGER.debug("Create Bean: Creating bean with info about @Storage annotated class"); + + Map map = creationalContext.getParams(); + final StorageClassInfo storageClassInfo = new StorageClassInfo((Class) map.get(BeanCreatorParameterNames.CLASS_NAME) + , (String) map.get(BeanCreatorParameterNames.FIELDS)); + + return new StorageBean(storageClassInfo); + + } + +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageClassInfo.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageClassInfo.java new file mode 100644 index 000000000..e7d71362b --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageClassInfo.java @@ -0,0 +1,65 @@ +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import java.util.Arrays; +import java.util.List; + +/** + * Information about a class annotated with {@link one.microstream.integrations.quarkus.types.Storage}. + */ +public class StorageClassInfo +{ + + private final Class classReference; + + private final List fieldsToInject; + + public StorageClassInfo(final Class classReference, final List fieldsToInject) + { + + this.classReference = classReference; + this.fieldsToInject = fieldsToInject; + } + + public StorageClassInfo(final Class classReference, final String fieldsToInject) + { + if (classReference != Object.class) + { + this.classReference = classReference; + } else { + // Object.class past since .map entries on BeanCreator blow up when null is specified in value. + // see https://github.com/quarkusio/quarkus/issues/27664 + this.classReference = null; + } + this.fieldsToInject = Arrays.asList(fieldsToInject.split(",")); + } + + public Class getClassReference() + { + return classReference; + } + + public List getFieldsToInject() + { + return this.fieldsToInject; + } +} diff --git a/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageManagerProducer.java b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageManagerProducer.java new file mode 100644 index 000000000..fbc8f16c6 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/java/one/microstream/integrations/quarkus/types/impl/StorageManagerProducer.java @@ -0,0 +1,117 @@ + +package one.microstream.integrations.quarkus.types.impl; + +/*- + * #%L + * MicroStream Quarkus 3 Extension - Runtime + * %% + * Copyright (C) 2019 - 2023 MicroStream Software + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 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 + * #L% + */ + +import one.microstream.integrations.quarkus.types.config.EmbeddedStorageFoundationCustomizer; +import one.microstream.integrations.quarkus.types.config.StorageManagerInitializer; +import one.microstream.reflect.ClassLoaderProvider; +import one.microstream.storage.embedded.configuration.types.EmbeddedStorageConfigurationBuilder; +import one.microstream.storage.embedded.types.EmbeddedStorageFoundation; +import one.microstream.storage.embedded.types.EmbeddedStorageManager; +import one.microstream.storage.types.StorageManager; +import org.eclipse.microprofile.config.Config; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Disposes; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Inject; +import java.util.Map; + + +@ApplicationScoped +public class StorageManagerProducer { + private static final Logger LOGGER = LoggerFactory.getLogger(StorageManagerProducer.class); + + @Inject + Config config; + + @Inject + StorageBean storageBean; + + + @Inject + Instance customizers; + + @Inject + Instance initializers; + + @Produces + @ApplicationScoped + public StorageManager getStorageManager() { + + final Map properties = ConfigurationCoreProperties.getProperties(this.config); + LOGGER.info( + "Loading default StorageManager from MicroProfile Config properties. The keys: " + + properties.keySet() + ); + + final EmbeddedStorageConfigurationBuilder builder = EmbeddedStorageConfigurationBuilder.New(); + for (final Map.Entry entry : properties.entrySet()) { + builder.set(entry.getKey(), entry.getValue()); + } + final EmbeddedStorageFoundation foundation = builder.createEmbeddedStorageFoundation(); + foundation.setDataBaseName("Generic"); + + LOGGER.debug("Executing EmbeddedStorageFoundationCustomizer beans"); + + this.customizers.stream() + .forEach(customizer -> customizer.customize(foundation)); + + // Required when using Quarkus + foundation.onConnectionFoundation(cf -> cf.setClassLoaderProvider(ClassLoaderProvider.New( + Thread.currentThread() + .getContextClassLoader()))); + + + final EmbeddedStorageManager storageManager = foundation + .createEmbeddedStorageManager(); + + if (this.isAutoStart(properties)) { + LOGGER.debug("Start StorageManager"); + storageManager.start(); + } + + if (!this.storageBean.isDefined()) { + LOGGER.debug("Executing StorageManagerInitializer beans"); + // Only execute at this point when no storage root bean has defined with @Storage + // Initializers are called from StorageBeanCreator.create if user has defined @Storage. + this.initializers.stream() + .forEach(initializer -> initializer.initialize(storageManager)); + } + + return storageManager; + } + + + private boolean isAutoStart(final Map properties) { + return Boolean.parseBoolean(properties.getOrDefault("autoStart", "true")); + + } + + public void dispose(@Disposes final StorageManager manager) { + LOGGER.info("Closing the default StorageManager"); + manager.close(); + } +} diff --git a/integrations/quarkus3/runtime/src/main/resources/META-INF/beans.xml b/integrations/quarkus3/runtime/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000..1a9123a0c --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/resources/META-INF/beans.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/integrations/quarkus3/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/integrations/quarkus3/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 000000000..a1d542a89 --- /dev/null +++ b/integrations/quarkus3/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,8 @@ +name: MicroStream Quarkus 3 Extension +description: Integrate MicroStream within your application. +metadata: + keywords: + - MicroStream + guide: https://docs.microstream.one/manual/misc/integrations/quarkus.html + categories: + - "integration" \ No newline at end of file From c68ffe8046c399e169827b5bbb8868ce80c8b354 Mon Sep 17 00:00:00 2001 From: Rudy De Busscher Date: Fri, 12 May 2023 14:39:42 +0200 Subject: [PATCH 2/2] Docu fix for Quarkus 3.x integration. --- docs/modules/misc/pages/integrations/quarkus.adoc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/modules/misc/pages/integrations/quarkus.adoc b/docs/modules/misc/pages/integrations/quarkus.adoc index fcf9ee7f5..42590d3e9 100644 --- a/docs/modules/misc/pages/integrations/quarkus.adoc +++ b/docs/modules/misc/pages/integrations/quarkus.adoc @@ -13,9 +13,7 @@ mvn quarkus:add-extension -Dextensions="one.microstream:microstream-quarkus-exte The extension requires Quarkus 2.11.1 as a minimal version. -The integration requires Spring Boot 2.x (with version 2.1.0.RELEASE being the minimal supported one). - -If you are running Quarkus 3, use the following dependency in your project: +If you are running Quarkus 3, use the following command in your project: [source, shell, title="Add Quarkus 3 extension", subs=attributes+] ----