Giter Club home page Giter Club logo

eclipse-store / store Goto Github PK

View Code? Open in Web Editor NEW
152.0 9.0 13.0 3.68 MB

High-Performance Java-Native-Persistence. Store and load any Java Object Graph or Subgraphs partially, Relieved of Heavy-weight JPA. Microsecond Response Time. Ultra-High Throughput. Minimum of Latencies. Create Ultra-Fast In-Memory Database Applications & Microservices.

Home Page: https://eclipsestore.io/

License: Eclipse Public License 2.0

Java 99.91% CSS 0.09%
in-memory-database in-memory-storage java object-graph persistence storage-engine

store's Introduction

GitHub GitHub issues Maven Central

High-Performance Java-Native-Persistence

Store and load any Java Object Graph or Subgraphs partially, Relieved of Heavy-weight JPA. Microsecond Response Time. Ultra-High Throughput. Minimum of Latencies. Create Ultra-Fast In-Memory Database Applications & Microservices.

EclipseStore is based on the Eclipse Serializer.

License

EclipseStore is available under Eclipse Public License - v 2.0.

Documentation

Build

To build EclipseStore you need Java 11 and Maven.

Just run

mvn install

Contribute

If you want to contribute to this project, please read our guidelines.

Links

store's People

Contributors

bananeweizen avatar fh-ms avatar hg-ms avatar rdebusscher avatar zambrovski avatar zdenek-jonas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

store's Issues

Audit like Envers

Is your feature request related to a problem? Please describe.
The feature is not related to a big problem but would be easy to mark a object as Audited and watch the audit taken care of

Describe the solution you'd like
Envers provides a audit for database entities, can we work towards a solution like that?

Describe alternatives you've considered
Alternative, we create it custom

Additional context
No additional context

Read only mode

We’d like to provide an operation mode that rejects all store operations trigged by the public store API to prevent accidental changes to the persisted data by applications. It is not intended to prevent all write operations! Write operations by other (internal) APIs should still be possible.

  • The read only mode should prevent write operations triggered via the public storing API from the application code.
  • Write operations trigged during the startup (e.g.: Persisted Roots updates) are still possible.
  • Housekeeping tasks are still possible.
  • Garbage Collection task are still possible.
  • Importing (binary) data must be possible.
  • The read-only mode can be enabled/disabled at runtime (no restart of the storage!)

Provided Dependencies

We must put some of the used dependencies in the provided scope for legal reasons.

A proper description in the readme and pom files should be added.

Gcp Cloud storage storage target

Is there any example of a Storage target for GCP storage? From the documentation, I am not able to see the GCP storage.

I am using micronaut framework - it will be better if there are any references

Eclipse Store CDI Integration

The goal is to have an integration with the CDI framework for the EclipseStore, making it easy to use the technology in a Jakarta / Microprofile environment.

Based on an initial brief survey, CDI 4 Lite seems to be a suitable choice for integration. This should allow for easier implementation with frameworks like Quarkus in the future.

Versioning layer exception

Environment Details

  • EclipseStore Version: 1.31.
  • JDK version: 21.02
  • OS: MacOs Sonoma 14.3.1

Describe the bug

The documentation states that a versioning layer can be shared between all entities. Therefore, I coded this:

public interface EntityFactory {
    JulLogger logger = new JulLogger();
    EntityVersionContext<Long> versionContext =   EntityVersionContext.AutoIncrementingLong(EntityVersionCleaner.AmountPreserving(10));
    static <E extends Entity, C extends Entity.Creator<E, C>> C addLayers(final C creator) {
        return creator
                .addLayer(logger)
                .addLayer(versionContext);
    }
}

public interface Team extends WithId<UUID>, WithName, WithAudit, Entity {
    static TeamCreator creator() { return EntityFactory.addLayers(TeamCreator.New());}
   //...
}

public interface User extends WithHumanName, WithId<UUID>, WithElectronicAddress, WithAudit, Entity {
    static UserCreator creator() {return EntityFactory.addLayers(UserCreator.New());}
   //...
}

To Reproduce

Here is a JUnit test that fails:

//...
static <C extends Collection<E>,E> C add(C c,E e){  c.add(e);   return c;}
//...
@Test
    void testRoleAssignment() {

        var auditTrace1 = new WithAudit.Trace("me", Instant.now(), "192.168.0.0", "unknown");

        User user1 = User.creator()
                .id(UUID.randomUUID())
                .trace(auditTrace1)
                .firstName("John")
                .lastName("Smith")
                .create();

        Hotel hotel = Hotel.creator()
                .id(UUID.randomUUID())
                .trace(auditTrace1)
                .name("Hotel California")
                .beds(1)
                .stars(1)
                .rooms(2)
                .create();

        Team team1 = Team.creator()
                .id(UUID.randomUUID())
                .trace(auditTrace1)
                .name("team 1")
                .roleAssignments(add(new HashSet<>(),RoleAssignment.creator()
                        .id(UUID.randomUUID())
                        .trace(auditTrace1)
                        .role(Role.OWNER)
                        .user(user1)
                        .business(hotel)
                        .create()))
                .create();

Expected behavior

I expected the test to work, but it fails:

org.eclipse.serializer.entity.EntityExceptionMissingDataForVersion: Missing data for version '2' in tourbiz.datamodel.user._User.UserEntity@75334338
	at org.eclipse.serializer.entity.EntityLayerVersioning.entityData(EntityLayerVersioning.java:56)
	at org.eclipse.serializer.entity.Entity.data(Entity.java:59)
	at org.eclipse.serializer.entity.EntityLayer.entityData(EntityLayer.java:63)
	at tourbiz.datamodel.user._User.UserEntity.entityData(UserEntity.java:21)
	at tourbiz.datamodel.user._User.UserEntity.otherElectronicAddresses(UserEntity.java:27)

Additional context

If I do not share the versioning layer, I do not get exception:

public interface EntityFactory {
    JulLogger logger = new JulLogger();
    EntityVersionCleaner<Integer> cleaner = EntityVersionCleaner.AmountPreserving(10);
    static <E extends Entity, C extends Entity.Creator<E, C>> C addLayers(final C creator) {
        return creator.addLayer(logger).addLayer(EntityVersionContext.AutoIncrementingInt(cleaner));
    }
}

Rest Client GUI link is broken

The current link in the documentation for the REST client GUI is broken.
https://oss.sonatype.org/content/repositories/snapshots/org/eclipse/store/storage-restclient-app/1.3.1/storage-restclient-app-standalone-1.3.1.jar
on page:
https://docs.eclipsestore.io/manual/storage/rest-interface/client-gui.html

The maven dependency download also fails:

Couldn't download artifact: Could not find artifact org.eclipse.store:storage-restclient-app-standalone:jar:1.3.1 in central (https://repo1.maven.org/maven2)

Close file after deleting

When deleting a StorageFile its delete method ensures that the StorageFile is writable. The ensureWritable method internally opens a FileChannel if the NIO AFS is used. That FileChannel is not closed after deleting the file (in the app). The open file channel may prevent the OS from deleting the file and releasing disk space.

Spring Integration - Configuration and basic beans

In the first part, the goal is to map Spring configuration properties onto the Eclipse Store configuration.

Ultimately, there will be three options for bean insertion: Configuration, Foundation, and StorageManager.

It will also be possible to import various configurations using a prefix, allowing for multiple storage options within a single application.
It would be beneficial to follow the following principle. : https://www.baeldung.com/spring-boot-configure-multiple-datasources

--add-exports java.base/jdk.internal.misc=ALL-UNNAMED - please fix the docs!

Environment Details

  • EclipseStore Version: 1.3.1
  • JDK version: 21.0.2
  • OS: MacSO Sonoma 14.3.1

Describe the bug

The EclipseStore documentation says that in order to enable persistence for Java records, one need to run the JVM with:

--add-exports java.base/jdk.internal.misc=ALL-UNNAMED

That does not solve the issue in all cases, and I found out that when using fully modularized app, one needs to actually use:

--add-exports java.base/jdk.internal.misc=java.base/jdk.internal.misc=org.eclipse.serializer.base

So, you may want to document both options?

Additional context

If you read the Java 21 docs for Javac ALL-UNAMED works for unnamed/legacy jars only :

--add-exports module/package=other-module(,other-module)*

Specifies a package to be considered as exported from its defining module to additional modules or to all unnamed modules when the value of other-module is ALL-UNNAMED.

Handling checked exceptions

Consider using this (perfectly legit ) java hack :

public interface ExceptionUtils {

    /**
     * Rethrow an {@link java.lang.Throwable} preserving the stack trace but making it unchecked.
     *
     * @param exception to be re-thrown as unchecked.
     */
    static void rethrowUnchecked(final Throwable eexception{
        rethrow(exception);
    }

    @SuppressWarnings("unchecked")
    private static <T extends Throwable> void rethrow(final Throwable t) throws T {
        throw (T) t;
    }

}

This would remove the need for always having to wrap check exceptions such as IORuntimeException and possibly others, preserving a clean stack trace:

try {
    //...
}
catch(IOException e)  {
    // throw new IORuntimeException(e);
    ExceptionUtils.rethrowUnchecked(e);
}

ES 1.1.0 cashes the JVM with memory error

Environment Details

  • EclipseStore Version: 1.1.0
  • JDK version: java 21.0.2 2024-01-16 LTS
  • OS: MacOs Somoma 14.2.1 ARM64
  • Used frameworks: None

Describe the bug

Eclipse Store generates the below error and kills the JVM:

java(75228,0x16e98b000) malloc: double free for ptr 0x12d008200
java(75228,0x16e98b000) malloc: *** set a breakpoint in malloc_error_break to debug

With the code I have it happens always. There is no stack trace as the JVM crashes immediately.

To Reproduce

I may be able to provide code.

Expected behavior

I expect ES not to kill the JVM :-)

Screenshots

N/A

Additional context

Exactly the same issue exists in Microstream 08.01.01-MS-GA

Maybe unrelated, but since I use Java Records, I also noticed that I need to run with --add-exports java.base/jdk.internal.misc=ALL-UNNAMED java options.

Can you, please, put back the java module definitions?

Is your feature request related to a problem? Please describe.

When trying to integarte Eclipse Store 1.1.0 in Helidon 4, the lack of proper Java 9 module definitions (module-info.java) generates compiler warnings from automatic module assumptions, based on jar names, etc.

Describe the solution you'd like

Put back module definitions (that were removed for some reason). Or, as a temporary solution, add Automatic-Module-Name: to jar's manifests.

Describe alternatives you've considered

I ma currently trying to suppress a lot fo the warnings as part of the Eclipse Sore integration with Helidon

Additional context

I think these module definitions were in MicroStream at asome point, not sure why they were removed?

Provide a SBOM

Is your feature request related to a problem? Please describe.

The creation of SBOMs is expected to be something that will be common practice, or sometimes even mandatory, when you deliver software. The US already has an "Executive Order on Improving the Nation’s Cybersecurity" with the SBOM requirement:
https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/ See Sec 4.E.vii

Describe the solution you'd like

Create a SBOM for every build of Eclipse Store. Brian Vermeer has a good article about this topic: https://snyk.io/blog/create-sboms-java-maven-gradle/

Describe alternatives you've considered

Having no SBOM ;)

