SQL Support coming in Apache Polygene 3.1

NOTE: This post is advanced and primarily intended for those who wants to know how Polygene works under the hood. This article could be helped with diagrams, but…

Since the Apache Polygene 3.0 was released, we have been hard at work of creating a nicer SQL Entity Store, that lays out the data model in a Enterprise-like manner, rather than the Key-Value approach that has been around in Polygene for years but never really used, since it doesn’t really play well with external tools.

SQL Model

First of all, if you are not familiar with Polygene, please see the Polygene Introduction from earlier this year (2017).

The relational model is fully supportive of the Polygene entities model, and it achieves this with 2 tables for overhead and two tables per mixin type;

  • Types table – which maps Polygene/Java types to Mixin tables.
  • Entities table – which maps Identity to current value rows in the respective Mixin table.
  • Mixin tables – One field for each Property and each Association (not ManyAssociation and NamedAssociation though) declared in the mixin type. Inherited Properties are always stored in their own tables.
  • Mixin Association tables – These tables contains the many-to-many mappings of ManyAssociation and NamedAssoication references in the mixin type.

Table names follows, if possible, the simple name of the mixin types.

Example

package org.hedhman.niclas;

import org.apache.polygene.api.association.Association;
import org.apache.polygene.api.common.Optional;
import org.apache.polygene.api.property.Property;
import org.apache.polygene.api.common.UseDefaults;

public interface Person
{
    Property<String> name();

    @Optional
    Assocation<Person> spouse();

    @UseDefaults
    ManyAssociation<Person> children();
}

This will cause the following DDL (Postgresql);

create schema "POLYGENE"
create table if not exists "POLYGENE"."TYPES" (
    "_identity" varchar null, 
    "_table_name" varchar null, 
    "_created_at" timestamp null, 
    "_modified_at" timestamp null, 
    primary key ("_identity")
)
create table if not exists "POLYGENE"."ENTITIES" (
    "_identity" varchar null, 
    "_app_version" varchar null, 
    "_value_id" varchar null,
    "_version" varchar null, 
    "_type" varchar null,
    "_modified_at" timestamp null,
    "_created_at" timestamp null, 
    primary key ("_identity")
)
create table "POLYGENE"."Person" (
    "_identity" varchar null, 
    "_created_at" timestamp null, 
    "name" varchar null, 
    "spouse" varchar null, 
    primary key ("_identity")
)
create table"POLYGENE"."Person_ASSOCS" (
    "_identity" varchar null, 
    "_name" varchar null, 
    "_index" varchar null, 
    "_reference" varchar null
)
create index "IDX_Person_ASSOCS" on "POLYGENE"."Person_ASSOCS"(
    "_identity"
)

This should almost be self-explanatory. But the Person_ASSOCS table might require some explanation.

When we add two Person instances to the children() ManyAssocation, one row will be written into the Person_ASSOCS, such as;

insert into "POLYGENE"."Person_ASSOCS" (
    "_identity", 
    "_name", 
    "_index", 
    "_reference"
) values (
    '0a6e89dd-89f7-46a9-9ce4-305f5ddda47c', 
    'children', 
    '0', 
    'c8116128-0f4c-4225-813c-c89a8e480c6c'
)

insert into "POLYGENE"."Person_ASSOCS" (
 "_identity", 
 "_name", 
 "_index", 
 "_reference"
) values (
 '0a6e89dd-89f7-46a9-9ce4-305f5ddda47c', 
 'children', 
 '1', 
 '0a6e89dd-89f7-46a9-9ce4-305f5ddda47c'
)

The “index” column is used both to preserve the order the children were added to the ManyAssociation, but also used for the name in the NamedAssociation case.

If there are multiple Polygene types in different packages, the Types table will keep them separated and start adding a sequence number to them. Person, Person_1, Person_2 and so on.

Fetching an Entity

So, in reality all entities are spread out over two or more tables. And when these are loaded back into memory an outer join query will take place. Well, in fact there will be two queries, one for the entity itself and one for the associations. So for a simple entity like Person above, these are a fairly small queries.

