Tutorial – Getting started with TRIMM JPA

This tutorial will take you through the process of creating a completely new Maven based Java project that uses TRIMM JPA to generated JPA (with support for Hibernate extension).

Prerequisites:

Step 1 – Create a TRIMM JPA enabled Maven project

Execute the following command through your commandline/terminal:

mvn archetype:generate -DarchetypeGroupId=dk.tigerteam.maven.archetypes -DarchetypeArtifactId=trimm.jpa.archetype 
-DarchetypeVersion=1.0.0 
-DarchetypeCatalog=http://www.tigerteam.dk/maven2/archetype-catalog.xml

and for this example we will provide the following values:

groupId dk.tigerteam.trimm.examples
artifactId firstjpaproject
version 1.0-SNAPSHOT
package dk.tigerteam.trimm.examples.firstjpaproject
Create TRIMM JPA enabled Maven Project

Create TRIMM JPA enabled Maven Project

Step 2 – Import the TRIMM enabled Maven project into your IDE

For IntelliJ follow the steps in this tutorial

Step 3 – Model your domain model in UML using Enterprise Architect (EA)

Follow the instructions here to model a simple Domain model that will be used for code generating a JPA entity model.

Step 4 Export your UML domain model to XMI

Follow the steps in this guide for Enterprise Architect.

Step 5 Configure the TRIMM JPA Maven plugin to generate sourcecode

The TRIMM JPA code generation functionality is defined in the projects Maven configuration file called pom.xml which is placed in the root of the project folder (e.g. C:\TRIMM-examples\firstjpaproject)

Within the pom.xml, inside the build/plugins section you will find the TrimmJpaMavenPlugin plugin

    
          <plugin>
                <groupId>dk.tigerteam</groupId>
                <artifactId>TrimmJpaMavenPlugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <id>generate</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <yamlFile>model/JpaModel.yml</yamlFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

You can see from the value inside the yamlFile the configuration file that is used to configure the TrimmJpaMavenPlugin plugin.
In this case it’s the JpaModel.yml which is placed inside the model folder of the project, together with our EA project file (FirstJPAModel.eap) and our XMI export from Step 4 (model.xml).

JpaModel.yml location

JpaModel.yml location

TRIMM JPA YAML configuration file

The TRIMM (currently) default configuration file is based on YAML which is a reading friendly file format.

