Skip to content
Martin Ledvinka edited this page Jun 27, 2023 · 3 revisions

Static metamodel works analogously to JPA static metamodel. It is a set of classes with public static constants representing the metamodel attributes of the corresponding entity class. The following snippet shows an example entity class and the corresponding static metamodel class:

@OWLClass(iri = "sioc:Usergroup")
public class UserGroup extends AccessControlAgent {

  @Id
  private URI uri;

  @ParticipationConstraints(nonEmpty = true)
  @OWLAnnotationProperty(iri = "dc:title")
  private String label;

  @OWLObjectProperty(iri = "sioc:has_member", fetch = FetchType.EAGER)
  private Set<User> members;
}

@StaticMetamodel(UserGroup.class)
public abstract class UserGroup_ {

  public static volatile Identifier<UserGroup, URI> uri;
  public static volatile SingularAttribute<UserGroup, String> label;
  public static volatile SetAttribute<UserGroup, User> members;
}

Static metamodel is populated by the persistence unit on its startup and can be used to prevent runtime errors when referencing metamodel elements (typos in attribute names) mainly in two scenarios in JOPA:

  1. Working with descriptors
  2. Writing Criteria API queries

In both cases the static metamodel allows to reference attributes in such a way that is verified by the compiler as opposed to verification by the metamodel at runtime. See the following example:

// Using dynamic metamodel, typo in attribute name leads to failures at runtime
final Descriptor descriptor = new EntityDescriptor(URI.create(StaticContexts.USER_GROUPS));
descriptor.addAttributeContext(em.getMetamodel().entity(UserGroup.class).getAttribute("members"), null);

// Using static metamodel, attribute reference is verified by the compiler
final Descriptor descriptor = new EntityDescriptor(URI.create(StaticContexts.USER_GROUPS));
descriptor.addAttributeContext(UserGroup_.members, null);

Generator

There is a generator of static metamodels in JOPA. This generator uses Java annotation processing and thus can be used in two ways:

  1. As annotation processor
  2. Via the JOPA Maven plugin

Annotation Processor

The ModelGenProcessor can be used directly as a Java annotation processor, for example, via the Maven Compiler plugin:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <annotationProcessors>
      <annotationProcessor>
        cz.cvut.kbss.jopa.modelgen.ModelGenProcessor
      </annotationProcessor>
    </annotationProcessors>
    <annotationProcessorPaths>
      <annotationProcessorPath>
        <groupId>cz.cvut.kbss.jopa</groupId>
        <artifactId>modelgen</artifactId>
      </annotationProcessorPath>
    </annotationProcessorPaths>
  </configuration>
</plugin>

Maven Plugin

The static metamodel generator is also integrate into the JOPA Maven plugin. The following snippet show a typical configuration:

<plugin>
  <groupId>cz.cvut.kbss.jopa</groupId>
  <artifactId>jopa-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>generate-static-metamodel</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>modelgen</goal>
      </goals>
      <configuration>
        <source-package>cz.cvut.kbss.termit.model</source-package>
      </configuration>
    </execution>
  </executions>
</plugin>

The source-package parameter specifies where the generator should look for entity classes to process.

See the thesis by Benjamin Rodr who implemented the static metamodel generator in JOPA for details.