select * from "POLYGENE"."ENTITIES" 
    left outer join "POLYGENE"."Person" on "_value_id" = "Person"."_identity" 
    where "ENTITIES"."_identity" = 'c8116128-0f4c-4225-813c-c89a8e480c6c'

select * from "POLYGENE"."ENTITIES" 
    join "POLYGENE"."Person_ASSOCS" on "_value_id" = "Person_ASSOCS"."_identity" 
    where "ENTITIES"."_identity" = 'c8116128-0f4c-4225-813c-c89a8e480c6c'

Say that the Person type was a bit more complex;

public interface Person 
    extends LegalEntity, AccountHolder, Customer
{}

Then there will be one “left outer join” per mixin type it inherits.

select * from "POLYGENE"."ENTITIES" 
 left outer join "POLYGENE"."Person" on "_value_id" = "Person"."_identity" 
 left outer join "POLYGENE"."LegalEntity" on "_value_id" = "LegalEntity"."_identity" 
 left outer join "POLYGENE"."AccountHolder" on "_value_id" = "AccountHolder"."_identity" 
 left outer join "POLYGENE"."Customer" on "_value_id" = "Customer"."_identity" 
 where "ENTITIES"."_identity" = 'c8116128-0f4c-4225-813c-c89a8e480c6c'

FAQ

Is it available now?

This is still work in development. The ‘develop’ branch right now has the implementation working, but further stress testing is needed. This extension is scheduled to be released in Polygene 3.1 before end of the year.

What Polygene features are not supported?

As far as we know, all Polygene persistence features are supported by the SQL Entity Store extension.

An auxiliary feature in Polygene persistence system is Migration Support, which allows for models to be modified over time and users can add support for entities to be “upgraded” on-the-fly. The Migration support is predicated on the JSON backed storage model that most Entity Stores are using. That is not currently available in this Entity Store, but something similar should come in a future release.

At the time of writing, the underlying JOOQ framework seems to have a bug in MySQL/MariaDb table creation script generation, and those databases don’t work at this moment, but we are working with them to solve this. And we expect that to be resolved before the Apache Polygene 3.1 release itself.

How does Polygene SQL Entity Store differ from JPA/JDO ?

First of all, JPA and JDO don’t have explicit modeling of entities built into their definitions. One is expected to work with CLASSES which are annotated either directly in the code, or in attached XML files.

In Polygene, you work with explicit Entities, Properties and various Associations types, and therefor no additional annotations are required. The entities model in Polygene is a top-down design, where the Polygene model drives that SQL database layout. Once used to the Polygene metaphor, it is much more natural, easier and less boiler-plate code. Additionally, all the AOP features of Polygene applies to entities and many advanced features are easily implemented in Polygene, but requires Hibernate hooks and other special implementation features to achieve in JPA/JDO.

In JPA and JDO, it is possible to “map” almost arbitrarily relational models on to Java classes, and that feature creates an immense complexity both in terms of design/usage as well as the internals. It is not likely that Polygene will attempt to support “existing DBs” to be mapped transparently.

Is Indexing/Query handled as well?

One of the promises of using SQL is that it might be possible to reuse the entity data for querying, and not require a separate indexing store. This is currently not the case, but something we will look into in the future.

Apache Polygene 3.0 Released!

Apache Polygene™ 3.0 was released today. It has been in the works for a long time, and we promise it will not be as slow in upcoming relases.

What’s Polygene 3.0 All About?

There has been 3 major themes in the work that has gone into this release;

  1. Breaking compatibility
    1. Java 8 Required
    2. org.apache.polygene namespace
    3. Serialization overhaul
    4. EntityStore overhaul
    5. Dropping explicit OSGi support
  2. Simplify Use
    1. Better error reporting
    2. Layered application assembly
    3. Code Generator for getting started
    4. Better Assemblers
  3. More Functionality
    1. Powerful Rest API library
    2. Apache Cassandra EntityStore
    3. Apache Geode Entity
    4. Full Scripting API support

