Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
861 lines (738 sloc) 27.4 KB
title description review details labels toc version_override tree_item_index history
Develop with Nuxeo Platform
Learn how to start working and developing with Nuxeo CLI.
comment date status
2017-12-15
ok
howto
excerpt level tool topics
Learn how to start working with Nuxeo CLI.
Intermediate
Nuxeo CLI, Nuxeo Studio
Automation, Layout
howto
nuxeo-cli
bchauvin
university
lts2016-ok
lts2017-ok
true
LTS 2016 LTS 2015 6.0
810/nxdoc/getting-started-with-nuxeo-ide
710/nxdoc/getting-started-with-nuxeo-ide
60/nxdoc/getting-started-with-nuxeo-ide
300
author date message version
Thibaud Arguillere
2016-08-26 17:56
77
author date message version
Solen Guitter
2016-07-21 08:52
Update link to SDK to use 8.3
76
author date message version
Manon Lumeau
2016-04-25 14:04
75
author date message version
Solen Guitter
2016-04-18 17:41
Update FT SDK link to 8.2
74
author date message version
Bertrand Chauvin
2016-04-14 14:01
fix missing comment
73
author date message version
Bertrand Chauvin
2016-04-13 15:31
Added Studio project binding
72
author date message version
Bertrand Chauvin
2016-03-21 15:55
71
author date message version
Bertrand Chauvin
2016-03-21 15:55
70
author date message version
Bertrand Chauvin
2016-03-21 15:55
69
author date message version
Solen Guitter
2016-03-21 15:34
Fix page layout
68
author date message version
Solen Guitter
2016-03-21 15:28
Fix screenshot max size and remove empty code block
67
author date message version
Bertrand Chauvin
2016-03-21 15:26
66
author date message version
Bertrand Chauvin
2016-03-21 15:26
65
author date message version
Bertrand Chauvin
2016-03-21 15:25
fix image size
64
author date message version
Bertrand Chauvin
2016-03-21 15:23
63
author date message version
Bertrand Chauvin
2016-03-21 15:18
fix link
62
author date message version
Bertrand Chauvin
2016-03-21 15:16
fix anchor
61
author date message version
Bertrand Chauvin
2016-03-21 15:14
Replace with generator version
60
author date message version
Solen Guitter
2016-02-01 15:38
Update SDK download link to point to 8.1 SDK
59
author date message version
Bertrand Chauvin
2016-01-07 11:26
Add imports and package declaration in final result
58
author date message version
Bertrand Chauvin
2016-01-07 11:14
Fix parent version for parent POM
57
author date message version
Bertrand Chauvin
2016-01-05 15:08
Fix SDK link
56
author date message version
Bertrand Chauvin
2015-12-30 14:45
55
author date message version
Bertrand Chauvin
2015-12-30 14:43
Update to LTS 2015 SDK
54
author date message version
Manon Lumeau
2015-11-30 17:11
53
author date message version
Bertrand Chauvin
2015-11-04 13:42
Fixed typos
52
author date message version
Bertrand Chauvin
2015-11-04 13:28
typo
51
author date message version
Bertrand Chauvin
2015-11-04 13:26
typo
50
author date message version
Bertrand Chauvin
2015-11-04 13:25
49
author date message version
Bertrand Chauvin
2015-11-04 13:23
Updated intro
48
author date message version
Bertrand Chauvin
2015-11-04 11:21
Complete / Fix / Refactor doc
47
author date message version
Bertrand Chauvin
2015-11-04 10:44
Complete doc until step 3
46
author date message version
Bertrand Chauvin
2015-11-04 10:24
Rename step
45
author date message version
Bertrand Chauvin
2015-11-04 10:23
Update SDK link
44
author date message version
Bertrand Chauvin
2015-11-04 10:22
Update prerequisites
43
author date message version
Julien Carsique
2015-10-29 13:56
update site URLs
42
author date message version
Solen Guitter
2015-10-14 09:00
Fix anchors and page layout
41
author date message version
Manon Lumeau
2015-09-25 13:32
40
author date message version
Manon Lumeau
2015-09-25 13:30
39
author date message version
Solen Guitter
2015-08-03 07:37
38
author date message version
Manon Lumeau
2015-07-31 13:59
37
author date message version
Solen Guitter
2015-07-21 09:19
36
author date message version
Bertrand Chauvin
2015-05-25 08:07
Updated Nuxeo SDK version to HF12
35
author date message version
Manon Lumeau
2014-12-29 14:29
34
author date message version
Manon Lumeau
2014-12-29 14:27
33
author date message version
Manon Lumeau
2014-12-29 14:24
32
author date message version
Solen Guitter
2014-12-26 14:05
31
author date message version
Solen Guitter
2014-12-26 13:42
Add link to previous step, typos
30
author date message version
Manon Lumeau
2014-12-24 14:50
29
author date message version
Manon Lumeau
2014-12-24 14:47
28
author date message version
Manon Lumeau
2014-12-24 14:46
27
author date message version
Manon Lumeau
2014-12-24 14:45
26
author date message version
Manon Lumeau
2014-12-24 14:42
25
author date message version
Manon Lumeau
2014-12-24 14:34
24
author date message version
Manon Lumeau
2014-12-24 14:32
23
author date message version
Manon Lumeau
2014-12-24 14:13
22
author date message version
Manon Lumeau
2014-12-24 13:56
21
author date message version
Manon Lumeau
2014-12-24 13:44
20
author date message version
Manon Lumeau
2014-12-24 13:27
19
author date message version
Manon Lumeau
2014-12-24 13:17
18
author date message version
Manon Lumeau
2014-12-24 11:12
17
author date message version
Manon Lumeau
2014-12-24 11:07
16
author date message version
Manon Lumeau
2014-12-24 10:56
15
author date message version
Manon Lumeau
2014-12-22 16:59
14
author date message version
Vladimir Pasquier
2014-12-20 17:38
13
author date message version
Anne Jubert
2014-11-25 15:29
12
author date message version
Manon Lumeau
2014-11-25 14:53
11
author date message version
Manon Lumeau
2014-11-17 14:33
10
author date message version
Manon Lumeau
2014-11-17 14:32
9
author date message version
Manon Lumeau
2014-11-17 14:31
8
author date message version
Manon Lumeau
2014-11-17 14:27
7
author date message version
Manon Lumeau
2014-11-07 10:59
6
author date message version
Manon Lumeau
2014-11-07 10:59
5
author date message version
Manon Lumeau
2014-11-06 12:29
4
author date message version
Manon Lumeau
2014-11-06 12:28
3
author date message version
Manon Lumeau
2014-11-06 12:26
2
author date message version
Manon Lumeau
2014-11-06 12:25
1