Additional context

What is an SBOM?
A software bill of materials, often abbreviated as SBOM, is a list of all software components used in an application. The SBOM is made up of third-party open-source libraries, vendor-provided packages, and first-party artifacts built by the organization. You can see it as the full list of ingredients for your applications.

But be careful not to confuse an SBOM with Maven’s Bill Of Materials (BOM).

An SBOM is something you create next to your application so that any user or client has a uniform way to find out what your application is using under the hood.

Move to Java 11

As discussed, we will update to Java 11 as a minimum requirement.
Within this step, we can build true JMS compatible modules without Maven hackery.

IndexOutOfBoundsException when using values().stream() on empty LazyHashMap

Environment Details

  • EclipseStore Version: 1.2.0
  • JDK version: 21.0.1
  • OS: Win 10
  • Used frameworks: -

Describe the bug

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
	at java.base/java.util.Objects.checkIndex(Objects.java:385)
	at org.eclipse.serializer.collections.lazy.LazyHashMap.calculateIndexPosition(LazyHashMap.java:545)
	at org.eclipse.serializer.collections.lazy.LazyHashMap$SegmentsSpliterator.<init>(LazyHashMap.java:1388)
	at org.eclipse.serializer.collections.lazy.LazyHashMap$ValueSpliterator.<init>(LazyHashMap.java:1654)
	at org.eclipse.serializer.collections.lazy.LazyHashMap$Values.spliterator(LazyHashMap.java:1170)
	at java.base/java.util.Collection.stream(Collection.java:750)
	at org.eclipse.serializer.collections.lazy.LazyCollection.stream(LazyCollection.java:75)

To Reproduce

new LazyHashMap<String, String>().values().stream().toList();

Expected behavior

No Exception, just an empty List as result.

Issue with generated layered entity code - may need documentation?

Environment Details

  • EclipseStore Version: 1.3.1
  • JDK version: 21.0.2
  • OS: MacOs Sonoma

Describe the bug

This is not really a bug, but rather a suggestion to add documentation.

In a fully modularized application, when the embedded storage manager attempts to persist entities, it fails with:

java.lang.reflect.InaccessibleObjectException: Unable to make protected datamodel.product._Product.ProductEntity() accessible: module datamodel does not "opens datamodel.product._Product" to module org.eclipse.serializer.persistence.binary
	at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
	at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Constructor.java:194)
	at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:187)
	at org.eclipse.serializer.persistence.binary@1.3.1/org.eclipse.serializer.persistence.binary.org.eclipse.serializer.entity.BinaryHandlerEntityLayerIdentity.WrapDefaultConstructor(BinaryHandlerEntityLayerIdentity.java:61)
	at org.eclipse.serializer.persistence.binary@1.3.1/org.eclipse.serializer.persistence.binary.org.eclipse.serializer.entity.BinaryHandlerEntityLayerIdentity.New(BinaryHandlerEntityLayerIdentity.java:50)
	at org.eclipse.serializer.persistence.binary@1.3.1/org.eclipse.serializer.persistence.binary.types.BinaryTypeHandlerCreator$Default.createEntityLayerIdentityHandler(BinaryTypeHandlerCreator.java:368)
	at org.eclipse.serializer.persistence.binary@1.3.1/org.eclipse.serializer.persistence.binary.types.BinaryTypeHandlerCreator$Default.internalCreateTypeHandlerEntity(BinaryTypeHandlerCreator.java:351)

Additional context

This is fixed by declaring the entity module "open" (also notice that the generated packages like _Product would need to be exported as well):

open module datamodel {
    //...
    exports datamodel.product._Product;
}

Foundation type handler registration depends on order of api calls

Discussed in #203

Originally posted by hrstoyanov April 16, 2024
Hello,
I register a TsidHandler into ES:

return EmbeddedStorageFoundation.New()
                .setConfiguration(StorageConfiguration.Builder()
                        .setStorageFileProvider(storageLiveFileProvider)
                        .setChannelCountProvider(StorageChannelCountProvider.New(channelCount))
                        .setBackupSetup(storageBackupSetup)
                        .createConfiguration())
                .onConnectionFoundation(BinaryHandlersJDK8::registerJDK8TypeHandlers)
                .onConnectionFoundation(BinaryHandlersJDK17::registerJDK17TypeHandlers)
                .onConnectionFoundation(f -> f.registerCustomTypeHandler(new TsidHandler())) // THIS ONE!
                .createEmbeddedStorageManager();

TSID (time sorted ids) is an economical and convenient 64-bit replacement for Java 128-bit UUIDs , which I would like ES to store as/convert to long values. However, when I put break points in the handler code below, none of the handler's methods get triggered (except the constructor). Why is ES ignoring my binary TsidHandler - what am I doing wrong?

public class TsidHandler extends AbstractBinaryHandlerCustomValueFixedLength<Tsid, Long> {

    public TsidHandler() {
        super(Tsid.class, defineValueType(long.class));
    }

    private static long instanceState(final Tsid instance)
    {
        return instance.toLong();
    }

    private static long binaryState(final Binary data)
    {
        return data.read_long(0);
    }

    @Override
    public void store(Binary data, Tsid instance, long objectId, PersistenceStoreHandler<Binary> handler) {
        data.storeLong(this.typeId(), objectId, instance.toLong());
    }

    @Override
    public Tsid create(final Binary data, final PersistenceLoadHandler handler) {
        return Tsid.from(data.read_long(0));
    }


    /** actually never called, just to satisfy the interface */
    @Override
    public Long getValidationStateFromInstance(final Tsid instance) {
        return instance.toLong();
    }

    /** actually never called, just to satisfy the interface */
    @Override
    public Long getValidationStateFromBinary(final Binary data) {
        return binaryState(data);
    }