And I will cover each below in better detail.

Breaking Compatibility

Java 8

In Polygene 2.x, we had our own Streaming and Functional APIs, which were originally modeled after the announcements made how it would work. Instead of waiting for Java 8, the entire runtime was written in a functional and streaming style. Once Java 8 is here, it was natural to drop org.qi4j.core.functional and org.qi4j.core.io and fully convert to Java Functional API and Java Streaming API.

Practically all places where Iterable was used as a Streaming alternative are now Stream, as well as new methods to fully embrace this style of coding.

org.apache.polygene Namespace

We decided to keep the org.qi4j namespace in the Apache Polygene 2.1 release about 2 years ago, to remain compatible with previous versions of Qi4j.

Since we were set to break compatibility, it is natural to adopt the org.apache.polygene namespace. Most classes remain in the sub-packages from original root package, but not 100%. Some classes have been moved around to clean the design further.

New Serialization SPI

The Serialization SPI was in dire need of clean up. We have adopted the javax.json extensions, and recommend Apache Johnzon. Any other javax.json compatible implementation can be used.

Additionally, there is an XML serialization service using javax.xml and its extension mechanism. And we also have MsgPack format available.

EntityStore SPI improvements

There has been a large number of changes in the EntityStore SPI. The most important ones are described below.

Storage format for JsonMapEntityStore has changed a little bit and existing data is not compatible. This is very unfortunate, but we feel we need to do this to ensure long-term compatibility from here on. Existing entity stores support that the data can be exported in JSON format and conversion to the new format is relatively easy to do offline. Contact dev@polygene.apache.org if help with this is needed.

UnitOfWorkFactory is now a Service Composite, and by default it creates UnitOfWork instances as Transient Composites. This opens up a lot of opportunities of custom code around UnitOfWork management.

Type management has been cleaned up and some Visibility bugs have been squashed in the process. All type handling is now done via a TypeLookup SPI, available from Module.

Dropping OSGi

When Qi4j started, OSGi was the hottest thing around and we felt obliged to be OSGi-friendly. Unfortunately, we have not been proactively testing that we are OSGi-capable and not been keeping up with the developments in the OSGi world.

So, instead of claiming that we are OSGi-compatible/friendly, we simply drop that claim, but there are no explicit changes that reduces Polygene’s ability to run in OSGi. We still generate OSGi Bundle manifests, but don’t know if they are optimal or not.

The explicit OSGi support may be re-introduced in the future, especially if we have active participants who are working on OSGi+Polygene projects.

Simplify Use

Better error reporting

Pre-3.0 it was quite tedious to get the application assembly in order. Types were not visible or was forgotten to be added to the assembly. We have tried hard to both make better messages of what is wrong, as well as trying to report more problems in the same run, so the number of edit-compile-run cycles decreases.

Layered application assembly

It was previous rather cumbersome to build the application structure in a layered fashion. Often single layers or even single modules were used because it was too hard to make it.

In 3.0, we have introduced LayeredApplicationAssembler which allows easy creation of layered applications, by using naming conventions and reflection.

Better Assemblers

In 2.0, we started to introduce ready-to-use, configurable assemblers for many of the extensions and some of the libraries.

In order to support the code generator, there has been a a convergence of naming and what assembly configurations are available. More often than not, you should be able to rely on these assemblers for standard functionality, rather than crafting your own (still possible).

More Functionality

Powerful Rest API library

Polygene 2.x contains a Rest Server API, which is very flexible, but somewhat hard to use and extend. It was a conversion from a project written in the DCI-style.

The new Restlet Library (fully supported by the Code Generator) makes it very easy to create CRUD operation in HATEOAS style, and/or call methods on resources. All resources are Composites and all the goodies of Composites are automatically available in the Rest API.

Apache Cassandra EntityStore

