Elastic Path Commerce Development

Extension Core Module Structure

Extension Core Module Structure

Use the extensions/core/ext-core module to customize and extend core functionalities. This module can include extensions to classes in ep-core as well as modules that ep-core depends on, such as ep-settings or ep-persistence-openjpa. It can also include new functionalities required for other extension modules.

The ext-core module has the following structure:

ext-core
   src  
      main
         java
            com
               java 
                   // Extension classes go here
                resources
                   META-INF
                      conf 
                         ep-core-plugin.xml   // Spring definitions and overrides 
                      jpa-persistence.xml     // OpenJPA persistence additions and overrides                   
                   OSGI-INF 
                      blueprint 
                         springCtx-import.xml // OSGi blueprint descriptor file
   pom.xml 

OSGi configuration

Cortex runs in an OSGi container. Any library that Cortex uses must be packaged as an OSGi bundle. This section describes how ext-core is configured for OSGi.

Extension pom.xml

The key OSGi configuration is highlighted in this snippet from the core extension's pom.xml.

<artifactId>ext-core</artifactId>
<packaging>bundle</packaging>
 ...
<build>
   <plugins>
      <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <extensions>true</extensions>
          <configuration>
             <instructions>
                <!-- Fragment-Host gives the symbolic name of the core wrapper bundle to attach to. -->
                <Fragment-Host>ext-commerce-engine-wrapper</Fragment-Host>
                <Import-Package>
                   !*
                </Import-Package>
                ...
             </instructions>
          </configuration>
      </plugin>

<packaging>bundle</packaging>

The first OSGi configuration data in the POM is the project's packaging <packaging>bundle</packaging> data. With this setting, Maven builds the project as an OSGi bundle. The project still builds into a JAR file, so the project can be used outside of an OSGi setting, which means you can leave this as is even if you are not using the core extension in an OSGi setting.

maven-bundle-plugin

The maven-bundle-plugin configuration transforms the core extension into a OSGi fragment and tells the fragment to attach to Cortex's ext-commerce-engine-wrapper bundle.. The extension commerce engine wrapper bundle wraps the core extension in an OSGi bundle. Fragments are treated as part of the host bundles. Relevant definitions of the fragment are merged with the definitions of the host bundle before the host is resolved, as long as the information does not conflict. If possible, fragment dependencies are resolved. However, if the fragment dependencies cannot be resolved, the fragment is not attached to the host bundle. A fragment cannot have its own class loader or bundle activator. It cannot override the information present in the host bundles. Fragments extend bundles with resources, classes, and permitted headers to customize your bundles.

<Import-Package>

The <Import-Package> element contributes any additional imports to the core bundle. Add !* in the <Import-Package> element if you do not want to import anything to the core bundle. If your core extension relies on additional third party libraries,other than the libraries already used by the core bundle, you must list the required packages in the <Import-Package> instruction. You must also include the manifest header directive value identifying a mandatory resolution type to enable attachment problem logging. For example:

<Import-Package>
  org.thirdparty.library.package; resolution:=mandatory,
  !*
</Import-Package>

If you do not specify the mandatory resolution, OSGI does not find the third party library package at run time and the fragment fails to attach, however, no error message appears.

springCtx-import.xml

This file provides information about the spring configuration for the extension project to OSGi.

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >

    <!-- Let OSGI know the spring configuration of this project. -->
    <import resource="../../META-INF/conf/ep-core-plugin.xml" />
</beans>

Notes

  • Core extension classes replacing the default core classes, which have the same package structure and class name, do not work with this approach.
  • If the extension uses third party libraries, the following additional configuration is required:
    • Add the third party packages to the <Import-Package> element as described in the Extension pom.xml section.
    • If the third-party libraries are OSGi compliant, add the libraries as a dependency and artifact items in the Cortex Webapp.
    • If the libraries are not OSGi compliant, the libraries must be embedded in the fragment.

jpa-persistence.xml

The core extension's jpa-persistence.xml file specifies the following:

<persistence-unit name="commerce-persistence-unit">
   ...
   <mapping-file>...</mapping-file>

   <class>...</class>

   <exclude-unlisted-classes>true</exclude-unlisted-classes>

   <validation-mode>NONE</validation-mode>

   <properties>
      <property name="openjpa.Log" value="slf4j"/>
      <property name="openjpa.DetachState" value="loaded(DetachedStateField=true)"/>
   </properties>

</persistence-unit>
  • <mapping-file> - Defines the classpath for new ORM metadata mapping files.
  • <class> - Defines the fully qualified class names of the new persistent classes.
  • <exclude-unlisted-classes> - Must be set to true so that OpenJPA will scan only the classpaths of the listed classes. OSGI does not permit scanning of unlisted clases.
  • <validation-mode> - Must be set to NONE, so that OpenJPA does not automatically perform JSR 330 validation on objects persisted to the database.
  • <properties> - Must have values as shown above. openjpa.DetachState is used during OpenJPA byte code enhancement.
    Important: Do not add additional properties here. To add or override OpenJPA properties, see Override Persistence Unit Properties.

For more information about how to exclude existing ORM mapping files and/or persistent classes, see Exclude references from the Persistence Unit.