    @Override
    public void validateState(Binary data, Tsid instance, PersistenceLoadHandler handler) {
        long instanceState = instanceState(instance);
        long binaryState   = binaryState(data);
        if(instanceState == binaryState) return;
        throwInconsistentStateException(instance, instanceState, binaryState);
    }

}
```</div>

Improve inaccuracies in SpringBoot3 integration

Environment Details

  • EclipseStore Version: 1.1.0
  • JDK version: OpenJDK 17
  • OS: Ubuntu 22.04
  • Used frameworks: Spring Boot 3.1.x

Describe the bug

There are some inaccuracies in Spring configuration which can be easily fixed. The provided integration works, but is little surprising.

Here are some:

  1. EclipseStoreSpringBoot should either be a @Configuraiton (= is manually included into config using an @Import annotation) or @AutoConfiguration (= be referenced in a org.springframework.boot.autoconfigure.AutoConfiguration.imports file). Currently, the class is annotated by @AutoConfiguration and the docs says so, but the spring-factory descriptor is missing requiring the @Import

  2. EclipseStoreProperties is a properties holding class. Usually it is a POJO (not @configuration, not a @component, not a Bean with a lifecycle, but is automatically provided by the IoC Spring container if initialized). Try to avoid declaration of beans with @Primary in a framework, since there is no way to overwrite the primary and you steal the user of your framework to overwrite your choice - in this particular case, @Primary has probably no effect at all.

  3. Please provide senceful JavaDoc for the properties fields because these get collected into SpringBoot Metadata and are available for the users (by most IDEs) on creation of properties in the yaml or properties files.

  4. EclipseStoreBeanFactory is marked itself as @Lazy and creates the EmbeddedStorageManager as a primary and lazy bean. As a framework/libarary provider try to make your configuration linear and simple. Both primary (preference of usage) and lazy (initialization via proxy resolved only at invocation time) are limiting usage and potentially lead to strange behaviour. Why is it needed at all?

  5. EmbeddedStorageManager is a Bean with a lifecycle (start(), shutdown()). I would expect the bean factory initializing it, to define the init method and destroy method pointing to those lifecycle methods. I understand that this is done imperative in the StorageManagerProviderImpl but this is indeed the impeorative Java way and not SpringBoot way. In spring boot your would provide several beans depending on properties and let container call autostart. I believe the shutdown is not called and left over to the user - not sure if this is critical, but can be avoided easily...

Expected behavior

  • use standard ways of Component configuration in SpringBoot
  • use AutoConfiguration

If you are interested in feedback and improvements of this kind, I could provide a PR with changes and we can continue discussion on code basis.

Cheers,

Simon

Improve query documentation

Hi, I'm reading the documentation, just learning about MicroStream/EclipseStore, and the part that I'm mostly interested is querying capabilities. In the documentation and online video presentations there is no much info about querying. Would it be possible to demonstrate (have more tutorials available) and improve the docs on the querying area?

With this I mean querying options, alternatives, parameters, querying on complex/hierarchical objects, etc, etc.

What I'm trying to understand is how querying with MS/ES compares with a RDBMS with ORM and which is better in different scenarios.

Thanks!

Concept: Create an audit log form

In short, it is about creating an audit log that would log the complete history of creating and changing Java objects in the Eclipse Store to some location on the disk. Including housekeeping operations.

A log of all consecutive actions can be created, including binary data (configurable), so that in the future, in case of any doubt, it can be traced back to what happened with the data when.

This log can subsequently serve as a form of backup, from which it may be possible to recreate the entire storage in case of data loss.

This issue is created for the purpose of analysis, collection of requirements for the final decision on possible implementation.

Get objects that will be peristed

thanks @hg-ms
do you think it might be of interest for you guys to incorporate some sort of a listener API for this inside the code?
I am thinking about potential use cases like outbox pattern, Change Data Capture integration etc...
this would be beneficial I think...

Originally posted by @guykatz in #134 (reply in thread)

Storage Channel Configuration and related error

Discussed in #71

Originally posted by DhinchakDhoomDev November 29, 2023

Q1 : I am using a FileNameProvider and Directory to save those entry in specific directories but after restarting the application I am getting error as : "Non-deleted non-empty data file not found: channel 1, file 1"
Source code is as follows :

            StorageFileNameProvider fileNameProvider = StorageFileNameProvider.Builder()
                    .setChannelDirectoryPrefix("channel_")
                    .setDataFilePrefix("data_")
                    .setDataFileSuffix(".databin")
                    .setTransactionsFilePrefix("events_")
                    .setTransactionsFileSuffix(".trbin")
                    .setTypeDictionaryFileName("typeDictionary.txt")
                    .createFileNameProvider();

            NioFileSystem fileSystem = NioFileSystem.New();
            StorageLiveFileProvider fileProvider = Storage
                    .FileProviderBuilder(fileSystem)
                    .setDirectory(fileSystem.ensureDirectoryPath("./saveDir"))
                    .setDeletionDirectory(fileSystem.ensureDirectoryPath("./deleteDir"))
                    .setTruncationDirectory(fileSystem.ensureDirectoryPath("./truncateDir"))
                    .setFileNameProvider(fileNameProvider)
                    .createFileProvider();
            EmbeddedStorageManager storage = EmbeddedStorage.Foundation(
                            Storage.ConfigurationBuilder()
                                    .setChannelCountProvider(Storage.ChannelCountProvider(2))
                                    .setStorageFileProvider(fileProvider)
                                    .createConfiguration()
                    )
                    .start();

I am using example from the following DOCS link

Q2 : There was a feature in Microstream Read-Only Storage Manager

Referenced from the following link :
https://docs.microstream.one/manual/storage/configuration/readonly.html

Spring integration lazy loading don't stream data when restarting application

Environment Details

  • EclipseStore Version: 1.2.0
  • JDK version: 17
  • OS: Windows
  • Used frameworks: e.g. Spring boot 3.2.2

Describe the bug

I am testing out eclipsestore and got it working with List in a root object. Upon trying to change it to Lazy it updates the data when the instance is still live but upon restarting my root is empty. Due to this issue I don't know If the data is really being saved or the lazy is not initialized properly

State if the problem is easily reproducible or happens intermittently.

Include stack traces or command outputs

To Reproduce

Step by step instructions to reproduce the problem.
Step one create root

import org.eclipse.serializer.reference.Lazy;
import sr.we.shekelflowcore.entity.eclipsestore.tables.Store;
import sr.we.shekelflowcore.entity.eclipsestore.tables.SuperDao;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Eclipse store root object
 */
public class Root {
    /**
     * Trying to simply mimic database tables, every field here would be a Lazy List
     */
    @Table(Store.class)
    private Lazy<List<Store>> stores = Lazy.Reference(new ArrayList<>());

    /**
     * This gets the list of data within the lazy field
     * @param c
     * @return
     * @param <T>
     */
    public <T extends SuperDao> List<T> getListByClass(Class<? extends SuperDao> c) {
        Lazy lazyByClass = getLazyByClass(c);
        if(lazyByClass != null){
            return (List<T>) lazyByClass.get();
        }
        return null;
    }

    /**
     * This gets the lazy field by the provided class
     * @param c
     * @return
     * @param <T>
     */
    public <T extends SuperDao> Lazy getLazyByClass(Class<? extends SuperDao> c) {
        if (c != null) {
            for (Field field : Root.class.getDeclaredFields()) {
                if (field.isAnnotationPresent(Table.class)) {
                    Table annotation = field.getAnnotation(Table.class);
                    if(annotation.value().equals(c)) {
                        try {
                            Lazy reference = (Lazy) field.get(this);
                            List<T> o = (List<T>) Lazy.get(stores);
                            if(o == null){
                                reference = (Lazy) Lazy.Reference(new ArrayList<>());
                                field.set(this, reference);
                                return (Lazy)field.get(this);
                            }
                            return reference;
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
        return null;
    }
}

Step two create methods to add and read data

public abstract class EclipseStoreSuperService<T extends SuperDao> {

    protected final EmbeddedStorageManager storageManager;
    Class<T> typeParameterClass;

    public EclipseStoreSuperService(EmbeddedStorageManager storageManager, Class<T> typeParameterClass) {
        this.storageManager = storageManager;
        this.typeParameterClass = typeParameterClass;
    }


    public T get(String uuId) {

        Root root = (Root) storageManager.root();
        List<T> list = root.getListByClass(typeParameterClass);
        Optional<T> any = list.stream().filter(f -> f.getUuId().equalsIgnoreCase(uuId)).findAny();
        return any.orElse(null);
    }


    public Stream<T> stream() {
        Root root = (Root) storageManager.root();
        List<T> list = root.getListByClass(typeParameterClass);
        return list.stream();
    }


    public T update(T dao, InterExecutable<T, T> update) {
        Root root = (Root) storageManager.root();
        List<T> list = root.getListByClass(typeParameterClass);

        if (StringUtils.isNotBlank(dao.getUuId())) {
            T daoExist = get(dao.getUuId());
            if (update != null && daoExist != null) {
                update.build(daoExist);// this method is provided to update the existed instance
                daoExist.setUuId(dao.getUuId());// to prevent people from overriding the UUID
            } else {
                return null;
            }
        } else {
            dao.setUuId(UUID.randomUUID().toString());// if new we will add to the list
            list.add(dao);
        }
        Lazy listByClass = root.getLazyByClass(typeParameterClass);
        storageManager.store(listByClass);

        return get(dao.getUuId());
    }


    public boolean delete(String uuId) {
        Root root = (Root) storageManager.root();
        T dao = get(uuId);
        boolean remove = root.getListByClass(typeParameterClass).remove(dao);
        storageManager.store(root.getLazyByClass(typeParameterClass));
        return remove;
    }


}

Step three this is the Store Object

import java.time.LocalDateTime;

import static java.util.Objects.requireNonNull;

/**
 * This store represents a business store and is saved in the eclipsestore database
 * As of now in the testing phase, the eclipsestore database does not provide any Audit.
 *
 * The goal here is to create as many stores as one wants and link the loyverse created items with a store.
 * This will then give back an opportunity to create daily dashboard for different store owners
 */
public class Store extends SuperDao {
    /**
     * This ID will be used to connect the store to the Particular business
     */
    Long businessId;
    /**
     * The ID is used to connect the store record to a particular loyverse registered store
     */
    String id;
    /**
     * Given name
     */
    String name;
    /**
     * Misc
     */
    String address;
    /**
     * Misc
     */
    String city;
    /**
     * Misc
     */
    String region;
    /**
     * Misc
     */
    String postalCode;
    /**
     * Misc
     */
    String countryCode;
    /**
     * Misc
     */
    String phoneNumber;
    /**
     * Misc
     */
    String description;
    /**
     * Little time audit
     */
    LocalDateTime createdAt;
    /**
     * Little time audit
     */
    LocalDateTime updatedAtt;
    /**
     * Little time audit, TODO: WE MIGHT NOT ADD SOFT DELETE
     */
    LocalDateTime deletedAt;

    public Store() {
    }

    public Store(Long businessId, String id, String name) {
        this.businessId = businessId;
        this.id = id;
        this.name = name;
        requireNonNull(this.name, "Store name cannot be null");
        requireNonNull(this.businessId, "Store parent business cannot be null");
        this.createdAt = LocalDateTime.now();
        this.updatedAtt = this.createdAt;
        this.deletedAt = null;
    }

    public Long getBusinessId() {
        return businessId;
    }

    public void setBusinessId(Long businessId) {
        this.businessId = businessId;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getRegion() {
        return region;
    }

    public void setRegion(String region) {
        this.region = region;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    public LocalDateTime getUpdatedAtt() {
        return updatedAtt;
    }

    public void setUpdatedAtt(LocalDateTime updatedAtt) {
        this.updatedAtt = updatedAtt;
    }

    public LocalDateTime getDeletedAt() {
        return deletedAt;
    }

    public void setDeletedAt(LocalDateTime deletedAt) {
        this.deletedAt = deletedAt;
    }

    @Override
    public String toString() {
        return "Store{" +
                "businessId=" + businessId +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", city='" + city + '\'' +
                ", region='" + region + '\'' +
                ", postalCode='" + postalCode + '\'' +
                ", countryCode='" + countryCode + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                ", description='" + description + '\'' +
                ", createdAt=" + createdAt +
                ", updatedAtt=" + updatedAtt +
                ", deletedAt=" + deletedAt +
                '}';
    }
}

Step 4 create store component to handle data saving

@Component
public class StoreStorage extends EclipseStoreSuperService<Store> implements IStoreStorage {

    public StoreStorage(EmbeddedStorageManager storageManager) {
        super(storageManager, Store.class);
    }

    @Override
    @Read
    public Store oneStore(String uuId) {
        return get(uuId);
    }

    @Override
    @Read
    public List<Store> allStores(Long businessId) {
        return stream().filter(store -> store.getBusinessId() != null && store.getBusinessId().compareTo(businessId) == 0).toList();
    }

    @Override
    @Write
    public Store saveOrUpdate(Store store) {
        return update(store, f -> {
            f.setAddress(store.getAddress());
            f.setCity(store.getCity());
            f.setBusinessId(store.getBusinessId());
            f.setDescription(store.getDescription());
            f.setCountryCode(store.getCountryCode());
            f.setId(store.getId());
            f.setName(store.getName());
            f.setPhoneNumber(store.getPhoneNumber());
            f.setRegion(store.getRegion());
            f.setPostalCode(store.getPostalCode());
            return f;
        });
    }

    @Override
    @Write
    public boolean deleteStore(String uuId) {
        return delete(uuId);
    }
}

Step five create test class

import org.eclipse.store.integrations.spring.boot.types.EclipseStoreSpringBoot;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import sr.we.shekelflowcore.entity.eclipsestore.tables.Store;
import sr.we.shekelflowservice.crud.store.impl.StoreStorage;

import java.util.List;

@SpringBootTest(classes = {EclipseStoreSpringBoot.class, StoreStorage.class, StoreTest.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class StoreTest {


    @Autowired
    private StoreStorage storage;

    @Order(1)
    @Test
    public void addNewStoreWithValidParametersPass() {
        Store store = storage.saveOrUpdate(new Store(5L,null, "Test"));
        Assertions.assertNotNull(store.getUuId());
    }


    @Order(3)
    @Test
    public void retrieveAllStorePass() {
        List<Store> stores = storage.allStores(5L);
        Assertions.assertNotNull(stores);
        Assertions.assertFalse(stores.isEmpty());
    }



}

Step 6
First only test the whole class
Step 7
Second test the methods seperately

Also this is my properties file

org.eclipse.store.storage-directory=/data/prod
org.eclipse.store.auto-start=true
org.eclipse.store.root=sr.we.shekelflowcore.entity.eclipsestore.Root
org.eclipse.store.channel-count=2
logging.level.org.eclipse.store=debug

Expected behavior

I Expect the data to be saved and to be accessible when restarting (This was the case with using List)

Screenshots

Additional context

Might be doing something wrong, hope you can clarify for me.

HelloWorld example

First of all thanks a lot for this great project and the great work you put into it!

I looked into the Getting Started section of the documentation and followed the link at the end of the page:

The full code for the Hello World example is on GitHub.

In my opinion - for a hello world - it is too complicated to execute the example and simply get started. I cannot find instructions how to actually run only the hello world example. How is it meant to run ?

Here is what I did:

tron$ pwd
/home/rpx/Downloads
tron$ git clone https://github.com/eclipse-store/store.git
tron$ cd store/examples/helloworld

Extended the pom.xml file like so:

`