Below is the complete configuration, JpaModel.yml, for our tutorial (everything with a # in front of it is a comment):

    
#Setup
xmiModelPath: model/model.xml
umlTool: EA
basePackageName: dk.tigerteam.trimm.examples.firstjpaproject
generateExtensionClasses: false

# Paths
generateBaseClassesToPath: target/generated-sources/domainmodel
generateInterfacesToPath: target/generated-sources/domainmodel
generateTestClassesToPath: target/generated-sources/generated-tests
generateResourcesToPath: target/generated-sources/generated-resources

mapUmlPropertyTypes:
    - name: LocalDate
      javaType: org.joda.time.LocalDate
      jpaTypeConverterClass: org.joda.time.contrib.hibernate.PersistentLocalDate

# JPA Setup
jpaSetup:
    addTableAndColumnNames: false
    defaultToLazyFetchingForAllAssociations: true
    rootMappedSuperClass: dk.tigerteam.trimm.examples.firstjpaproject.model.AbstractEntity

# Extensions
eventListeners:
    - dk.tigerteam.trimm.mdsd.java.generator.extension.BidirectionalGeneratorEventListener
    - dk.tigerteam.trimm.mdsd.java.generator.extension.SerialVersionUIDGeneratorListener
    - dk.tigerteam.trimm.mdsd.java.generator.extension.PropertySugarMethodsEventListener
    - dk.tigerteam.trimm.mdsd.jpa.Jpa2OrphanRemovalListener

# Create Runtime Meta Model
createRuntimeMetaModel:
    packageName: dk.tigerteam.trimm.examples.firstjpaproject.model.meta

# Create JPA Integration tests for all entities
createIntegrationTest:
    testClassName: CompleteModelIntegrationTest
    testPackageName: dk.tigerteam.trimm.examples.firstjpaproject.model
    extendsClass: dk.tigerteam.trimm.examples.firstjpaproject.model.BaseJpaModelTest
    autoHandleTransactionsAndResources: true

Explanation for the configuration parameters:

ParameterValueExplanation
xmiModelPathdk.tigerteam.trimm.examples.firstjpaprojectThe relative path to our XMI export file
basePackageNamedk.tigerteam.trimm.examples.firstjpaprojectThis package will pre-appended all generated packages, classes, interfaces, etc. Since we export the model package in EA this means that our Member, Offer, OfferType and ExpirationType will be generated into the package dk.tigerteam.trimm.examples.firstjpaproject.model
generateExtensionClassesfalseMeans that we will NOT generate using the Generator Gap pattern. This basically means that any changes you the developer would make to the generated code will be overwritten next time the TRIMM JPA plugin is run

ParameterValueExplanation
generateBaseClassesToPathtarget/generated-sources/domainmodelWhen generating without the Generator Gap pattern, then most classes generated (except interfaces) qualify as Base classes.
As can be seen, we generated to a java code subfolder of the target/generated-sources folder, which means that all generated code will be placed inside Mavens preferred location for intermediate code that isn’t checked into source control (which is recommended)
generateInterfacesToPathdk.tigerteam.trimm.examples.firstjpaprojectAny interfaces generated are placed in this java code folder (same as above)
generateTestClassesToPathfalseAny test classes (i.e. code that doesn’t qualify as runtime code) gets generated to this java test code folder
generateResourcesToPathfalseAny resources (such as text files, xml, orm.xml, etc) gets generated to this resource folder
ParameterValueExplanation
nameLocalDateThe full name of an attribute/parameter type defined in the UML model
javaTypeorg.joda.time.LocalDateDescribes which Java class to use when (in this case) LocalDate is used in the UML model
jpaTypeConverterClassorg.joda.time.contrib.hibernate.
PersistentLocalDate
Describes which Hibernate EnhancedUserType that should be used (is indicated in the generated code using @org.hibernate.annotations.Type – or if you use EclipseLink then it represents which @org.eclipse.persistence.annotations.Converter to use)
ParameterValueExplanation
addTableAndColumnNamesfalseThis setting controls whether JPA defaults should apply or if TRIMM JPA should place @JoinTable, @Column, etc. annotations to control table and column mapping names. In this case we rely on JPA defaults
defaultToLazyFetchingForAllAssociationstrueHere we force all JPA associations to be default lazy and thereby overrule JPA defaults
rootMappedSuperClassdk.tigerteam.trimm.examples.
firstjpaproject.model.AbstractEntity
Here we insert a class of your choosing at the top of every inheritance hierarchy. In this case we chose a hand written class called AbstractEntity, which in our example defines @Id field
ListenerExplanation
BidirectionalGeneratorEventListenerThis listener will insert code into property accessors (e.g. getOrder() or getOrderLinesCollection()) that will ensure that associations that are defined as bi-directional in your UML also support that same in-memory (e.g. so customer.setAddress(address), will ensure that the generated code will call address.setCustomer(inverseCustomer) so that both customer and address have a pointer to each other in memory)
SerialVersionUIDGeneratorListenerThis listener will generate a private static final long serialVersionUID field in every generated class
PropertySugarMethodsEventListenerThis listener will generate fluent interface methods such as withXxxx or addToXxxxCollection properties
Jpa2OrphanRemovalListenerThis listener will investigate the UML model and in case associations adhere to the JPA rules of Orphan Removal, then a @OrphanRemoval annotation will be applied automatically
ParameterValueExplanation
packageNamedk.tigerteam.trimm.examples.
firstjpaproject.model.meta
This parameter control under which package the RuntimeMetaModel should be generated
ParameterValueExplanation
testClassNameCompleteModelIntegrationTestDetermines the name of the JUnit 4 class which control the test of all Entities in the Model
testPackageNamedk.tigerteam.trimm.examples.
firstjpaproject.model
Determines under which package te testClassName (in our case CompleteModelIntegrationTest) will be placed.
extendsClassdk.tigerteam.trimm.examples.
firstjpaproject.model.BaseJpaModelTest
Determines which hand written class to extend from. This class control initialization of the JPA EntityManagerFactory/EntityManager. The only requirement is that the class inherits from dk.tigerteam.trimm.persistence.mdsd.
test.AbstractModelTest
autoHandleTransactionsAndResourcestrueControl whether the code that’s generated into the testClassName (in our case CompleteModelIntegrationTest) should control transactions (begin and rollback)

This configuration section control whether a Runtime version of the MetaModel (that’s a representation of the UML model) will be generated.Explanation for the Create JPA Integration tests for all entities configuration parameters.
This section controls whether a complete JUnit 4 test suite, that integration tests the generated JPA model against a database of your choice, will be generated.

5.1 – Completing the configuration with handwritten classes

Before we can complete the code generation part for this example we need to provide implementations for the handwritten classes we specified in the configuration, specifically the JPA rootMappedSuperClass and JPA Unit test extendsClass.

5.1.1 – Provide the TRIMM JPA RootMappedSuperClass

In the IDE select the src/main/java folder (see picture for IDEA) and select New Package dk.tigerteam.trimm.examples.firstjpaproject.model

Create package for TRIMM JPA RootMappedSuperClass
Create package for TRIMM JPA RootMappedSuperClass

After this add Class AbstractEntity to the newly created dk.tigerteam.trimm.examples.firstjpaproject.model package:

Create JPA AbstractEntity class
Create JPA AbstractEntity class

Paste the following content into the newly created AbstractEntity class:

 
package dk.tigerteam.trimm.examples.firstjpaproject.model;

import javax.persistence.*;

@MappedSuperclass
public class AbstractEntity {
  @Id
  @SequenceGenerator(name = "FIRST_JPA_GEN", sequenceName = "FIRST_JPA_SEQ")
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "FIRST_JPA_GEN")
  private Long id;


  public Long getId() {
    return id;
  }
}

