Core Extension Project Structure
Core Extension Project Structure
Elastic Path 6.12.0 provides a template project that extends the Commerce Engine's core library. Use this template project to customize and extend core functionality.
Your core extension module can also include extensions to classes in Elastic Path modules that core depends on, such as ep-settings or ep-persistence-openjpa.
The core library extension has the following structure:
ext-core |--src //Contains the package directory structure for the extension project. Your customized source code goes here. |----main |------java |--------com |----------java //Contains the java source extension files. |------------<package_dirs> |----------resources |------------META-INF |------------------jpa-persistence.xml //OpenJPA persistence configuration file, which is normally named persistence.xml. |------------------conf //Creates the resource representation and sets the representation's properties |--------------------ep-core-plugin.xml //Adds new bean definitions and overrides existing ones in the base application. |------------OSGI-INF //Contains the OSGi files to configure and assemble the core extension as an OSGi bundle |------------------blueprint //contains the bundle's descriptor |--------------------springCtx-import.xml //blueprint descriptor file |----test //Contains your unit test java code. |------java //Contains test classes |--target //Contains the core JAR file with the custom binaries. |--pom.xml //Contains a <dependency> for the core library jar and <build> section identifying the Maven plugins required for builds.
OSGi and the core extension
Cortex runs in an OSGi container. This means any library Cortex uses must be wrapped in an OSGi bundle. Cortex is unable to access any libraries not running alongside it in the OSGi container. Therefore, the core extension contains OSGi configuration files, so the core extension can be deployed as an OSGi bundle. This section describes how some of the core extension project's OSGi files work.
The core extension's pom.xml contains some important OSGi configuration information. The example below outlines the POM's key OSGi configuration details:
<artifactId>ext-core</artifactId> <packaging>bundle</packaging> <name>Extension Core</name> ... <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>
The first OSGi configuration data in the POM is the project's packaging: <packaging>bundle</packaging>. This tells Maven to build 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.
The maven-bundle-plugin configuration turns 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 host bundle's definitions before the host is resolved, as long as the information does not conflict. Fragment dependencies are resolved if possible. If the fragment dependencies cannot be resolved, the fragment does not attach 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 enabling you to customize your bundles.
The <Import-Package> element contributes any additional imports to the core bundle. The core bundle already has everything we need, so we are telling it to not import anything by specifying !* If your core extension relies on additional third party libraries (other than those already used by core), you must list the required packages in the <Import-Package> instruction. If you do this, 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 don't specify the mandatory resolution, OSGI won't find your third party library package at run time and the fragment will fail to attach, but no error message will appear.
The core extension's jpa-persistence.xml file specifies the following:
<persistence-unit name="commerce-persistence-unit"> ... <exclude-unlisted-classes>true</exclude-unlisted-classes> ... </persistence-unit>
This tells OpenJPA to not perform a classpath scan for any classes that need to be enhanced for run time. This scan is not permitted by OSGi and will cause a error if the scan initiates. See the Knowledge Base for more information on this error.
This file tells OSGi where to find the spring configuration for the extension project.
<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>
Technical Notes for the core extension and OSGi
- Core extension classes replacing the out-of-the-box core classes (meaning classes that have the exact same package structure and class name) will not work with this approach.
- If the extension uses third-party libraries, additional configuration is required:
- Add the third-party packages to the <Import-Packages> element (as described above in Extension POM.xml)
- If the third-party libraries are OSGi compliant, add them as a dependency and artifact item in the Cortex Webapp. For information on how to do this, see Referencing custom core services with the Commerce Manager Client.
- If the libraries are not OSGi compliant, they need to be embedded in the fragment.