<modelVersion>4.0.0</modelVersion>

<parent>
	<groupId>org.eclipse.store</groupId>
	<artifactId>examples-parent</artifactId>
	<version>1.2.0-SNAPSHOT</version>
	<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>examples-helloworld</artifactId>

<name>EclipseStore Example Hello World</name>
<description>EclipseStore Hello World Example</description>
<url>https://projects.eclipse.org/projects/technology.store</url>

<dependencies>
	<dependency>
		<groupId>org.eclipse.store</groupId>
		<artifactId>storage-embedded</artifactId>
		<version>1.2.0-SNAPSHOT</version>
	</dependency>
	<dependency>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-compiler-plugin</artifactId>
		<version>3.12.1</version>
	</dependency>
	<dependency>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-assembly-plugin</artifactId>
		<version>3.6.0</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-simple</artifactId>
		<version>2.0.9</version>
		<scope>runtime</scope>
	</dependency>

</dependencies>

<build>
	<plugins>
		<plugin>
			<artifactId>maven-assembly-plugin</artifactId>
			<configuration>
				<archive>
					<manifest>
						<mainClass>org.eclipse.store.examples.helloworld.HelloWorld</mainClass>
					</manifest>
				</archive>
				<descriptorRefs>
					<descriptorRef>jar-with-dependencies</descriptorRef>
				</descriptorRefs>
			</configuration>
			<executions>
				<execution>
					<id>make-assembly</id>
					<phase>package</phase>
					<goals>
						<goal>single</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jar-plugin</artifactId>
			<version>3.3.0</version>
			<configuration>
				<archive>
					<manifest>
						<mainClass>org.eclipse.store.examples.helloworld.HelloWorld</mainClass>
					</manifest>
				</archive>
			</configuration>
		</plugin>
	</plugins>