5.1.2 – Provide the TRIMM JPA Unit test ExtendsClass

In the IDE select the src/test/java (as we’re creating test related code) and select New Package dk.tigerteam.trimm.examples.firstjpaproject.model:

Create package for JPA Unit test ExtendsClass
Create package for JPA Unit test ExtendsClass

After this add Class BaseJpaModelTest to the newly created dk.tigerteam.trimm.examples.firstjpaproject.model package:

Create BaseJpaModelTest class
Create BaseJpaModelTest class

Paste the following content into the newly created BaseJpaModelTest:

     
package dk.tigerteam.trimm.examples.firstjpaproject.model;


import dk.tigerteam.trimm.mdsd.runtime.RuntimeMetaClazz;
import dk.tigerteam.trimm.mdsd.runtime.RuntimeMetaProperty;
import dk.tigerteam.trimm.persistence.mdsd.test.AbstractModelTest;
import dk.tigerteam.trimm.persistence.mdsd.test.RuntimeMetaTestDataCreator;
import dk.tigerteam.trimm.persistence.util.HibernateProxyHandler;
import dk.tigerteam.trimm.persistence.util.ObjectPrinter;
import dk.tigerteam.trimm.persistence.util.ProxyHandler;
import dk.tigerteam.trimm.util.IndentPrintWriter;
import org.joda.time.LocalDate;
import org.junit.AfterClass;
import org.junit.BeforeClass;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.lang.reflect.Field;
import java.util.Set;

public class BaseJpaModelTest extends AbstractModelTest {
  private static EntityManagerFactory emf;

  @BeforeClass
  public static void setup() {
    emf = Persistence.createEntityManagerFactory("firstjpamodel");
  }

  @AfterClass
  public static void teardown() {
    emf.close();
  }

  @Override
  public EntityManager getEntityManager() {
    return emf.createEntityManager();
  }

  @Override
  public ProxyHandler getProxyHandler(EntityManager entityManager) {
    return new HibernateProxyHandler(entityManager);
  }

  @Override
  public Field[] getIgnoreFieldsDuringGraphCompare(Class<?> aClass) {
    return new Field[0];
  }

  // Support for pretty printing tests errors that contain LocalDate
  @Override
  public ObjectPrinter[] getObjectPrinters() {
    return new ObjectPrinter[]{new ObjectPrinter() {
      @Override
      public boolean support(Object object) {
        return object instanceof LocalDate;
      }

      @Override
      public void print(Object object, Set<Object> printedObjects, IndentPrintWriter printWriter) {
        printWriter.print(((LocalDate) object).toString());
      }
    }};
  }