Nothing much to say, EntityStore for Cassandra has been added and it does NOT use the JsonMapEntityStore SPI.

Apache Geode Entity

Apache Geode (commercially available as GemFire) is another addition to the family of EnittyStores available.

Full Scripting API support

We have supported some scripting languages for a long time, but didn’t rely on the Java Scripting API to implement it.

We should now be fully compatible with all Scripting API compliant languages, and the list of explicitly supported languages are; Javascript (Nashorn), Groovy, Kotlin, JRuby, Jython and Lua. Other languages are likely to work, but no guarantees yet.

This means that for a Composite with 7 methods, we can implement each method in a different language, yet make it seem to be like a single object. This is at the extreme end of Polygene power. Different languages within an Object!!

What’s Next?

There are already many things being worked on for the next couple of releases. It is too early to tell when these are coming, but we have a vague idea of what they will contain.

Polygene 3.1

Two big features are being worked on, and should be ready in 3-4 months time.

Enterprise-friendly SQL EntityStore

The current SQL EnityStore is effectively a Key/Value store backing the JsonMapEntityStore. This is not friendly for SQL processing by other applications and worrisome for DBA and Data managers who wants the data to survive for long in accessible formats. This is the norm and environment in large IT departments, a.k.a The Enterprise.

The new SQL EntityStore in the works, will store all properties in their own columns, and built relationships across them in the defacto standard of how SQL models are built. Any data manager looking at a the resulting SQL model will not object to it on the previous grounds.

However, we don’t intend to support mapping any SQL model to the Polygene model, as that will sink us into the same swamp that JPA is desperately fighting with endless problems. We might provide tooling, perhaps in later releases, to convert a SQL data model into a working Polygene model, but we can’t promise at this point in time that it will be feasible.

Kotlin Assembly

Kotlin is a very neat programming language from Jetbrains. And it turns out that with a few additions to Polygene, very nice application assembly can be written in Kotlin instead of Java.

Code Generator for getting started

One of the biggest new features in Polygene 3.x is the Yeoman-powered code generator.

Answer a few questions about name, package and which modules you want to use, and a ready-to-deploy skeleton is created, complete with a Gradle build system, layered and things like Apache Shiro security, Scripting API and JMX optionally included.

It is possible to supply a JSON document which may contain definitions for entities, values and services, incl their properties and association. This will hopefully lead to a web service where you can build your model interactively and have the skeletal application be fully generated for you.

It is similar to Spring Boot and Spring Initializr, except much better and creates a full application, not only bringing down loosely coupled parts not working together.

Demo of this will follow on this blog soon.

Polygene 3.2

New Indexing/Query system

Currently, Indexing and Query is the weakest part of Apache Polygene and we need to improve it. Not only do we need to improve the API, but more importantly, we need to unify that all queries work on all implementations. We will probably keep the existing Indexing/Query system as-is, for compatibility reasons and introduce a parallel system that can be used instead.

Effort will also be made to try to create an abstraction at a higher level, to make it easier to create an Indexing extension. Currently all the effort is in the extension, and it is very hard to get it right. Something similar to the JsonMapEntityStore is what we want to see.

Polygene 3.3

Timeseries Support

If one wants to store Timeseries in an Polygene application, it becomes very ineffective and slow.

Timeseries support should be both at UnitOfWork and Querying level as well as REST API support for Grafana and other visualization tools.

Final Thoughts

Polygene (Qi4j) has come a long way, and even though the journey has been up and down, the slow progress is eventually paying off. I am really looking forward to the next few years and see Polygene’s uptake increase, mostly due to its solid object model with extraordinary flexibility in the Composition features, a nicely integrated persistence mechanism and other useful extensions.

The two major hurdles for Polygene adoption is addressed in the next release, the steep learning curve to get started and the lack of enterprise-friendly SQL support. With that, I think there is no arguments against using Polygene for green-field projects, and strong arguments for using it in existing projects. And Polygene remains an unchallenged platform for Domain Driven Design.

Introducing Apache Polygene

