Using jetstreamDB as in-memory Database for Java
June 30th, 2018 by Micha KopsJetstreamDB is a in-memory database engine for Java that claims to be built for ultra-high speed and the ability of managing complex data structures by storing real Java objects instead of serializing data structures to other database specific formats.
In the following short example I would like to demonstrate how to create and read items from such a database by building a small article management sample app.
Contents
Project Setup
First of all we’re adding some Maven repositories to our project’s pom.xml:
<repositories> <repository> <id>jetstream-releases</id> <url>https://maven.jetstream.one/maven2-public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>jetstream-snapshots</id> <url>https://maven.jetstream.one/maven2-public-snapshot</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories>
Afterwards just need to add the following dependency:
<dependency> <groupId>com.jetstreamdb</groupId> <artifactId>jetstreamdb-embedded</artifactId> <version>1.0.0-beta1</version> </dependency>
Sample Application
We’re now implementing a sample application to store and retreive some data from a jetstreamDB…
Root Entity
This is our aggregate, the root of our persisted data:
package com.hascode.tutorial; import java.util.ArrayList; import java.util.List; public class RootData { private final List<Article> articles = new ArrayList<>(); public List<Article> getArticles() { return articles; } }
Article Entity
This is our article entity
package com.hascode.tutorial; public class Article { private final String title; // constructor, getter, setter, tostring ommitted.. }
Command Line App
This is our command line app that allows us to create and list our articles:
package com.hascode.tutorial; import com.jetstreamdb.JetstreamDBInstance; import java.io.Console; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; public class ArticleApp { private static final String USAGE = "Enter a command 'l': list, 'a': add, 'q': quit 'd': db info\n"; private JetstreamDBInstance<RootData> db; public ArticleApp() { db = JetstreamDBInstance.New("my-articles-db ", RootData.class); Path databaseDirectory = Paths.get("").resolve("article-db"); System.out.printf("creating database directory in %s%n", databaseDirectory.toAbsolutePath()); db.configuration().properties().setStorageDirectory(databaseDirectory.toFile()); } public static void main(String[] args) { new ArticleApp().run(); } public void run() { prompt(); } private void prompt() { Console console = System.console(); System.out.println(USAGE); String command = console.readLine(); switch (command) { case "q": System.out.println("quitting..."); System.exit(1); break; case "l": List<Article> articles = db.root().getArticles(); System.out.printf("%d articles found:%n", articles.size()); articles.forEach(System.out::println); prompt(); break; case "a": System.out.println("Please enter a title"); String title = console.readLine(); List<Article> update = db.root().getArticles(); update.add(new Article(title)); db.store(update); prompt(); break; case "d": System.out.printf("basedir: %s, name: %s%n", db.configuration().getBaseDir(), db.configuration().name()); prompt(); break; default: System.out.println("invalid command"); prompt(); } } }
Running the Application
Now we’d like to add and fetch some data from our application:
We may start the application using our IDE or using Maven in the command line like this:
mvn clean compile exec:java -Dexec.mainClass=com.hascode.tutorial.ArticleApp [..] `:osssssssso/. y+ .oy/. `:oy/ ho /h: `sy` hddd/oooooooooooooooo+omdo. smmmoy+ d/dmmd/ JetstreamDB -mmmm+h/ h/dmmmh -mmmmh/y+` .oy+mmmmd Version 1.0.0-beta1 -mmmmdy.:os+-.```.:oso-:dmmmmd :mh+- -yo. .:++o+/:``:so``/sdd :h/ .+so+//:/+oss/` .oy. :d. `` `.:m-.` `` /d. h+ oo .d` +s so d: oo .d` /oooo- +s +y h/ oo .d` +s +y /h----yo `: +y----h+ sd/::yo +y::/ds :yo:so +s:oy/ ./ho .d` oh/. so .d` +y oo .d` +y ohoooo+++/+m+/+++oooohy .ss+::/+shs/sho/:-:/ss. ``````````-:::-.`````-:///-````````` ```````````````````````````````````` `````````````````````````` creating database directory in /data/project/jetstream-tutorial/article-db Enter a command 'l': list, 'a': add, 'q': quit 'd': db info l 0 articles found: Enter a command 'l': list, 'a': add, 'q': quit 'd': db info a Please enter a title Some title Enter a command 'l': list, 'a': add, 'q': quit 'd': db info l 1 articles found: Article{title='Some title'} Enter a command 'l': list, 'a': add, 'q': quit 'd': db info d basedir: article-db, name: my-articles-db Enter a command 'l': list, 'a': add, 'q': quit 'd': db info a Please enter a title another one Enter a command 'l': list, 'a': add, 'q': quit 'd': db info l 2 articles found: Article{title='Some title'} Article{title='another one'} Enter a command 'l': list, 'a': add, 'q': quit 'd': db info
Internal Structure
Having created those articles we can see that jetstreamDB has created the following files in the designated directory:
/article-db
├── channel_0
│ ├── channel_0_1.dat
│ └── transactions_0.sft
├── ObjectId.oid
├── PersistenceTypeDictionary.ptd
└── TypeId.tid
Tutorial Sources
Please feel free to download the tutorial sources from my Bitbucket repository, fork it there or clone it using Git:
git clone https://bitbucket.org/hascode/jetstreamdb-tutorial.git
September 12th, 2018 at 3:22 pm
Which Java version did you use. I tried with Java 10 – fresh clone from bitbucket – and it just crashed
September 12th, 2018 at 8:47 pm
I’ve used Java 8 (https://bitbucket.org/hascode/jetstreamdb-tutorial/src/master/pom.xml#lines-13).
Which error did you encounter with Java 10? Some Illegal reflective access error?
September 13th, 2018 at 2:44 pm
No a class cast exception, I will try again with Java 8. Below my stack trace
java.lang.ClassCastException: [B cannot be cast to [C
at com.jetstreamdb.memory.Memory.accessChars(Memory.java:282)
at com.jetstreamdb.persistence.binary.types.BinaryPersistence.storeStringsAsList(BinaryPersistence.java:1201)
at com.jetstreamdb.persistence.binary.types.BinaryPersistence.storeStringsAsList(BinaryPersistence.java:1180)
at com.jetstreamdb.persistence.binary.internal.BinaryHandlerPersistenceRootsImplementation.store(BinaryHandlerPersistenceRootsImplementation.java:144)
at com.jetstreamdb.persistence.binary.internal.BinaryHandlerPersistenceRootsImplementation.store(BinaryHandlerPersistenceRootsImplementation.java:1)
at com.jetstreamdb.persistence.binary.internal.AbstractBinaryHandlerNative.store(AbstractBinaryHandlerNative.java:1)
at com.jetstreamdb.persistence.binary.types.BinaryStorer$Implementation.storeItem(BinaryStorer.java:450)
at com.jetstreamdb.persistence.binary.types.BinaryStorer$Implementation.storeGraph(BinaryStorer.java:441)
at com.jetstreamdb.persistence.binary.types.BinaryStorer$Implementation.store(BinaryStorer.java:325)
at com.jetstreamdb.persistence.types.PersistenceManager$Implementation.store(PersistenceManager.java:163)
at com.jetstreamdb.storage.types.StorageConnection.store(StorageConnection.java:132)
at com.jetstreamdb.storage.types.EmbeddedStorageManager$Implementation.initialize(EmbeddedStorageManager.java:214)
at com.jetstreamdb.storage.types.EmbeddedStorageManager$Implementation.start(EmbeddedStorageManager.java:141)
at com.jetstreamdb.storage.types.EmbeddedStorageManager$Implementation.start(EmbeddedStorageManager.java:1)
at com.jetstreamdb.storage.types.EmbeddedStorageManager.start(EmbeddedStorageManager.java:50)
at com.jetstreamdb.storage.types.EmbeddedStorageManager.start(EmbeddedStorageManager.java:41)
at com.jetstreamdb.JetstreamDBInstance.createAndStartStorageManager(JetstreamDBInstance.java:462)
at com.jetstreamdb.JetstreamDBInstance.start(JetstreamDBInstance.java:402)
at com.jetstreamdb.JetstreamDBInstance.root(JetstreamDBInstance.java:284)
at net.tangly.erp.crm.db.CrmRoot.addFoo(CrmRoot.java:55)
at net.tangly.erp.crm.db.CrmRootTest.testCrmRoot(CrmRootTest.java:12)
September 13th, 2018 at 2:58 pm
Java 8 works fine. It seems that the library is not compatible with Java 10 or Java 11. Thanks for the hint.
September 13th, 2018 at 7:54 pm
You’re welcome! Thanks for keeping me up-to-date :)
September 20th, 2018 at 9:33 pm
With using Java8, I get the following exception when starting the unchanged example:
Exception in thread “main” java.lang.NoClassDefFoundError: com/jetstreamdb/collections/types/XGettingCollection
at com.hascode.tutorial.ArticleApp.(ArticleApp.java:17)
at com.hascode.tutorial.ArticleApp.main(ArticleApp.java:24)
Caused by: java.lang.ClassNotFoundException: com.jetstreamdb.collections.types.XGettingCollection
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
… 2 more
September 21st, 2018 at 10:07 pm
Oh, it was just a corrupt JAR file. Just removed it from local repository and updated maven – everything fine!
September 21st, 2018 at 10:56 pm
Hi, I’m glad that it’s working for you now, thanks for the update! :)
September 30th, 2018 at 2:45 pm
Which license has jetstreamdb?
October 31st, 2018 at 10:08 pm
Hi,
I also have the same error “An illegal reflective access operation has occurred” on Java 9+.
I’m currently evaluating your library but we are switching to Java 11.
So could you let me know if you intend to make the library compatible for Java 9+ or do you have a hint how I make a workaround.
Thanks
November 2nd, 2018 at 6:46 pm
Hi,
it’s not my library, I have only written an article about it. Please consider contacting the vendor for such questions: http://jetstreamdb.com/
Best regards
Micha