  // Support for LocalDate in test data
  @Override
  protected RuntimeMetaTestDataCreator lazyCreateDataCreator() {
    return new RuntimeMetaTestDataCreator() {
      @Override
      protected Object newInstance(RuntimeMetaClazz metaClazz,
                                   ObjectInstancesStack objectInstancesStack,
                                   RuntimeMetaProperty metaProperty) {
        Class<?> _class = metaClazz.getJavaClass();
        if (_class != null &amp;&amp; LocalDate.class.equals(_class)) {
          return new LocalDate();
        } else {
          return super.newInstance(metaClazz, objectInstancesStack, metaProperty);
        }
      }
    };
  }
}

The first thing to notice is the public static void setup() method where we initialize a JPA EntityManagerFactory for a PersistenceUnit called “firstjpamodel”.
This PersistenceUnit needs to be configured, otherwise the unit test wont pass.If you want to use the same PersistenceUnit configuration for both test and normal runtime purposes, then you should place your persistence.xml file in src/main/resources/META-INF otherwise, as for this example, we will define a special unit test PersistenceUnit configuration that uses an in memory database (H2) during testing. For this purpose, we place our persistence.xml in src/test/resources/META-INF.First you need to create the META-INF folder inside the src/test/resources folder. Select the src/test/resources folder and choose New Package META-INF (don’t mind that IDEA complains about invalid package name – just ignore the warning and press OK):

Create META-INF folder
Create META-INF folder

Create a file called persistence.xml (which is the default filename for JPA PersistenceUnit configurations). Choose the src/test/resources/META-INF folder/package and select New File persistence.xml:

Create persistence.xml file
Create persistence.xml file