Apache Polygene is a small and somewhat obscure project, with enormous potential as the business application framework of choice for typical enterprise applications.

Polygene promises to simplify Java enterprise application software development, by getting away from flawed persistence systems such as EJB, Hibernate, JPA, JDO and others, as well as greatly aid in domain model design.

Polygene in a Nutshell

Polygene challenges the status quo in Java eco system, and nothing more so than the so called “POJO”, or sometimes called the Java Bean, concept/abstraction/paradigm. POJO is ill-defined and Java Beans Specification (from 1996) is almost never followed, but there are a few accepted things about it, that we object fervishly;

  • Setters – very poor choice, since either it is unknown what setters must be called for the object to be useful, or have extensive checks that those has been called and throw exceptions in runtime, or have sensible defaults at all times. Most so called POJOs fail on all of these, and rely solely on documentation and trial and error by programmer. Further, setters makes immutable value objects impossible, and which makes the semantics around equals/hashCode often broken, i.e. equals treats objects with setters with value equality (perhaps the compiler should ensure that only final fields are allowed?). It took Spring something like 5 years to introduce constructor injection, which is neat, but it also sink all generic use, such as JSON deserializers.
  • Anemic object models – The whole POJO culture is built around POJOs without behavior, and external services manipulating (or creating) the state of these POJOs. Object-oriented programming is about keeping State and Behavior together, but we constantly see a style that could have been done with C structs.
  • Over-generalization – Especially Spring framework drives the “if all you have is a hammer, then everything looks like a nail” notion. There is a huge difference between application assembly (which components are glued together and how) and the values to be changed by operations (say, hostname and ports).
  • Persistence nightmare – The POJO culture in enterprise applications is largely driven by the combination of Spring and Hibernate, each reinforcing the other, with horrendous consequences. Hibernate itself tries to solve any design choice people make between an overly generalized object model and any conceived SQL data model. To make it even worse, Hibernate/JPA made some very poor choices on design, that any POJO can be “saved”, but after it is saved, it is not really an entity yet, but still cached as if it was. The distinction of when POJOs are usable and not is practically undefined, and people struggle immensely from it. Hibernate has single-handedly created billions of dollars in salary to miserable programmers trying to get it to work somewhat properly. Yet, plenty of internal bugs in Hibernate over the years, some destroying data very subtly.

And these things drives a poor style of business application development, making applications larger, more buggy, more costly and much harder to maintain and extend.

Polygene set out to create a platform to develop enterprise applications without having to worry about the above problems and many other technical aspects of the application. Write the business logic in a domain model without needing to see any technical choices bleeding into the model.

Polygene does not try to make things more general than they are. A Value (as defined in “Domain Driven Design – Tackling complexity in the heart of software”) is a specific metatype, as is an Entity or a Service. It also drops the notion that a pair of methods, with certain signatures to be a Property. Polygene has a type called Property and methods in interfaces that returns a Property is the property (examples below). Similarly, reference to an Entity is an explicit type, Association, which is automatically fetched on access. Similarly, ManyAssociation and NamedAssociation are for lists and maps of entity references.

Polygene also abandons classes as the primary feature of Java, in favor of interfaces. Classes are simply the implementation details, and secondary to domain model design, which happens with interfaces. Polygene handles the binding of class methods to interface methods.

Can you show me a simple example?

Ok, we can write

public interface Person extends HasIdentity
{
    Property<String> name();
    Property<Address> address();
    Property<LocalDate> dateOfBirth();

    @Optional
    Association<Person> spouse();
    ManyAssociation<Person> children();  // List of children

    // Map of phone numbers, such as "Work", "Home", "Mobile"
    NamedAssociation<PhoneNumber> phoneNumbers();
}

(Polygene-specific types/methods/annotations marked in purple.)

Intent is cleanly expressed in this domain type. If we register the type as an Entity, it can be loaded, modified and persisted inside a UnitOfWork. If we register the type as a Value, it will be immutable. And in both cases, No implementation is required.

