This tutorial remains very interesting as it explains many basics of a Nuxeo module and is IDE agnostic. Yet the common way of initializing a plugin project for Nuxeo Platform is now to use Nuxeo CLI which provides many bootstraps.
This recipe describes the steps to create the bare structure of a Nuxeo addon project (aka a bundle).
This is the very first recipe of this cookbook and it will be the basis for the development of new bundles, of new features, even of new UI elements all along this cookbook. All the other recipes will assume that this recipe has been done.
- This recipe is not specific to a system or an IDE. You will have to adapt it to your needs. The sole obligation is to use Maven available in a console and Nuxeo CLI installed. But, even this part, with experience, could be fitted to your IDE habits if you have any.
- For any remark about this recipe or about this cookbook, don't hesitate to leave us a comment on this page.
This recipe is composed of the major steps below:
- Step 1: Create the basic project skeleton
- Step 2: Created Files Description
- Step 3: Install and check the deployment of your Bundle
What You Need
Tool | Version |
---|---|
Java | JDK 17 |
Maven | 3.x |
NodeJS | 6.x |
Nuxeo CLI | latest |
Nuxeo Server distribution | Latest LTS |
Create the Basic Project Skeleton
To create a basic folder structure, we use the Nuxeo CLI. There is no required location to create your project. To create your project structure, follow the steps below.
- In a console, type:
mkdir cookbook && cd $_
- In a console, type:
nuxeo bootstrap single-module
. You are prompted a series of choices to create your project. Accept the default propositions and follow those:
create Generating Single module info Parameters: Parent group, Parent artifact, Parent version, Nuxeo version, Project group, Project artifact, Project version, Project description ? Parent Group id (use white space to cancel default value.): org.nuxeo ? Parent Artifact id: nuxeo-addons-parent ? Parent Version: 9.10 ? Project Group id: org.nuxeo.cookbook ? Project Artifact id: cookbook-core ? Project version: 1.0-SNAPSHOT ? Project description: Cookbook bare project create pom.xml create src/main/resources/META-INF/MANIFEST.MF create src/main/java/org/nuxeo/cookbook/package-info.java create src/test/resources/jndi.properties create src/test/resources/log4j2.xml info You can start editing code or you can continue with calling another generator (nuxeo bootstrap <generator>..)
Complete the Folder Structure
After you completed the project creation, you get this folder structure:
cookbook └── src ├── main │ ├── java │ │ └── org │ │ └── nuxeo │ │ └── cookbook │ └── resources │ ├── META-INF │ └── OSGI-INF └── test ├── java │ └── org │ └── nuxeo │ └── cookbook └── resources
Created Files Description
The pom.xml
File Explained
Nuxeo Addon set as parent to pull all Nuxeo dependencies:
<parent> <groupId>org.nuxeo</groupId> <artifactId>nuxeo-addons-parent</artifactId> <version>9.10</version> </parent>
Repositories:
Repository
public
contains all Nuxeo's bundle releases.<repository> <id>public</id> <url>http://maven.nuxeo.org/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository>
Repository
public-snapshot
contains all Nuxeo's bundle snapshots.<repository> <id>public-snapshot</id> <url>http://maven.nuxeo.org/nexus/content/groups/public-snapshot</url> <releases> <enabled>false</enabled> </releases> <snapshots> <updatePolicy>always</updatePolicy> <enabled>true</enabled> </snapshots> </repository>
Repository
nuxeo-studio
contains Studio projects.<repository> <id>nuxeo-studio</id> <url>https://connect.nuxeo.com/nuxeo/site/studio/maven</url> <releases> <enabled>true</enabled> </releases> <snapshots> <updatePolicy>always</updatePolicy> <enabled>true</enabled> </snapshots> </repository>
The deployment-fragment.xml
File
For this exercise, in order to deploy your Nuxeo addon project in the Nuxeo server, you need a new file called deployment-fragment.xml
in the cookbook/src/main/resources/OSGI-INF
folder. This file tells the deployment mechanism which files must be copied and where. This file is not mandatory, but it is needed to have your bundle displayed in the log at start up.
For now, the content of the file deployment-fragment.xml
should be:
<?xml version="1.0"?>
<fragment version="1">
<install>
<!-- to be completed later -->
</install>
</fragment>
The content of this file will be completed in a coming recipe.
Remark:
- If you want your bundle deployed after all other bundles, you can add an element
<require>
inside the<fragment>
element, and fill it with the required bundle name. Theall
pseudo-bundle can also be referenced, so that this bundle is deployed after all others:<require>all</require>
. - The
deployment-fragment.xml
file is not required if you have no dependency information to transmit to the runtime or pre-deployment actions to execute.
The MANIFEST.MF
File
As Nuxeo addons are OSGi modules, you have a MANIFEST.MF
file in the /src/main/resources/META-INF
folder.
Here is a sample that a MANIFEST.MF
file must hold:
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
Manifest-Version: 1.0
Bundle-Vendor: org.nuxeo.cookbook
Bundle-Version: 1.0.0
Bundle-Name: cookbook-core
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.nuxeo.cookbook.cookbook-core;singleton=true
Some of the values above are mandatory, some should be changed to be adapted to your needs. The following properties are more the less "constants" and their values must always be the same:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
The other properties should be customized to your needs. The two principals are:
Bundle-Name: cookbook-core
Bundle-SymbolicName: org.nuxeo.cookbook.cookbook-core;singleton=true
Bundle-Name
corresponds to the human-readable name of the bundle;Bundle-SymbolicName
is the reference computed by the OSGi container and looked-up by the other bundles. This declaration is immediately followed, on the same line, by;singleton:=true
which declares to the OSGi container that the bundle can't cohabit with an other version of the bundle at runtime. The semi-colon is of course mandatory.
The other properties are:
Bundle-Version
: This property is all on your responsibility. The Nuxeo convention is three digits separated by a dot such as "x.y.z";Bundle-Vendor
: This is the name of the addon owner.
Although not used in this recipe, there is one more property you should know of: Nuxeo-Component:
.
It contains a list of files used to define various elements of your component. Its use is detailed in Writing a Bundle Manifest.
The trickiest and most important part of a MANIFEST.MF
file is its formatting. One mistake and the OSGi context can't be correctly started, leading to unexpected issues and an unreachable bundle. Here are the three formatting rules to respect:
- Each property name:
- begins at the first character of the line;
- ends with a colon without space between the name of the property and the colon itself.
- Each value:
- must be preceded by a space;
- ends with a "end of line" with eventually a comma before it.
- There MUST be an EMPTY LINE at the END OF THE FILE.
Files for the Tests
The log4j2.xml
File
As the tests will run in a sandbox, it could be useful to define a file named log4j2.xml
file. It must be placed in the /src/test/resources
folder.
Here is a sample of such a file:
<root>
<priority value="INFO" />
<appender-ref ref="CONSOLE" />
</root>
To make the log more or less verbose, just change the first value of the priority value. In this example, the level is "INFO". If you want more details, downgrade it to "DEBUG". You will have more entries displayed in the console about Nuxeo classes involved in the running tests.
Install and Check the Deployment of Your Bundle
Build your bundle, in a console, using the following Command Line Interface (CLI):
$ mvn install
In the
/target
folder of your project, you get a JAR file whose name is formed like that:cookbook-core-1.0-SNAPSHOT.jar
.Copy your brand new jar into the sub-folder "nxserver/bundles/" of your Nuxeo Server's root folder:
- under Windows, assuming that the Nuxeo Server Distribution is installed at the location "C:\Nuxeo\", copy the jar in
C:\Nuxeo\nxserver\bundles\
; - under Linux, assuming that the Nuxeo Server Distribution is installed at the location "/opt/nuxeo", copy the jar in
/opt/nuxeo/nxserver/bundles
.
- under Windows, assuming that the Nuxeo Server Distribution is installed at the location "C:\Nuxeo\", copy the jar in
Start your server using the
./bin/nuxeoctl start
commandYou can check the dedicated Start and stop page of the technical documentation for more information about the different ways to start your server).
- Check that your bundle is correctly deployed: check if its SymbolicName (as configured in the
/src/main/resources/META-INF
) appears in the logs. The logs are displayed:- in the console if you started your server using the
./bin/nuxeoctl start
- in the file
server.log
located in thelog
folder of your Nuxeo Server root folder. This name is found in the list of the bundles deployed by Nuxeo in the very first lines of the logs, just after the line ended byPreprocessing order:
.
- in the console if you started your server using the
Now you've got a bundle ready for customization. You can start generating more stuff with the Nuxeo CLI and use it to improve your Nuxeo Server instance.
As said in the beginning of this recipe, if you have unexpected errors or Nuxeo Application behavior don't forget to check Nuxeo Answers and don't forget to leave us a comment about this recipe or about the cookbook!