</build>

`

tron$ mvn clean install

Ran the program:

tron$ java -jar target/examples-helloworld-1.2.0-SNAPSHOT-jar-with-dependencies.jar

[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation - Creating embedded storage manager
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Type dictionary is empty or not existing. Initializing type handler manager with a new default type dictionary
[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageManager - Starting embedded storage manager
[main] INFO org.eclipse.store.storage.types.StorageSystem - Starting storage system
[main] INFO org.eclipse.store.storage.types.StorageStructureValidator - Storage structure validated successfully.
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager
[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageManager - Embedded storage manager initialized
Root: null
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager

tron$ java -jar target/examples-helloworld-1.2.0-SNAPSHOT-jar-with-dependencies.jar

[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation - Creating embedded storage manager
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager
[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageManager - Starting embedded storage manager
[main] INFO org.eclipse.store.storage.types.StorageSystem - Starting storage system
[main] INFO org.eclipse.store.storage.types.StorageStructureValidator - Storage structure validated successfully.
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager
[main] INFO org.eclipse.store.storage.embedded.types.EmbeddedStorageManager - Embedded storage manager initialized
Root: Hello World! @ Tue Feb 06 10:27:05 CET 2024
[main] INFO org.eclipse.serializer.persistence.types.PersistenceTypeHandlerManager - Initializing type handler manager

Thank you.

Spring Boot Integration Tests need @DirtiesContext

Environment Details

  • EclipseStore Version: 1.2.0
  • JDK version: termurin-17.0.10
  • OS: Windows
  • Used frameworks: Spring Boot

Describe the bug

A clear and concise description of what the bug is.

I use the Spring Boot Configuration with @import(EclipseStoreSpringBoot.class)

when I run my Integration Tests with EclipseStore need the @DirtiesContext annotation to work properly when mixed with other Integration Tests, as it tries to recreate the embeddedStorage Manager instead of reusing the on already available in the context.

Failed to instantiate [org.eclipse.store.storage.embedded.types.EmbeddedStorageManager]: Factory method 'embeddedStorageManager' threw exception with message: Active storage for org.eclipse.store.storage.types.Database$Default@7ab9ef6c "Eclipse Serializer@storage" already exists.

I think this issue can be solved by looking for an already active embeddedStorageManager in: org.eclipse.store.integrations.spring.boot.types.EclipseStoreBeanFactory#embeddedStorageManager

To Reproduce

Create mupltiple @SpringBootTest IntegrationTest with EclipseStore

Expected behavior

EmbeddedStorageManager should be reused .

EclipseStore Rest Client (Vaadin) App should be separated in the application module and assembly

Is your feature request related to a problem?

If running in a SpringBoot environment, it would be handy to have the client app (today running as a separate app using SpringBoot 3 and Vaadin) included in the main app. Today, the rest client app is both: a Vaadin application module and the Spring Boot 3 application (including the repackaging for running as a self-contained executable FAT jar.

Describe the solution you'd like

I would like to have two separated artifacts: the Vaadin app and the SpringBoot assembly starting it. This would allow to use the Vaadin app in other contexts (as a part of the main spring boot application) and in other configuration (e.g. not bound to "/", but bound to "/store-console", bound not to default HTTP port, but management port, etc...).

Describe alternatives you've considered

Currently the JAR of the rest-client app is a SpringBoot Fat JAR, and no "thin" JAR is available in maven central (the repackage step of the build replaces the original JAR). It would be also possible to produce two JARS, even if this is not the best solution and I would rather propose to have the restclient-app as an a client JAR and restclient-app-standalone as a SpringBoot module using the app and configuring it to run as a standalone app only.

Improve behavior if PersistenceTypeDictionary.ptd is missing

Trying to load an existing storage with a missing PersistenceTypeDictionary.ptd causes an unclear exception.
Maybe the exception could be improved or the storage initialization could handle the case that storage files already exists but the PersistenceTypeDictionary is missing.

SpringBoot3 integration should offer a REST service for EclipseStore

Is your feature request related to a problem? Please describe.

In a context of SpringBoot3 it is not possible (and probably not desired) to start a REST service via SprarkJava. Thus the REST service is not available.

Describe the solution you'd like

Utilize SpringBoot 3.x Web MVC framework to provide a REST service for debugging and information provision about the Eclipse Store.

Describe alternatives you've considered

Since SpringBoot 3.x provides the entire REST stack, why should we not use this?

Additional context

I could provide an implementation, if you would accept a PR.

o.e.s.storage.types.StorageChannelTask : Error occurred in storage channel#0org.eclipse.store.storage.exceptions.StorageExceptionIoWriting: Physical length 3047424 of current head file 146 is not equal its expected length of 3047612

Environment Details

  • EclipseStore Version: 1.0.0

  • JDK version: /eclipse_adoptium-21-amd64-linux/jdk-21.0.1+12

  • OS:
    os.arch = amd64
    os.name = Linux
    os.version = 6.1.61-85.141.amzn2023.x86_64

  • Used frameworks: None.

Describe the bug

Exception occur while storing data.

o.e.s.storage.types.StorageChannelTask : Error occurred in storage channel#0org.eclipse.store.storage.exceptions.StorageExceptionIoWriting: Physical length 3047424 of current head file 146 is not equal its expected length of 3047612

And another one with the same use case.

2023-12-14 15:16:54.791 ERROR   --- [torageChannel-0]  o.e.store.storage.types.StorageChannel   : StorageChannel#0 encountered disrupting exceptionorg.eclipse.store.storage.exceptions.StorageExceptionGarbageCollector: Exception in channel #0
        at org.eclipse.store.storage.types.StorageEntityCache$Default.incrementalGarbageCollection(StorageEntityCache.java:1451) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.performGarbageCollection(StorageChannel.java:314) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageHousekeepingBroker$Default.performGarbageCollection(StorageHousekeepingBroker.java:118) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeepingGarbageCollection(StorageChannel.java:376) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeeping(StorageChannel.java:238) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.work(StorageChannel.java:429) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.run(StorageChannel.java:486) [storage-1.0.0.jar]
        at java.lang.Thread.run(Thread.java:1583)
Caused by: org.eclipse.store.storage.exceptions.StorageExceptionIoReading
        at org.eclipse.store.storage.types.StorageFile$Abstract.readBytes(StorageFile.java:163) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageFileManager$Default.loadData(StorageFileManager.java:643) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageLiveDataFile$Default.loadEntityData(StorageLiveDataFile.java:372) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.internalLoadData(StorageEntity.java:397) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.loadData(StorageEntity.java:392) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.ensureCachedReferenceData(StorageEntity.java:364) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.iterateReferenceIds(StorageEntity.java:528) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.incrementalMark(StorageEntityCache.java:904) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.internalIncrementalGarbageCollection(StorageEntityCache.java:1502) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.incrementalGarbageCollection(StorageEntityCache.java:1447) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.performGarbageCollection(StorageChannel.java:314) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageHousekeepingBroker$Default.performGarbageCollection(StorageHousekeepingBroker.java:118) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeepingGarbageCollection(StorageChannel.java:376) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeeping(StorageChannel.java:238) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.work(StorageChannel.java:429) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.run(StorageChannel.java:486) [storage-1.0.0.jar]
        at java.lang.Thread.run(Thread.java:1583)
Caused by: org.eclipse.serializer.exceptions.IndexBoundsException: Index out of bounds: 8063955 not in [0;8062879[ (StartIndex >= bound)
        at org.eclipse.serializer.io.XIO.internalRead(XIO.java:1230) [base-1.0.0.jar]
        at org.eclipse.serializer.io.XIO.read(XIO.java:1208) [base-1.0.0.jar]
        at org.eclipse.store.afs.nio.types.NioIoHandler$Default.specificReadBytes(NioIoHandler.java:431) [afs-nio-1.0.0.jar]
        at org.eclipse.store.afs.nio.types.NioIoHandler$Default.specificReadBytes(NioIoHandler.java:81) [afs-nio-1.0.0.jar]
        at org.eclipse.serializer.afs.types.AIoHandler$Abstract.readBytes(AIoHandler.java:777) [afs-1.0.0.jar]
        at org.eclipse.serializer.afs.types.AReadableFile.readBytes(AReadableFile.java:98) [afs-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageFile$Abstract.readBytes(StorageFile.java:159) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageFileManager$Default.loadData(StorageFileManager.java:643) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageLiveDataFile$Default.loadEntityData(StorageLiveDataFile.java:372) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.internalLoadData(StorageEntity.java:397) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.loadData(StorageEntity.java:392) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.ensureCachedReferenceData(StorageEntity.java:364) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntity$Default.iterateReferenceIds(StorageEntity.java:528) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.incrementalMark(StorageEntityCache.java:904) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.internalIncrementalGarbageCollection(StorageEntityCache.java:1502) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageEntityCache$Default.incrementalGarbageCollection(StorageEntityCache.java:1447) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.performGarbageCollection(StorageChannel.java:314) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageHousekeepingBroker$Default.performGarbageCollection(StorageHousekeepingBroker.java:118) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeepingGarbageCollection(StorageChannel.java:376) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.houseKeeping(StorageChannel.java:238) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.work(StorageChannel.java:429) [storage-1.0.0.jar]
        at org.eclipse.store.storage.types.StorageChannel$Default.run(StorageChannel.java:486) [storage-1.0.0.jar]
        at java.lang.Thread.run(Thread.java:1583)

To Reproduce

Here are relevant snippets.

void doIt {
     try (EmbeddedStorageManager storageManager = EmbeddedStorage.start(Paths.get(dataDirectory))) {
            PerfData root = getRoot(storageManager);
            var userData = root.getUsers();
            Stopwatch stopwatch = Stopwatch.createStarted();
            for (int userIndex = 0; userIndex < USER_COUNT; userIndex++) {
                completionService.submit(this::createUser);
            }
            log.info(
                    "Submitted all {} tasks to the executor, waiting for generation of all users",
                    USER_COUNT);
            AtomicInteger atomicInteger = new AtomicInteger();
            for (int userIndex = 0; userIndex < USER_COUNT; userIndex++) {
                Future<UserDataCreated> future = completionService.take();
                try {
                    var userDataCreated = future.get();
                    userData.add(userDataCreated);
                    storageManager.store(userDataCreated);
                    atomicInteger.incrementAndGet();
                } catch (ExecutionException e) {
                    log.warn("Error while generating user", e);
                }
                // Display number of generated user and production rate per minute
                int successfullyGeneratedUsers = atomicInteger.get();
                if (successfullyGeneratedUsers % 100 == 0) {
                    log.info(
                            "Generated {} users in {} ms. Production rate: {} users per minute",
                            successfullyGeneratedUsers,
                            stopwatch.elapsed().toMillis(),
                            (successfullyGeneratedUsers * 60000) / stopwatch.elapsed().toMillis());
                    storageManager.store(userData);
                }
            }
            log.info("Persisting list of users");
            storageManager.store(userData);
        } finally {
            taskExecutor.shutdown();
        }
}

    private PerfData getRoot(EmbeddedStorageManager storageManager) {
        var stopwatch = Stopwatch.createStarted();
        var elapsed = stopwatch.elapsed();
        PerfData perfData;
        if (storageManager.root() == null) {
            perfData = new PerfData();
            perfData.setUsers(new LinkedList<>());
            storageManager.setRoot(perfData);
            storageManager.storeRoot();
            log.info("Generating new root for data.");
        } else {
            perfData = (PerfData) storageManager.root();
            log.info("Reusing data. Already {} users generated", perfData.getUsers().size());
        }
        log.info("Loading all data took {} ms", stopwatch.elapsed().minus(elapsed).toMillis());
        return perfData;
    }

Expected behavior

No Error.

Unclear REST service endpoint content type for /dictionary

Environment Details

  • EclipseStore Version: 1.1.0
  • JDK version: 17
  • OS: ubuntu 22.04
  • Used frameworks: Spring, SparkJava

Describe the bug

Implementing the endpoints for restservice-spring I realized that there is a "contradiction" in the docs and the implementation. The docs of the REST API says:

Returns the type dictionary as plain text.

In fact it is a plain text, since its return type is a plain string:

0000000000000000001 byte{
	primitive 8 bit integer signed,
}
0000000000000000002 boolean{
	primitive 8 bit boolean,
}
0000000000000000003 short{
	primitive 16 bit integer signed,
}

and so on

If I look on the implementation of the SparkJava Rest Service the response type is set to application/text (I believe this doesn't exist as contentType)

At the same time, the Jersey Client expects the content type to be application/json.

Expected behavior

Clarify which content type should be delivered.

TypeCastException for Root object when spring-boot-devtools dependency available classpath/runtime

Environment Details

  • EclipseStore Version: integrations-spring-boot3 : 1.2.0
  • JDK version: 21
  • OS: Mac
  • Used frameworks: Spring

Describe the bug

EmbeddedStorageManager creation failed due to TypeCastException for root object. This happens only when spring-boot-devtools dependency is present.

If spring-boot-devtools depedency removed, its works fine. Not sure, this has to be reported to eclipse serializer project

### StackTrace:
Caused by: org.eclipse.serializer.exceptions.TypeCastException: Cannot cast com.deepak.storedemokotlin.Data to com.deepak.storedemokotlin.Data
	at org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerReflective.updateState(AbstractBinaryHandlerReflective.java:539)
	at org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerReflective.updateState(AbstractBinaryHandlerReflective.java:44)
	at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.buildInstances(BinaryLoader.java:462)
	at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.build(BinaryLoader.java:396)
	at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.get(BinaryLoader.java:828)
	at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.loadRoots(BinaryLoader.java:872)
	at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.loadExistingRoots(EmbeddedStorageManager.java:349)
	at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.initialize(EmbeddedStorageManager.java:372)
	at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:252)
	at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:95)
	at org.eclipse.store.integrations.spring.boot.types.EclipseStoreProviderImpl.createStorage(EclipseStoreProviderImpl.java:59)
	at org.eclipse.store.integrations.spring.boot.types.EclipseStoreProviderImpl.createStorage(EclipseStoreProviderImpl.java:50)
	at org.eclipse.store.integrations.spring.boot.types.EclipseStoreBeanFactory.embeddedStorageManager(EclipseStoreBeanFactory.java:59)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140)


storage-restservice-sparkjava does not work in Quarkus

Environment Details

  • EclipseStore Version: 1.2.0
  • JDK version: openjdk version "21.0.2" 2024-01-16
  • OS: Mac OS
  • Used frameworks: Quarkus 3.8.1

Describe the bug

I use EclipseStore in Quarkus (in JVM-Mode) sucessfully after changing the ClassLoaderProvider according to https://stackoverflow.com/questions/65898882/quarkus-with-microstream-classloader-problems:

return EmbeddedStorageConfigurationBuilder.New()
	..
	.createEmbeddedStorageFoundation()
	// TODO workaround see https://stackoverflow.com/questions/65898882/quarkus-with-microstream-classloader-problems
	// default is "ClassLoader.getSystemClassLoader()"
	.onConnectionFoundation(cf -> cf.setClassLoaderProvider(ClassLoaderProvider.New(Thread.currentThread().getContextClassLoader())))
	..
	.start();

However, when using the eclipse-store "rest-interface":

<dependency>
	<groupId>org.eclipse.store</groupId>
	<artifactId>storage-restservice-sparkjava</artifactId>
	<version>1.2.0</version>
</dependency>

then quarkus does not start the application successfully and the following stacktrace is shown:

2024-03-01 10:38:59,512 INFO [org.ecl.ser.per.typ.PersistenceTypeHandlerManager] (Quarkus Main Thread) Initializing type handler manager
Exception in thread "Thread-38" java.lang.NoClassDefFoundError: javax/servlet/Filter
at spark.embeddedserver.EmbeddedServers.initialize(EmbeddedServers.java:41)
at spark.Service.lambda$init$2(Service.java:618)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:518)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:468)
... 3 more

I also tried to use another spark-version as suggested in microstream-one/microstream#238:

<dependency>
	<groupId>org.eclipse.store</groupId>
	<artifactId>storage-restservice-sparkjava</artifactId>
	<version>1.2.0</version>
</dependency>
<!-- workaround because of: https://github.com/microstream-one/microstream/issues/238  -->
<dependency>
	<groupId>com.sparkjava</groupId>
	<artifactId>spark-core</artifactId>
	<version>2.8.0</version>
</dependency> 

I also tried to solve this issue by making the javax.servlet-api-dependency explicit:

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>3.1.0</version>
	<scope>provided</scope>
</dependency>

But that doesn't help. Looking at the classpath I can see that javax.servlet.api exists:

Screenshot at Mar 01 10-50-40

To Reproduce

Use EclipseStore in Quarkus and initialize a StorageRestService by storage-restservice.

Expected behavior

Using a StorageRestService should work.

Entity and Wrapper code generators in Gradle - please document

Please consider adding the below example code to the relevant ES documentation sections - it may save Gradle users headaches and frustrations.

A Gradle user migth attempt to add ES generators as per the Gradle docs like shown below (where all information is extracted from the codegen jar and manifest):

dependencies {
    annotationProcessor "org.eclipse.serializer:codegen-wrapping:1.3.1"
    annotationProcessor "org.eclipse.serializer:codegen-entity:1.3.1"
    implementation "org.eclipse.store:storage-embedded:1.3.1"
}

compileJava {
    options.compilerArgs += [
            '-Awrapper.types=org.eclipse.serializer.persistence.types.PersistenceStoring',
            '-Aentity.hashequalator=true',
            '-Aentity.appendable=true'
    ]
}

Unfortunately, this works for the codegen-wrapper, but not for codegen-entity, which is simply ignored by Gradle 8.6+. I filed a Gradle issue for that, and we need to see what the Gradle team says (but I suspect codegen-entity is ignored because it does not declare to really processes any annotations).

In the meantime, here is a workaround that works fine: adding explicit -processor option to the javac command line to point to the processor class(es). Here is an example of enabling both ES code generators (note how the processor classes are comma-separated):

dependencies {
    annotationProcessor "org.eclipse.serializer:codegen-wrapping:${eclipseSerializerVersion}"
    annotationProcessor "org.eclipse.serializer:codegen-entity:${eclipseSerializerVersion}"
    implementation "org.eclipse.store:storage-embedded:${eclipseStoreVersion}"
   // ... more dependencies

}

compileJava {
    options.compilerArgs += [
            '-Awrapper.types=org.eclipse.serializer.persistence.types.PersistenceStoring',
            '-Aentity.hashequalator=true',
            '-Aentity.appendable=true',
            '-processor', 'org.eclipse.serializer.codegen.wrapping.WrapperProcessor,org.eclipse.serializer.codegen.entity.EntityProcessor'
    ]
    options.annotationProcessorPath = configurations.annotationProcessor
}

Storage migration tool

We need a tool to migrate a storage to another one with different settings.
The main reason for that is a transfer to a different channel count or file system.

ES 1.3.1 testing against a Minio (S3-compatible ) storage backend - please help!

Discussed in #188

Originally posted by hrstoyanov March 28, 2024
Hello,
I am trying to test ES 1.3.1 (with AWS Java SDK 2.25.18) against a local Minio server - a highly compatible AWS S3 storage server, widely for local development/testing of S3.

This setup code:

var awsBasicCredentials = AwsBasicCredentials.create(s3configuration.accessKey, s3configuration.secretKey);

            var s3Client = S3Client.builder()
                    .region(isEmptyOrNull(s3configuration.region)? Region.AWS_ISO_GLOBAL: Region.of(s3configuration.region))
                    .endpointOverride(s3configuration.endpoint)
                    .credentialsProvider(StaticCredentialsProvider.create(awsBasicCredentials))
                    .build();

            var buckets = s3Client.listBuckets().buckets();//Validate the S3 connection!
            logger.log(INFO, () -> STR."S3 buckets: \{buckets} ");

            var fileSystem = BlobStoreFileSystem.New(S3Connector.Caching(s3Client));

            return EmbeddedStorageFoundation.New()
                    .setConfiguration(StorageConfiguration.Builder()
                                        .setStorageFileProvider(StorageLiveFileProvider.Builder(fileSystem)
                                                                    .setDirectory(fileSystem.ensureDirectoryPath("storage"))
                                                                    .createFileProvider())
                                        .setChannelCountProvider(StorageChannelCountProvider.New(4))
                     .createConfiguration())
                     .onConnectionFoundation(BinaryHandlersJDK8::registerJDK8TypeHandlers)
                     .onConnectionFoundation(BinaryHandlersJDK17::registerJDK17TypeHandlers)
                     .createEmbeddedStorageManager();

generates the following exeception:

software.amazon.awssdk.services.s3.model.S3Exception: null (Service: S3, Status Code: 400, Request ID: 17C0DACB248DA3B8, Extended Request ID: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8)
	at software.amazon.awssdk.protocols.xml@2.25.18/software.amazon.awssdk.protocols.xml.internal.unmarshall.AwsXmlPredicatedResponseHandler.handleErrorResponse(AwsXmlPredicatedResponseHandler.java:156)
	at software.amazon.awssdk.protocols.xml@2.25.18/software.amazon.awssdk.protocols.xml.internal.unmarshall.AwsXmlPredicatedResponseHandler.handleResponse(AwsXmlPredicatedResponseHandler.java:108)
	at software.amazon.awssdk.protocols.xml@2.25.18/software.amazon.awssdk.protocols.xml.internal.unmarshall.AwsXmlPredicatedResponseHandler.handle(AwsXmlPredicatedResponseHandler.java:85)
	at software.amazon.awssdk.protocols.xml@2.25.18/software.amazon.awssdk.protocols.xml.internal.unmarshall.AwsXmlPredicatedResponseHandler.handle(AwsXmlPredicatedResponseHandler.java:43)

Am I setting up the embedded store manager correctly? In my code, you will see that I list the available buckets from the Minio server, so I know the S3Client connection is working fine. What am I missing?

In the Minio WEB UI admin console I see these traces:

s3.ListBuckets    200 OK
s3.HeadObject     400 Bad Request

java.lang.ClassNotFoundException: sun.misc.Unsafe

I tried Wicket as front end and using the Wicket Quickstart

mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=10.0.0 -DgroupId=com.mycompany -DartifactId=myproject -DarchetypeRepository=https://repository.apache.org/ -Dlog4j.properties=wildfly-doesnt-need-log4j.properties -DinteractiveMode=false

Deployment in Wilffly 31 and requesting of the webpage works as expected.

After adding the eclipse-store dependency to the POM and to class HomePage the line

final EmbeddedStorageManager storageManager = EmbeddedStorage.start();

I get an error with a new request:

`Root cause:

java.lang.ClassNotFoundException: sun.misc.Unsafe from [Module "deployment.myproject-1.0-SNAPSHOT.war" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:200)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.memory.sun.JdkInternals.getMemoryAccess(JdkInternals.java:77)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.memory.sun.JdkInternals.(JdkInternals.java:52)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.memory.sun.JdkMemoryAccessor.guaranteeUsability(JdkMemoryAccessor.java:51)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.memory.XMemory.guaranteeUsability(XMemory.java:329)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.Binary.(Binary.java:137)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustom.chars(AbstractBinaryHandlerCustom.java:87)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.java.lang.BinaryHandlerString.(BinaryHandlerString.java:44)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.java.lang.BinaryHandlerString.New(BinaryHandlerString.java:30)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.BinaryPersistence.createNativeHandlersValueTypes(BinaryPersistence.java:220)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.BinaryPersistence.createDefaultCustomTypeHandlerRegistry(BinaryPersistence.java:159)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.BinaryPersistenceFoundation$Default.lambda$ensureCustomTypeHandlerRegistryEnsurer$1(BinaryPersistenceFoundation.java:266)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.binary.types.BinaryPersistenceFoundation$Default.ensureCustomTypeHandlerRegistry(BinaryPersistenceFoundation.java:278)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.types.PersistenceFoundation$Default.getCustomTypeHandlerRegistry(PersistenceFoundation.java:977)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.types.PersistenceFoundation$Default.ensureRootsProvider(PersistenceFoundation.java:2467)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.serializer.persistence.types.PersistenceFoundation$Default.getRootsProvider(PersistenceFoundation.java:1342)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation$Default.createEmbeddedStorageManager(EmbeddedStorageFoundation.java:792)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.store.storage.embedded.types.EmbeddedStorage.createAndStartStorageManager(EmbeddedStorage.java:607)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.store.storage.embedded.types.EmbeddedStorage.start(EmbeddedStorage.java:437)
at deployment.myproject-1.0-SNAPSHOT.war//org.eclipse.store.storage.embedded.types.EmbeddedStorage.start(EmbeddedStorage.java:298)
at deployment.myproject-1.0-SNAPSHOT.war//com.mycompany.HomePage.(HomePage.java:18)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:171)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:76)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.DefaultMapperContext.newPageInstance(DefaultMapperContext.java:90)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.core.request.handler.PageProvider$Provision.getPage(PageProvider.java:369)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.core.request.handler.PageProvider.getPageInstance(PageProvider.java:170)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.handler.render.PageRenderer.getPage(PageRenderer.java:78)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:231)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:202)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:910)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:63)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:294)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:255)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:277)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:208)
at deployment.myproject-1.0-SNAPSHOT.war//org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:307)
at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at [email protected]//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.lambda$handleRequest$1(ElytronRunAsHandler.java:68)
at [email protected]//org.wildfly.security.auth.server.FlexibleIdentityAssociation.runAsFunctionEx(FlexibleIdentityAssociation.java:103)
at [email protected]//org.wildfly.security.auth.server.Scoped.runAsFunctionEx(Scoped.java:161)
at [email protected]//org.wildfly.security.auth.server.Scoped.runAs(Scoped.java:73)
at [email protected]//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.handleRequest(ElytronRunAsHandler.java:67)
at [email protected]//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at org.wildfly.security.elytron-web.undertow-server-servlet@4.0.0.Final//org.wildfly.elytron.web.undertow.server.servlet.CleanUpHandler.handleRequest(CleanUpHandler.java:38)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:44)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:51)
at [email protected]//io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:276)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:132)
at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1413)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1413)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1413)
at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1413)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:256)
at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:101)
at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:393)
at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:859)
at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at [email protected]//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)
at java.base/java.lang.Thread.run(Thread.java:1583)`

I have seen some hint in the eclipse store docs related to

--add-exports java.base/jdk.internal.misc=ALL-UNNAMED

and I tried to add compiler args to maven compiler plugin and also added this to wildfly conf JAVA_OPTS,but still noc success.

Any ideas ? How to fix it?

Environment Details

  • EclipseStore Version: 1.3.1

  • JDK version: openjdk 21.0.2 2024-01-16
    OpenJDK Runtime Environment (build 21.0.2+13-1)
    OpenJDK 64-Bit Server VM (build 21.0.2+13-1, mixed mode, sharing)

  • OS: OpenBSD 7.5

  • Used frameworks: Wicket 10, Wildfly 31

Plans for Eclipse Store Cluster (on premise) soon?

According to the below conference talk, something like this is coming up, but no roadmap has been shared?

I am asking, because I will soon need one, and can try to develop myself Eclipse Store Cluster (with Raft protocol coordination using jGroups), but would like to avoid duplication of efforts, if the ES team will also be publishing one.

Screenshot_2023-12-03-17-26-25-53_e4424258c8b8649f6e67d283a50a2cbc.jpg

The documentation for the layered entities configuration section is incorrect

The artifactId in the Maven coordinates of the codegen-entity module described in the document is wrong.

Description in the document:

<dependencies>
	<dependency>
		<groupId>org.eclipse.serializer</groupId>
		<artifactId>entity-codegen</artifactId>
		<version>1.3.1</version>
	</dependency>
</dependencies>

The correct description should be:

<dependencies>
	<dependency>
		<groupId>org.eclipse.serializer</groupId>
		<artifactId>codegen-entity</artifactId>
		<version>1.3.1</version>
	</dependency>
</dependencies>

Bootloader issues with Quarkus

Environment Details

  • EclipseStore Version: 1.2.0
  • JDK version: 21
  • OS: Mac OS
  • Used frameworks:Quarkus 3.8.1

Describe the bug

Explained here https://stackoverflow.com/questions/65898882/quarkus-with-microstream-classloader-problems, we have to set the Classpath provider to be able to run with Quarkus:

EmbeddedStorageConfigurationBuilder.New()
// default is "ClassLoader.getSystemClassLoader()"
.onConnectionFoundation(cf -> cf.setClassLoaderProvider(ClassLoaderProvider.New(Thread.currentThread().getContextClassLoader())))
..
.start();

After setting the ClassLoaderProvider to Thread.currentThread().getContextClassLoader()), EclipseStore will run in Quarkus. However, the Classloader issue is not fully resolved, when starting Quarkus in dev-mode:

Reproducer:

  1. Start Quarkus in dev-mode (clean compile quarkus:dev)
  2. Change any file so that quarkus:dev refreshes
  3. The following error log is shown:
2024-03-03 04:09:06,651 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (vert.x-worker-thread-1) Failed to start quarkus: io.quarkus.dev.appstate.ApplicationStartException: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:58)
	at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:132)
	at io.quarkus.deployment.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:192)
	at io.quarkus.deployment.dev.IsolatedDevModeMain.restartCallback(IsolatedDevModeMain.java:173)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:541)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:441)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:150)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:137)
	at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$0(ContextImpl.java:177)
	at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:276)
	at io.vertx.core.impl.ContextImpl.lambda$internalExecuteBlocking$2(ContextImpl.java:209)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
	at io.quarkus.runtime.Application.start(Application.java:101)
	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:113)
	... 1 more
Caused by: java.lang.ClassCastException: class app.data.Root cannot be cast to class app.data.Root (app.data.Root is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @6a0659ac; app.data.Root is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @2c135f49)
	...
	at io.App_Bean.doCreate(Unknown Source)
	at io.App_Bean.create(Unknown Source)
	at io.App_Bean.create(Unknown Source)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:119)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:38)
	at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:35)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:32)
	at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
	at io.quarkus.arc.impl.ComputingCacheContextInstances.computeIfAbsent(ComputingCacheContextInstances.java:19)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:35)
	at io.App_Bean.get(Unknown Source)
	at io.App_Bean.get(Unknown Source)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:554)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:534)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:567)
	at io.quarkus.arc.impl.ArcContainerImpl.instance(ArcContainerImpl.java:339)
	at io.App_Observer_Synthetic_wKazinfVTztwl6u625c5_wlQFVE.notify(Unknown Source)
	at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:346)
	at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:328)
	at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:82)
	at io.quarkus.arc.runtime.ArcRecorder.fireLifecycleEvent(ArcRecorder.java:155)
	at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:106)
	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy_0(Unknown Source)
	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent1144526294.deploy(Unknown Source)
	... 11 more

Expected behavior

No classloader problem should happen. The ideal way would be to provide a quarkus-eclipsestore extension so that the user doesn't have to fiddle around or set the class loader themselves.

Additional context

I think the cause of the problem (and maybe a solution) is very similar to quarkusio/quarkus#30741.

Node dependency

Not sure if vaadin should be a dependency for the eclipse store project.

I get the same error as with the book-store example, c.f.: eclipse-store/bookstore-demo#1

[ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:24.2.6:prepare-frontend (default) on project storage-restclient-app: Could not execute prepare-frontend goal.: Failed to install Node: Unable to detect version of Node. Using command /home/rpx/.vaadin/node/node --version: Process exited with non 0 exit code. (1) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn -rf :storage-restclient-app

Type not persistable: "class java.lang.Thread" for customized class loader and Postgresql storage target

As mentioned in the docs a customization is necessary if there are issues regarding different classloaders. For file based storagees the given solution works perfectly. Now I've switched to Postgresql as Storage targets and also use the code example given in the docs here.
But in this case, the following error occur:

org.eclipse.serializer.persistence.exceptions.PersistenceExceptionTypeNotPersistable: Type not persistable: "class java.lang.Thread".

This is the whole Spring Bean Config:

    // configured as usual via application.yml
    private final DataSource dataSource;
    private final Environment environment;

    public DatabaseConfiguration(DataSource dataSource, Environment environment) {
        this.dataSource = dataSource;
        this.environment = environment;
    }  

  @Bean(destroyMethod = "shutdown")
  @Primary
  public StorageManager defineStorageManager() {
        SqlFileSystem fileSystem = SqlFileSystem.New(
            SqlConnector.Caching(
                SqlProviderPostgres.New(dataSource)
            )
        );
  
        EmbeddedStorageManager storageManager = EmbeddedStorage.Foundation()
            .onConnectionFoundation(cf -> cf.setClassLoaderProvider(ClassLoaderProvider.New(
                Thread.currentThread().getContextClassLoader())))
            .start(fileSystem.ensureDirectoryPath("storage"));

        // Check Root available within StorageManager
        RootData root = (RootData) storageManager.root();
        if (root == null) {
            root = new RootData();
        } else {
            log.debug(root.toString());
            log.debug(root.getCustomers().toString());
        }

        storageManager.setRoot(root);
        return storageManager;
    }

What config is neccessary for Postgresql storage target plus the classloader customization ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.