Say that we have the following code somewhere

public void personBornNow( Person person ) 
{
    person.dateOfBirth().set( LocalDate.now() );
}

Then if the Person passed is an Entity, the setting of the dateOfBirth will succeed, but on a Value it will throw an exception.

Can I make any Property immutable?

Yes, of course. Say that we want the dateOfBirth to be immutable (because no mistakes could be made).

public interface Person extends HasIdentity
{
    Property<String> name();

    @Immutable
    Property<LocalDate> dateOfBirth();
    :

and again the intent is clear, without any clutter in the code.

So, how do I create Polygene objects, if I only have interfaces?

Polygene uses Builder for that purpose. This is both to control the creation process as well as allow the immutability to be handled in a type-safe manner.

public class SomeImplementationClass
{
    @Structure 
    ValueBuilderFactory vbf;

    public Person createPerson( String name, LocalDate birthDate )
    {
        ValueBuilder<Person> builder = 
            vbf.newValueBuilder( Person.class );

        Person prototype = builder.prototype();
        prototype.name().set( name );
        prototype.dateOfBirth().set( birthdate );
        return builder.newInstance();
    }
}

The @Structure annotation is a dependency injection directive, asking Polygene to inject (in this case) a ValueBuilderFactory from the “Structure scope” (Scopes are beyond the scope of this article – no pun intended).

The “prototype” is useful when you have many values instances to be created with only a small number of differences between them.

The pattern also allows for “private state”. Polygene can hide the properties/associations from access them outside. More about that later.

There is a central idea of Composites, which is a uniquely Polygene innovation. A Polygene Composite is considered the “object” of the above examples, but the implementation of the interface may consist of many implementation classes, that are weaved together by the Polygene runtime engine. The implementation classes are called Mixins, and one mixin may implement one or many of the methods in the interface, and do so in a type-safe manner, or by using dynamic invocation handlers. Let’s look at an example;

@Mixins( { PhoneNumberMixin.class, AddressMixin.class } )
public interface Person
{
    void addPhoneNumber( String type, PhoneNumber number );
    void removePhoneNumber( String type );

    void changeAddress( Address newAddress );

    // We also create private state, which users can't reach
    interface State
    {
        Property<String> name();
        Property<Address> address(); 
        Property<List<Address>> oldAddresses();
        Property<LocalDate> dateOfBirth();

        @Optional
        Association<Person> spouse();
        ManyAssociation<Person> children();  // List of children

        // Map of phone numbers, such as "Work", "Home", "Mobile"
        NamedAssociation<PhoneNumber> phoneNumbers();
    }
}
public abstract class AddressMixin
    implements Person
{
    @This
    private Person.State state;

    public void changeAddress( Address newAddress )
    {
        // Save old address before changing.
        state.oldAddresses().get().add( state.address().get() );
        state.address().set( newAddress );
    }
}

public abstract class PhoneNumberMixin
    implements Person
{
    @This
    private Person.State state;

    public void addPhoneNumber( String type, PhoneNumber number )
    {
        state.phoneNumbers().put( type, number );
    }

    public void removePhoneNumber( String type )
    {
        state.phoneNumbers().remove( type );
    }
}

Quite a lot of features are in that sample.

First of all, the inner interface “State” to hide access from user code.

Secondly, there are two mixins declared on the interface. These are the default mixins, but can be overridden by subinterfaces or at start-up time.

Thirdly, the mixin implementations declares “implements Person” but does not implement all methods. To avoid compiler complaining about that, we need them to be abstract. But Polygene will make that work anyway.

Fourthly, the @This annotation makes it possible to reach inside the private state of the Composite that the mixin is part of.

So how do I instantiate a Value now?

It is very similar to before.

public class SomeImplementationClass
{
    @Structure 
    ValueBuilderFactory vbf;