Here we want to add some server side Java logic that will update the contract's renegotiation date. In our example it will simply take the contract's start date and add three months to it, but you can think of integrating any custom logic in your Java class, including a connection to an external webservice or an ERP.

{{#> callout type='info'}} Watch the related courses on Nuxeo University

Prerequisites

  • A Contract document type created on this [page]({{page version='' space='nxdoc' page='web-ui-document-layouts'}})
  • An IDE that integrates with Maven. We provide instructions for Eclipse IDE for Java EE Developers 4.5 (Mars) or IntelliJ IDEA
  • Java 8 with JDK
  • Maven 3.3+ (see the Installing Maven section of page [Maven Usage]({{page version='' space='corg' page='maven-usage'}}))
  • The latest stable NodeJS version should be installed on your machine
  • npm 2.12.0+

Step 1 - Install Nuxeo CLI

From a command line prompt, type:

$ npm install -g nuxeo-cli

[Nuxeo CLI]({{page page='nuxeo-cli'}}) lets you easily scaffold common Nuxeo components like empty projects, Packages, Automation Operations, Services, etc. This saves you time writing boilerplate code to focus on your code instead of the structure.

We'll use it to generate a new Nuxeo project and a custom operation.

Step 2 - Implement a Custom Operation

We want to create an operation that indicates the date of renegotiation of a contract. This will be done by fetching the document's start date and adding three months to it.

A custom operation is a Java class in which you can put custom business logic. Custom operations usually serve one of two purposes: to support business logic that is too complex to express via an Automation Chain; or to provide functionality that does not exist within existing operations.

Once created, the operation can be exposed in Nuxeo Studio and used just like any other operation via automation chains and automation scripts. See the [Automation]({{page page='automation'}}) section for more information about operations.

Create Your Project

From a command line:

  1. Create an empty folder in which to store the project:

    $ mkdir contract-mgt-project
    $ cd contract-mgt-project
  2. Generate a "Multi module" project structure:

    $ nuxeo bootstrap
  3. Fill in the following values, via the prompts provided by Nuxeo CLI:

    ? Use a parent artifact (for instance your company's BOM or the org.nuxeo.ecm.distribution:nuxeo-distribution POM)? y
    ? Parent Group id: org.nuxeo.ecm.distribution
    ? Parent Artifact id: nuxeo-distribution
    ? Parent Version: (leave the default option here)
    ? Project group id: com.bigcorp.contractmgt
    ? Project Artifact id: contract-mgt-project-parent
    ? Project version: 1.0-SNAPSHOT
    ? Project description: Contract management parent.
    

    Once complete, Nuxeo CLI will automatically start the process to create a "Single Module" project (the operation will be implemented here).

  4. Fill in the following values to generate the "Single Module" project:

    ? Project Group id: com.bigcorp.contractmgt
    ? Project Artifact id: contract-mgt-project-core
    ? Project version: 1.0-SNAPSHOT
    ? Project description: Contract management project.
    

    Now that the project is generated, it can be used in any IDE.

Import the Project Into an IDE

  • Using IntelliJ IDEA

    1. Select File / Open....

    2. Browse to your project root folder (contract-mgt-project), then the pom.xml file and click Open.

    3. Choose Open as Project.

  • Using Eclipse

    1. Generate Eclipse configuration files.

      $ mvn install
      
      # The following parameters (downloadSources, downloadJavadocs and useProjectReferences) are optional
      # For details, see Maven Eclipse Plugin documentation: https://maven.apache.org/plugins/maven-eclipse-plugin/eclipse-mojo.html
      $ mvn eclipse:clean eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true -Declipse.useProjectReferences=true
      
      # Linux and OS X users should run the following script to make Eclipse use different build directories than Maven:
      $ curl -o- https://raw.githubusercontent.com/nuxeo/nuxeo/master/fixeclipse|bash
      # A cross-platform script is also available for Windows users:
      # curl -o- https://raw.githubusercontent.com/nuxeo/nuxeo/master/scripts/fixeclipse.py|python
    2. In Eclipses select File / Import / General / Existing Projects into Workspace.

    3. Browse to your project root folder (contract-mgt-project), then click Finish. ![]({{file name='eclipse_import_project.png'}} ?w=400)

Implement Your Operation

  1. In a terminal, generate an operation code template:

    $ nuxeo bootstrap operation
  2. You are prompted for a few details:

    ? Operation package: com.bigcorp.contractmgt
    ? Operation class name: ContractUpdater
    ? Operation label: Contract Updater
    
  3. Update the dependencies:

    • IntelliJ IDEA
      In IntelliJ IDEA, click on Import Changes in the Maven's popup.

    • Eclipse

      1. In a terminal:
      $ mvn eclipse:eclipse
      1. In Eclipse, then right-click on the project and click Refresh (F5).
  4. Nuxeo CLI will generate a new Java class for the operation at contract-mgt-project/contract-mgt-project-core/src/main/java/com/bigcorp/contractmgt/ContractUpdater.java like so:

    package com.bigcorp.contractmgt;
    
    import org.apache.commons.lang3.StringUtils;
    import org.nuxeo.ecm.automation.core.Constants;
    import org.nuxeo.ecm.automation.core.annotations.Context;
    import org.nuxeo.ecm.automation.core.annotations.Operation;
    import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
    import org.nuxeo.ecm.automation.core.annotations.Param;
    import org.nuxeo.ecm.core.api.CoreSession;
    import org.nuxeo.ecm.core.api.DocumentModel;
    import org.nuxeo.ecm.core.api.PathRef;
    
    /**
     *
     */
    @Operation(id=ContractUpdater.ID, category=Constants.CAT_DOCUMENT, label="Contract Updater", description="Describe here what your operation does.")
    public class ContractUpdater {
        public static final String ID = "Document.ContractUpdater";
        @Context
        protected CoreSession session;
        @Param(name = "path", required = false)
        protected String path;
        @OperationMethod
        public DocumentModel run() {
            if (StringUtils.isBlank(path)) {
                return session.getRootDocument();
            } else {
                return session.getDocument(new PathRef(path));
            }
        }
    }
  5. Time to fill in the skeleton and start coding! Here is the final result of ContractUpdater.java:

    package com.bigcorp.contractmgt;
    
    import java.util.Calendar;
    import org.nuxeo.ecm.automation.core.Constants;
    import org.nuxeo.ecm.automation.core.annotations.Operation;
    import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
    import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector;
    import org.nuxeo.ecm.core.api.DocumentModel;
    import org.nuxeo.ecm.core.api.NuxeoException;
    
    /**
     *
     */
    @Operation(id = ContractUpdater.ID, category = Constants.CAT_DOCUMENT, label = "Contract Updater", description = "On a contract, sets the reminder date to three months after its start date.")
    public class ContractUpdater {
    
        public static final String ID = "Document.ContractUpdater";
        static final String CONTRACT_TYPE = "Contract";
        static final String CONTRACT_SCHEMA = "contract";
        static final String CONTRACT_START = CONTRACT_SCHEMA + ":start";
        static final String CONTRACT_REMINDER = CONTRACT_SCHEMA
                + ":reminder";
    
        @OperationMethod(collector = DocumentModelCollector.class)
        public DocumentModel run(DocumentModel input) throws NuxeoException {
            if (!(CONTRACT_TYPE.equals(input.getType()))) {
                throw new NuxeoException("Operation works only with "
                        + CONTRACT_TYPE + " document type.");
            }
    
            Calendar start = (Calendar) input.getPropertyValue(CONTRACT_START);
            Calendar reminder = (Calendar) start.clone();
            reminder.add(Calendar.MONTH, 3);
            input.setPropertyValue(CONTRACT_REMINDER, reminder.getTime());
            return input;
        }
    }

Send the Operation to Nuxeo Studio

  1. Build a JAR file (without running the tests); from the contract-mgt-project folder run:
$ mvn -DskipTests package
  1. Link your local project to your Studio Project
$ nuxeo studio link
  info You are going to link a Studio project to this project.
? NOS Username: my-user
? NOS Password: [hidden]
? Studio Project: my-project
? Do you want to update your Maven settings.xml file accordingly? Yes

{{#> callout type='warning' }} At this point, you just added your Nuxeo Connect password in ~/.m2/settings.xml in clear text. This is not recommended, please read the following Security Best Practices section. {{/callout}}

  1. Export your contributions to Nuxeo Studio
$ nuxeo studio export
  info Building and exporting your contributions to 'my-project' Studio project.
  info Contributions successfully exported to 'my-project' Studio project.
  1. In Nuxeo Studio go to Settings > Automatic Registries > Automation Operations, and you should see the JSON definition of your operation.

The operation is available in the Automation Chain editor, under the Document category.

Security Best Practices

It is strongly recommended that you encrypt the secrets stored in ~/.m2/settings.xml. Read the official Maven Password Encryption documentation page, for more information.

  1. Create a master password:
$ mvn --encrypt-master-password

The command will prompt you for your master password and produce an encrypted version, something like this:

{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}
  1. Store this password in ~/.m2/settings-security.xml:
<settingsSecurity>
  <master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>
</settingsSecurity>
  1. Encrypt your Nuxeo Studio password:
$ mvn --encrypt-password
  1. Find and update your credentials in your ~/.m2/settings.xml file as below:
<servers>
  ....
  <server>
    <id>nuxeo-studio</id>
    <username>your_studio_username</username>
    <password>your_new_encrypted_studio_password</password>
  </server>
  ...
</servers>

This configures your Maven client to use authentication when accessing the Studio Maven repository.

Step 3 - Create Your Chain in Nuxeo Studio

Create an Automation Chain

  1. In the Studio menu Automation > Automation Chains, click on New.

  2. Call your chain ContractUpdater.

  3. Leave the Fetch > Context Document(s) operation and add the custom operation, available in Document > ContractUpdater.

    ![]({{file name='contractUpdater_chain.png'}} ?w=600,border=true)

  4. Click on Save.

Create an Event Handler

Now create an Event Handler in order to call your operation when a contract is created.

  1. In the Studio menu Automation > Event Handlers, click on New.

  2. Call the event handler SetReminderDate.

  3. Fill in the creation wizard:

    • Events: Select About to create.
    • Current document has one of the types: Select your document type Contract.
    • Event Handler Execution: Choose your automation chain ContractUpdater.
  4. Click on Save. Now you can try it on your server either by running the unit tests or by testing manually.

  5. Import your automation chain in your Java project

We assume you already called nuxeo studio link from the previous chapter.

$ nuxeo studio import
  info You are going to create a new Constant Class with Studio\'s related models.
? Constant package: nuxeo.studio.test
? Constant class name: StudioConstant
  create contract-mgt-project-core/src/main/java/nuxeo/studio/test/StudioConstant.java

Step 4 - Test the Code

The code can either be tested through unit tests or manually. You need to bind the Studio project first (using nuxeo studio link and imported Studio constants nuxeo studio import seen previously) to have it deployed during the unit tests or on the server when testing manually.

Update the Unit Test

Nuxeo CLI automatically created a unit test class for the Operation at contract-mgt-project/contract-mgt-project-core/src/test/java/com/bigcorp/contractmgt/TestContractUpdater.java. This test must be made to pass in order to compile and deploy your project.

  1. Replace TestContractUpdater.java with the following code:

    package com.bigcorp.contractmgt;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    import static org.junit.Assert.assertNull;
    
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import javax.inject.Inject;
    import nuxeo.studio.test.StudioConstant;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.nuxeo.ecm.automation.test.AutomationFeature;
    import org.nuxeo.ecm.core.api.CoreSession;
    import org.nuxeo.ecm.core.api.DocumentModel;
    import org.nuxeo.ecm.core.test.DefaultRepositoryInit;
    import org.nuxeo.ecm.core.test.annotations.Granularity;
    import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
    import org.nuxeo.runtime.test.runner.Deploy;
    import org.nuxeo.runtime.test.runner.Features;
    import org.nuxeo.runtime.test.runner.FeaturesRunner;
    import org.nuxeo.runtime.test.runner.PartialDeploy;
    import org.nuxeo.runtime.test.runner.TargetExtensions;
    
    @RunWith(FeaturesRunner.class)
    @Features(AutomationFeature.class)
    @RepositoryConfig(init = DefaultRepositoryInit.class, cleanup = Granularity.METHOD)
    
    // Be sure to replace studio.extensions.MAVEN-ARTIFACT-ID
    // with your Studio project's symbolic name.
    // You can find it in Studio:
    // Settings > Application Information > Maven Artifact id field
    @Deploy({"com.bigcorp.contractmgt.contract-mgt-project-core"})
    @PartialDeploy(bundle = StudioConstant.BUNDLE_NAME, extensions = { TargetExtensions.Automation.class })
    public class TestContractUpdater {
          @Inject
          protected CoreSession session;
          @Test
          public void shouldCallTheAutomationChain() {
              // Create a contract, currently stored in memory
              DocumentModel doc = session.createDocumentModel("/default-domain", "my-test-doc", ContractUpdater.CONTRACT_TYPE);
              GregorianCalendar now = new GregorianCalendar();
              doc.setPropertyValue(ContractUpdater.CONTRACT_START, now);
    
              // At this stage, the reminder date should be empty
              assertNull(doc.getPropertyValue(ContractUpdater.CONTRACT_REMINDER));
    
              // We'll save the document in the database which will
              // trigger an event handler that sets the reminder date
              doc = session.createDocument(doc);
              session.save();
    
              // Now we'll check that the reminder date is set as expected
              int currentMonth = now.get(Calendar.MONTH);
              GregorianCalendar reminder = (GregorianCalendar) doc.getPropertyValue(ContractUpdater.CONTRACT_REMINDER);
              assertNotNull("Reminder date is not set, check your automation chain.", reminder);
              assertEquals("Reminder date is not set in three months from now", (((currentMonth + 3) > 12) ? (currentMonth - 9):(currentMonth + 3)), reminder.get(Calendar.MONTH));
          }
    }

If you try running the test (in Eclipse, right-click on your project and choose Run As, JUnit Test, or Run TestContractUpdater in IntelliJ IDEA), you will notice that the test fails because our Studio project is missing a few things. We need to add them to make the test pass.

Using Unit Tests

  1. Right-click on your unit test class and choose Run As, JUnit Test in Eclipse, or Run TestContractUpdater in IntelliJ IDEA. The tests should now pass.

Using unit tests is the recommended way to ensure a feature is working as expected. Unit tests are triggered automatically whenever you build your project using Maven, and as such they help you in maintaining a high quality level.

Testing Manually

  1. Start your Nuxeo server. Update your Studio package from the Update Center.

  2. Create a new Contract with the following information:

    • Title: Maintenance Contract
    • Contract Owner: Nuxeo
    • Starting Date: Choose today's date. You should end up with something like this: ![]({{file name='result.png'}} ?w=600,border=true)

{{#> callout type='info' }} That's it! You are ready to develop on the Nuxeo Platform. {{/callout}}

What to do Next

You should learn to package and deploy your application in a Nuxeo Platform instance.

You can’t perform that action at this time.