Skip to content
Martin Goellnitz edited this page Dec 4, 2016 · 4 revisions

The Data Model

The foundation of data driven web applications obviously is the data model. To avoid re-inventing the wheel, we rely on proven ORM solutions for the Java environment but have to add a little more specific details.

The available ORMs / storage backends are:

  • Java Data Objects (JDO)
  • CoreMedia Adaptor (CoMA)
  • MongoDB Morphia
  • Objectify
  • Java Persistence API (JPA)
  • EBean

JDO

The first implementation of a storage layer for Tangram was the Java Data Objects (JDO) implementation DataNucleus Access Plattform. There is no second implementation of JDO available. The separate Package org.tangram.nucleus as the specialized variant of org.tangram.jdo stems from the formlerly available org.tangram.gae which also used this API.

To be able to use DataNucleus, that compiled classes need to be "enhanced" (byte code transformed to include database acccess methods). The gradle-tangram plugin does this automatically for you. If you don't want to use that plugin refer to the DataNucleus documentation.

With the JDO solution it is also possible to place model classes as code resources in the JDO based storage backend.

These classes are created as instances of org.tangram.nucleus.Code with a mime type of application/x-groovy. The code needs too be a full persistence capable class implementation for JDO/DataNucleus and can be a subclass of the Java based static classes. The annotation is not important in this case. It is recommended to place the name of the superclass of the implemented class here, to receive help items in the Tangram editor left of the code text.

After the start of the application these models are added to the list of available model classes and can be used like standard Java based model classes (persistence capable in JDO lingo). The byte-code transformation called "enhancing" (s.a.) is handled by an internal Tangram component internally on startup or any change of the classes in the code parts of the content repository.

CoMA

Through the CoreMedia Adaptor CoMA it is possible to use the Database of a CoreMedia (versions 5.2/2008 and up) Content Server - Content Management Server, Master Live Server, Replication Live Server - as the read only data source for a tangram instance.

The mapping of content to Java instances is quite limited at the moment since though.

JPA

Tangram contains a module JPA to use Java Persistence API based model implementations as the storage backend.

All of the supported JPA implementations need or support byte code transformations after the compilation of the model describing classes. This byte code transformation is called "enhancing" with DataNucleus, Hibernate, and OpenJPA while EclipseLink calles it "weaving".

This being said it is obvious that special variants of the module need to be available containing byte code transformed class files for the JPA implementation in use.

Except DataNucleus all of the JPA implementations also support model classes without byte code transformation and Tangram contains a "clean" version of the JPA module for that purpose.

The Tangram gradle plugin again supports automatic byte code transformation for the JPA implementation in use which is automatically discovered from the compile time class path.

EBean

EBean is a lean ORM implementation similar to JPA in its syntax for the model classes. Like with other ORM solutions the code of the model classes must be byte code transformed to be used.

Again the Tangram gradle plugin automatically discoveres the use of EBean and transforms the compiled model classes.

Morphia

When you decide to limit yourself to the use of MongoDB as your database of choice - which is very well supported with JDO/DataNucleus and supported with some JPA implementations - you can consider using the Morphia Java API for MongoDB.

With the Morphia solution it is also possible to place model classes as code resources in the - in turn - Morphia based storage backend.

These classes are created as instances of org.tangram.morpcia.Code with a mime type of application/x-groovy. The code needs too be a full entity class implementation for Morhpia and can be a subclass of the Java based static classes. The annotation is not important in this case. It is recommended to place the name of the superclass of the implemented class here, to receive help items in the Tangram editor left of the code text.

After the start of the application these models are added to the list of available model classes and can be used like standard Java based Morphia model classes (Entities in Morphia lingo). Update of the additional classes for models is handled by a Tangram component internally on startup or any change of the classes in the code parts of the content repository.

Objectify

Another data model layer option which is also related to a given backend is Objectify. It can be used in conjunction with the data store of the Google App Engine. It forms the foundation of a new Google App Engine support for Tangram.

Tangram specific Model Elements

In addition to the ORM solutions usable with Tangram there are some extensions and constraints built on top of the plain ORM layer.

Basics

The main contraint vor model classes to be usable within Tangram is, that they must implement the org.tangram.content.Content interface.

Any of the content base classes provided by the ORM specific modules of Tangram implements this interface and provides all the necessary details. If you use derived classes you are safe.

package org.tangram.example;

import javax.persistence.MappedSuperclass;
import org.tangram.content.Content;
import org.tangram.ebean.EContent;


@MappedSuperclass
public abstract class Linkable extends EContent {

    private String title;

    private String shortTitle;

    private String keywords;

} // Linkable

EBean example

Structured Text Properties

Tangram supports structured text in a property of a class. This structured text can be either HTML fragments (divs and ps) or markdown.

If the getters and setters of the property use char[] as the property type, this property is handled as a HTML fragment holder and editing takes place through the CKEditor in the Tangram editor module.

If you prefer to edit structured text as markdown, you have to wrap your internal data as org.tangram.content.Markdown.

package org.tangram.example;

import javax.jdo.annotations.PersistenceCapable;
import lombok.Getter;
import lombok.Setter;
import org.tangram.content.Markdown;


@PersistenceCapable
public class Article extends Linkable {

    @Getter
    @Setter
    private char[] text;

    private char[] markdown;


    public Markdown getMarkdown() {
        return new Markdown(markdown);
    }


    public void setMarkdown(Markdown markdown) {
        this.markdown = markdown.getContent();
    }

} // Article

JDO Example using DataNucleus Access Plattform

Besides the getter and setter constraints you are free to store the data internally as String, char[], or blob whichevery fits your storage needs better.

Taking Care of the Modification Date and Time

If you need to track the modification time of an object through the Tangram editor module, you simply have to implement the org.tangram.mutable.HasModificationTime interface and store a long value together with the needed getters and setters.

All code implementations of Tangram implement this interface, so you will be able to check when you last modified the codes stored in the Tangram repository like you can do this on you local disk storage with file containing code.

Also the ftp module has been extended to make use of the modification time field.

Pseudo Abstract Classes

In some situation you might only want to avoid that classes are instanciated through Tangram and not in general. (Sometimes there might be limitations with the model implementation leading to pseudo-abstract classes.) In such situations you can add a Tangram specific annotation @Abstract at the class level (The org.tangram.annotate.Abstract annotation) to let Tangram handle this class as if it were abstract.

package org.tangram.example;

import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import lombok.Getter;
import lombok.Setter;
import org.tangram.annotate.Abstract;
import org.tangram.content.Content;
import org.tangram.jpa.JpaContent;


@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Abstract
public class Linkable extends JpaContent {

    @Getter
    @Setter
    private String title;

    @Getter
    @Setter
    private String shortTitle;

    @Getter
    @Setter
    private String keywords;

} // Linkable

Lomboked JPA Example intended for OpenJPA

Clone this wiki locally