    public Person createPerson( String name, LocalDate birthDate )
    {
        ValueBuilder<Person> builder = 
            vbf.newValueBuilder( Person.class );

        Person.State prototype = 
            builder.prototypeFor(Person.State.class);

        prototype.name().set( name );
        prototype.dateOfBirth().set( birthdate );
        return builder.newInstance();
    }
}

The only difference is the prototypeFor() which needs the type of the interface where the state is declared. Note, the private state interface does not necessarily need to be an inner interface. It is just a convention used to keep state and behavior together.

How about creating Entities that can be persisted?

Glad you asked. It is very similar, but all entity operations must happen within a UnitOfWork, similar to a database transaction but different enough to validate a different name. Creation of UnitOfWork will be explained later, let’s for now just assume that it has been set up.

public class SomeImplementationClass
{
    @Structure 
    UnitOfWorkFactory uowf;

    public Person createPerson( String name, LocalDate birthDate )
    {
        UnitOfWork uow = uowf.currentUnitOfWork();

        EntityBuilder<Person> builder = 
            uow.newEntityBuilder( Person.class );

        Person.State instance = 
            builder.instanceFor( Person.State.class );
        instance.name().set( name );
        instance.dateOfBirth().set( birthdate );
        return builder.newInstance();
    }
}

As you can see, it is very similar. “instanceFor” instead of “prototypeFor” is to make it explicit that in the entity case, we can’t use it to create multiple entities with small changes.

It is important to understand that entities (and UnitOfWork itself) are thread-bound and it is not possible to pass an entity to another thread. And since Values are immutable, allowing the user to ignore threading issues in these meta types.

So I can create an Entity, but how do I get retrieve one from persistence?

Entities can only be retrieved by direct fetch via its Identity. In the example above, we didn’t provide an Identity, so it was generated automatically, but we could have given an explicit identity in the “newEntityBuilder()” method.

Identity identity = new StringIdentity( "Niclas Hedhman" );
EntityBuilder<Person> builder = 
    uow.newEntityBuilder( Person.class, identity );

So IF you know the identity of the entity, then you can easily retrieve it

Identity identity = new StringIdentity( "Niclas Hedhman" );
UnitOfWork uow = uowf.currentUnitOfWork(); 
Person p = uow.get( Person.class, identity );

Also, any entity that is referenced by Association, ManyAssociation and NamedAssociation are retrieved automatically in the same direct fashion under the hood. And in many cases, there is no need for any additional lookup of entities, but often query capabilities are required. We leave that for the next article about Polygene.

Where are the entities stored?

Entities are stored in, well, Entity Stores. Users can implement the Entity Store Extension SPI themselves, or choose among a dozen or so implementations available at the time of writing, and new ones are added regularly.

During development, it is rather convenient to have a in-memory entity store, that doesn’t depend on any external systems and perhaps have LevelDB for the production setup. This is all decided during “assembly of the application”, which happens at startup. The model is created, then activated, before the Polygene engine takes control of Composite generation and much more. So, we can write something like,

public void assemble( ModuleAssembly module )
{
    // mode might be a command line argument, system property, ...
    if( mode == Mode.production )
    { 
        new LevelDBEntityStoreAssembler().assemble( module );
    }
    else
    {
        new MemoryEntityStoreAssembler().assemble( module );
    }
}

No other changes are needed, which simplifies development significantly compared to always need a SQL database at hand when working with EJB, JPA, JDO and others.

The following Entity Store implementations are under development and to be part of Polygene 3.0, expected to be released in May 2017.

Apache Cassandra
File system
Apache Geode
Hazelcast
Apache JClouds
JDBM
LevelDB
Memory
MongoDB
Java Preferences
Redis
Riak
SQL (Postgres, MySQL/MariaDB, SQLite, Derby, H2)

The Extensions SPI was mentioned. What other Extensions are available?

There are 5 areas where the Polygene Runtime can be extended,

  1. Entity Stores
  2. Indexing/Query (see next article)
  3. Serialization
  4. Caching
  5. Metrics

It is beyond the scope of this article to cover these topics and will be covered in later articles on this blog.