The New Way to Bootstrap Your Application with Nuxeo Generator


Thu 02 June 2016 By Arnaud Kervern

generator-nuxeo


Do you remember those days when you'd create a new Java Nuxeo Operation in your bundle and the whole process of creating it seemed a little too much? Indeed, there was a lot going on: checking if you had the right Maven dependencies, and trying to find another Operation somewhere to get the right Java Annotations for parameters and run method before you finally did a "nice" copy paste!

You must have also put in effort in creating a Nuxeo Package to simplify your application deployment inside your Nuxeo Platform, creating a Java Listener or a Nuxeo Service, trying to figure out what event name exists, how to define your Service (which class? which XML?), or making sure you added your component to the MANIFEST.MF file!

Well, that time is now over! (You didn't see that coming, eh!)

Now you'll even be able to use your beloved IDE (as it's a headless tool.). Let’s take a look at this new easier process!

Setting up Your Environment

It's based on a great tool, Yeoman. Yeoman helps you kickstart new projects, prescribing best practices and tools to help you stay productive.

With a correct Node installation, the simplest way is to install the module in your global registry:

npm install -g yo generator-nuxeo

And ensure yo is working well:

yo --generators

You must find the nuxeo generator in the output list.

Available Generators:

  nuxeo

That’s it! We are all set to save a lot of time now.

Let's Generate!

We will take the most common use case: Creating a new Operation and bundle it in a Nuxeo Package.

mkdir sample-project && cd sample-project
yo nuxeo operation package

Let's talk a little bit about what is requested while generating:

invoke Requirements: multi-module, single-module, operation, package
  info You'll be prompted for generation of: multi-module, single-module, operation, package

Other modules may be needed. In our example, we are starting from an empty project and we need to bootstrap a Maven multi-module, then create a -core module where we'll have the sources of our Operation. Finally, we need a -package module for our Nuxeo Package.

create Generating Multi module (Your project parent POM)
  info   Parameters: Use a parent artifact, Parent group, Parent artifact, Parent version, Import nuxeo in the `dependency management`, Nuxeo version, Project group, Project artifact, Project version, Project description
? Use a parent artifact (for instance your company's BOM or the org.nuxeo.ecm.distribution:nuxeo-distribution POM)? Yes
? Parent Group id: org.nuxeo.ecm.distribution
? Parent Artifact id: nuxeo-distribution
? Parent Version: 7.10
? Project group id: com.bigcorp.sample
? Project Artifact id: sample-project-parent
? Project version: 1.0-SNAPSHOT
? Project description: my sample

Sometimes you'll need to use a BOM; aka your enterprise pom with your dependency management. The other option is to use the nuxeo-distribution artifact as module parent, but in case you don't want to do that, you can import your dependency management in the pom.

create Generating Single module
  info   Parameters: Nuxeo version, Project group, Project artifact, Project version, Project description
? Nuxeo Version: 7.10 (LTS 2015)
? Project Group id: com.bigcorp.sample
? Project Artifact id: sample-project-core
? Project version: 1.0-SNAPSHOT
? Project description:

create Generating Operation
  info   Parameters: Operation class name, Operation label
? Operation class name: MyOperation
? Operation label: My Cool Operation

create Generating Package
  info   Parameters: Package artifact, Package name, Company name
? Package Artifact id: sample-project-package
? Package name: sample app
? Company name: bigcorp

You can do the same for the others generators.

create Configuration: multi
  info Maven dependency: org.nuxeo.ecm.automation:nuxeo-automation-core
  info Maven dependency: org.nuxeo.ecm.automation:nuxeo-automation-test:::test
create pom.xml
create sample-project-core/src/main/resources/META-INF/MANIFEST.MF
create sample-project-core/pom.xml
create sample-project-core/src/main/java/com/bigcorp/sample/package-info.java
create sample-project-core/src/test/resources/log4j.xml
create sample-project-core/src/main/java/com/bigcorp/sample/MyOperation.java
create sample-project-core/src/test/java/com/bigcorp/sample/TestMyOperation.java
create sample-project-core/src/main/resources/OSGI-INF/my-operation-operation-contrib.xml
create sample-project-marketplace/pom.xml
create sample-project-marketplace/src/main/assemble/assembly.xml
create sample-project-marketplace/src/main/resources/install/templates/sample-project/nuxeo.defaults
create sample-project-marketplace/src/main/resources/install.xml
create sample-project-marketplace/src/main/resources/package.xml
  info You can start editing code or you can continue with calling another generator (yo nuxeo <generator>..)

Voilà! All the files are created. You can ask Maven to package everything, or you can open the project and start coding! Note that we added a unit test for Operation, Service, and Event Listener (you're welcome!). And please, instead of removing the test files, make them work! ;)

Under the Hood

Under the hood

You already know that our generator is built on top of Yeoman but we tweaked it a little bit because all our generators are pulled from another repository generator-nuxeo-meta to give us a meta-model that represents what is created and move all the generation logic to the engine. The goal of this repository is to handle all generated templates; like the pom.xml of your modules, Java classes, Package assembly file, and so on.

If we look closer at how it works, each generator has a descriptor.js file. This file describes what must be requested of the user and what must be created, using a clear and simple JSON format.

The descriptor file is composed of different definitions. You can check out the README for the description.

  • params: It defines which parameters will be prompted to the user. It is handled with Inquirer.js; and we added some sugar coating! For instance, a store parameter will not be asked twice during a generation process even if it is required by several generators.
  • templates folder: After having the user's inputs, the content of the templates folder is rendered. We decided to use the more natural way to template a file to a specific path: by using just the path.
  • contributions: It’s a templating system for contributions but with a src and dest entry for the filenames. It renders the file in the OSGI-INF folder, which is then added to the MANIFEST.MF.
  • main-java/test-java: It’s a templating system for Java classes, which also uses a src and dest entry, and expects to have a user's input package. It renders the file in the corresponding package.
  • dependencies: List of Maven GAV (group, artifact, version) of the dependencies. The format is: <groupId>:<artifactId>[:<version>[:<extension>[:<classifier>]]].

With those entries, you should be able to understand and create your own generator, and/or contribute with an awesome Pull Request!

Upcoming Features

The next steps are:

  • Bringing Nuxeo Studio and the Generator to work together allowing you to create constant class, based on what is defined on Studio side
  • New generators to bootstrap Polymer / Angular app to be deployed in your Nuxeo Platform
  • Bug fixing

References


Tagged: Nuxeo Generator, Nuxeo Platform