Paste the following content into the newly created persistence.xml file: org.hibernate.ejb.HibernatePersistence META-INF/orm.xml true This configures JPA to use Hibernate as provider and use the H2 database in an in-memory mode.Final step – Enable additional Maven dependenciesTo complete the configuration we need to enable additional Maven dependencies in the pom.xml file, so that we can use Hibernate, H2, etc.Open pom.xml and uncomment additional dependencies that are currently commented out.
The complete pom.xml should look like this:

   
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>dk.tigerteam.trimm.examples</groupId>
    <artifactId>firstjpaproject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>firstjpaproject</name>

    <url>trimm.tigerteam.dk</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <default.encoding>UTF-8</default.encoding>
        <default.jdk.version>1.6</default.jdk.version>
        <hibernate.version>3.6.10.Final</hibernate.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>dk.tigerteam</groupId>
            <artifactId>TrimmCore</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>dk.tigerteam</groupId>
            <artifactId>TrimmJpa</artifactId>
            <version>1.0.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.173</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>1.6.2</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time-hibernate</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-legacy</artifactId>
            <version>4.0.2.GA</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${default.jdk.version}</source>
                    <target>${default.jdk.version}</target>
                    <encoding>${default.encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>dk.tigerteam</groupId>
                <artifactId>TrimmJpaMavenPlugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <id>generate</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <yamlFile>model/JpaModel.yml</yamlFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>tigerteam-maven2-repository</id>
            <name>tigerteam.dk Repository for Maven 2</name>
            <url>http://www.tigerteam.dk/maven2/</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>tigerteam-maven2-repository</id>
            <name>tigerteam.dk Repository for Maven 2</name>
            <url>http://www.tigerteam.dk/maven2/</url>
        </pluginRepository>
    </pluginRepositories>

</project>

Step 6 Generate code using TRIMM JPA

After you have completed Step 1 to 5 you now have a completely configured TRIMM JPA project.
From here on, you can make small changes to the UML model (and re-export) or to the configuration and complete the code generation phase as often as you want.So let’s get to it, to generate code you run at least the maven generate-sources lifecycle (i.e. if you run any lifecycle after that such as compile, test, package or install then code will also be generated) mvn generate-sources This will look something like this

Maven generate-sources for TRIMM JPA
Maven generate-sources for TRIMM JPA

(note the long generation time is due to downloading of latest Maven snapshots, which can be turned off)But since we used an IDE for all the other things we didn’t, we could also use the IDE for initiating the code generation.
Since we configured TRIMM JPA to use maven source- and resource-folders the easiest way to generate code from within IntelliJ IDEA and also have IDEA configure source folders for the IDE project is to right click the root of the project, select Maven > Generate Sources and Update Folders:

IDEA Maven Generate Sources and Update Folders (TRIMM JPA)
IDEA Maven Generate Sources and Update Folders (TRIMM JPA)

After completing this step the IDEA project should have the following configuration/source/test folders:

IntelliJ IDEA TRIMM JPA project after Maven initiated Code Generation
IntelliJ IDEA TRIMM JPA project after Maven initiated Code Generation

Step 7 – Running the generated JPA Unit test

To verify that all code generated is working and all JPA code and mappings are correct, we can execute the generated JPA Unit test (which is an integration test as it works against an external resource – the database).
To do this either run (from the command line): mvn test Or select the CompleteModelIntegrationTest in target/generated-sources/generated-tests/dk.tigerteam.trimm.examples.firstjpaproject.model and choose Run.. in IDEA:

Run CompleteModelIntegrationTest (TRIMM JPA)
Run CompleteModelIntegrationTest (TRIMM JPA)

The result should look like this:

Run CompleteModelIntegrationTest result (TRIMM JPA)
Run CompleteModelIntegrationTest result (TRIMM JPA)

Step 8 – Taking it one step further – using Generator Gap/Extension Classes pattern (optional)

This step is optional, but sometimes it’s nice or even necessary to be able to add code to generated source code.

Don’t edit generated sourcecode by hand!

Editing generated sourcecode by hand is bad practice – your changes will be overwritten the next time you generate. Instead you should apply the Generator Gap pattern – which is called Extension Classes in TRIMM Java/JPA

To enable Extension Classes (Generator Gap Pattern) for TRIMM JPA all you need to do is add the following configurations to the JpaModel.yml configuration file:

  • Change generateExtensionClasses to true
  • Add addExtensionAndBaseClassAnnotations: true to the same Setup section. These annotations are required by the JPA Unit test code
  • Add generateExtensionClassesToPath: src/main/domainmodel-extensions to the Paths section. This will ensure that extension classes (the concrete classes that you can hand edit) are generated to a folder inside src/main so that it can come under source control.
  • Add makeBaseClassesIntoMappedSuperClassesIfPossible: true to the JPA Setup section. This will optimize JPA inheritance mapping code, so that real Abstract classes don’t consume additional tables in case you later opt for another inheritance scheme than Single table.

The complete configuration is show here:

#Setup
xmiModelPath: model/model.xml
umlTool: EA
basePackageName: dk.tigerteam.trimm.examples.firstjpaproject
generateExtensionClasses: true
addExtensionAndBaseClassAnnotations: true


# Paths
generateBaseClassesToPath: target/generated-sources/domainmodel
generateExtensionClassesToPath: src/main/domainmodel-extensions
generateInterfacesToPath: target/generated-sources/domainmodel
generateTestClassesToPath: target/generated-sources/generated-tests
generateResourcesToPath: target/generated-sources/generated-resources

mapUmlPropertyTypes:
    - name: LocalDate
      javaType: org.joda.time.LocalDate
      jpaTypeConverterClass: org.joda.time.contrib.hibernate.PersistentLocalDate

# JPA Setup
jpaSetup:
    addTableAndColumnNames: false
    makeBaseClassesIntoMappedSuperClassesIfPossible: true
    generatePresentFieldInEmbeddables: false
    defaultToLazyFetchingForAllAssociations: true
    rootMappedSuperClass: dk.tigerteam.trimm.examples.firstjpaproject.model.AbstractEntity


# Extensions
eventListeners:
    - listener: dk.tigerteam.trimm.mdsd.java.generator.extension.BidirectionalGeneratorEventListener
    - listener: dk.tigerteam.trimm.mdsd.java.generator.extension.SerialVersionUIDGeneratorListener
    - listener: dk.tigerteam.trimm.mdsd.java.generator.extension.PropertySugarMethodsEventListener
    - listener: dk.tigerteam.trimm.mdsd.jpa.Jpa2OrphanRemovalListener

# Create Runtime Meta Model
createRuntimeMetaModel:
    packageName: dk.tigerteam.trimm.examples.firstjpaproject.model.meta

# Create JPA Integration tests for all entities
createIntegrationTest:
    testClassName: CompleteModelIntegrationTest
    extendsClass: dk.tigerteam.trimm.examples.firstjpaproject.model.BaseJpaModelTest
    testPackageName: dk.tigerteam.trimm.examples.firstjpaproject.model
    autoHandleTransactionsAndResources: true
ParameterValueExplanation
xmiModelPathdk.tigerteam.trimm.examples.firstjpaprojectThe relative path to our XMI export file
basePackageNamedk.tigerteam.trimm.examples.firstjpaprojectThis package will pre-appended all generated packages, classes, interfaces, etc. Since we export the model package in EA this means that our Member, Offer, OfferType and ExpirationType will be generated into the package dk.tigerteam.trimm.examples.firstjpaproject.model
generateExtensionClassesfalseMeans that we will NOT generate using the Generator Gap pattern. This basically means that any changes you the developer would make to the generated code will be overwritten next time the TRIMM JPA plugin is run
ParameterValueExplanation
generateBaseClassesToPathtarget/generated-sources/domainmodelWhen generating without the Generator Gap pattern, then most classes generated (except interfaces) qualify as Base classes.
As can be seen, we generated to a java code subfolder of the target/generated-sources folder, which means that all generated code will be placed inside Mavens preferred location for intermediate code that isn’t checked into source control (which is recommended)
generateInterfacesToPathdk.tigerteam.trimm.examples.firstjpaprojectAny interfaces generated are placed in this java code folder (same as above)
generateTestClassesToPathfalseAny test classes (i.e. code that doesn’t qualify as runtime code) gets generated to this java test code folder
generateResourcesToPathfalseAny resources (such as text files, xml, orm.xml, etc) gets generated to this resource folder
ParameterValueExplanation
nameLocalDateThe full name of an attribute/parameter type defined in the UML model
javaTypeorg.joda.time.LocalDateDescribes which Java class to use when (in this case) LocalDate is used in the UML model
jpaTypeConverterClassorg.joda.time.contrib.hibernate.
PersistentLocalDate
Describes which Hibernate EnhancedUserType that should be used (is indicated in the generated code using @org.hibernate.annotations.Type – or if you use EclipseLink then it represents which @org.eclipse.persistence.annotations.Converter to use)
ParameterValueExplanation
addTableAndColumnNamesfalseThis setting controls whether JPA defaults should apply or if TRIMM JPA should place @JoinTable, @Column, etc. annotations to control table and column mapping names. In this case we rely on JPA defaults
defaultToLazyFetchingForAllAssociationstrueHere we force all JPA associations to be default lazy and thereby overrule JPA defaults
rootMappedSuperClassdk.tigerteam.trimm.examples.
firstjpaproject.model.AbstractEntity
Here we insert a class of your choosing at the top of every inheritance hierarchy. In this case we chose a hand written class called AbstractEntity, which in our example defines @Id field
ListenerExplanation
BidirectionalGeneratorEventListenerThis listener will insert code into property accessors (e.g. getOrder() or getOrderLinesCollection()) that will ensure that associations that are defined as bi-directional in your UML also support that same in-memory (e.g. so customer.setAddress(address), will ensure that the generated code will call address.setCustomer(inverseCustomer) so that both customer and address have a pointer to each other in memory)
SerialVersionUIDGeneratorListenerThis listener will generate a private static final long serialVersionUID field in every generated class
PropertySugarMethodsEventListenerThis listener will generate fluent interface methods such as withXxxx or addToXxxxCollection properties
Jpa2OrphanRemovalListenerThis listener will investigate the UML model and in case associations adhere to the JPA rules of Orphan Removal, then a @OrphanRemoval annotation will be applied automatically
ParameterValueExplanation
packageNamedk.tigerteam.trimm.examples.
firstjpaproject.model.meta
This parameter control under which package the RuntimeMetaModel should be generated
ParameterValueExplanation
testClassNameCompleteModelIntegrationTestDetermines the name of the JUnit 4 class which control the test of all Entities in the Model
testPackageNamedk.tigerteam.trimm.examples.
firstjpaproject.model
Determines under which package te testClassName (in our case CompleteModelIntegrationTest) will be placed.
extendsClassdk.tigerteam.trimm.examples.
firstjpaproject.model.BaseJpaModelTest
Determines which hand written class to extend from. This class control initialization of the JPA EntityManagerFactory/EntityManager. The only requirement is that the class inherits from dk.tigerteam.trimm.persistence.mdsd.
test.AbstractModelTest
autoHandleTransactionsAndResourcestrueControl whether the code that’s generated into the testClassName (in our case CompleteModelIntegrationTest) should control transactions (begin and rollback)

When you run mvn generate-sources or select IntelliJ IDEA’s Maven > Generate Source and Update Folders option, then the result should look like this:

Project with Extension Classes enabled
Project with Extension Classes enabled

It’s now possible to go into the concrete classes and add custom logic.

< Back