Versionen im Vergleich

Schlüssel

  • Diese Zeile wurde hinzugefügt.
  • Diese Zeile wurde entfernt.
  • Formatierung wurde geändert.

This section shows how to setup and implement a first UM plugin that provides Goal: Implement a simple REST API.

Create your first plugin

Creating an empty UM plugin is as simple as creating a directory structure following a specific naming rule and putting a plugin.desc.json file in the right place.-Service and expose it via REST Proxy.

Info

You can download the whole Kickstarter-based sample application from our GitLab repository: um-public/tutorial-functional-rest-endpoints

Start a new Kickstarter project

First, choose a Java-style package name for your new plugin – e.g. de.acme.firststepstutorial. (See also ACME Corporation)
Please note that com..., net... and org... denote reserved namespaces and can not be used as top-level package names.

Assuming you already have a running UM (version 7.29.0 or later) installed in ~/UM, create a directory named after your chosen package name under ~/UM/cmsbs-conf/cse/plugins/ with a plugin descriptor file in itSecond, use UM-Kickstarter to begin a new UM project:

Codeblock
languagebash
mkdirumkickstarter ~/UM/cmsbs-conf/cse/plugins/-n de.acme.firststeps
touch ~/UM/tutorial
cd umkickstarter
gradle setup run

Implement REST controller

Create an .es6 or .mjs file in your plugin’s rest/ folder:

cmsbs-conf/cse/plugins/de.acme.

...

tutorial/rest/

...

api.

...

Edit the newly created plugin descriptor file with your favorite text editor to make it look something like this:

mjs

Codeblock
languagejson
{
    "name": "de.acme.firststeps",
    "title": "First steps",
    "description": "Provides a simple REST API for demonstration purposes",
    "version": "0.9.0",
    "um": ">=7.29.0"
}

Restart your UM instance and visit Tools / Apps to find your new plugin listed among a bunch of vendor supplied plugins. Note, however, that the icon displayed in front of your plugin's title looks broken. We'll fix this later on.

Create your first REST controller

Each REST endpoint you want to provide needs its own controller class with a name following a certain convention. Create and edit a new ES6 file with the following name: ~/UM/cmsbs-conf/cse/plugins/de.acme.firststeps/rest/controllers/ListsController.es6.

Codeblock
languagejs
class ListsController {
    constructor() {
    }
}

...

js
/// <reference path="../../../.vscode.js"/>

import { RouterBuilder } from "@de.pinuts.apirouter/shared/routing.es6";

de.acme.tutorialController = new RouterBuilder()
    .get('/hello', (req, res) => {
        res.json({ 
            msg: 'Hello world!',
            params: req.params,
            headers: req.headers,
        });
    })

    .build();

Restart your UM instance:

Codeblock
gradle run

Invoke REST service

Try to invoke the new REST service in your browser:

http://localhost:8080/cmsbs/rest/de.acme.firststeps.Lists/index

This yields a 404 and the logfile ~/UM/cmsbs-work/sys.log says:

Codeblock
Undefined REST controller class: de.acme.firststeps.ListsController

You have created the new controller class but the UM cannot see it because it is not contained in the expected name space object. Add the following line to the end of your ES6 file:

Codeblock
languagejs
de.acme.firststeps.ListsController = ListsController;

This puts the class into the namespace object you chose when writing the plugin descriptor file.

Restart your UM instance and try to run the GET request again.

This still yields a 404 and the logfile says:

Codeblock
Undefined REST action method: de.acme.firststeps.ListsController.prototype.index

So the controller class could be found but it does not define an index action method.

Fix this by allowing the index action with the GET verb and adding an empty method named index_GET to your controller:

...

languagejs

...

tutorial/hello?a=Hello&b=world

URL mapping

Please note, that de.acme.tutorialController corresponds to the name of your plugin as defined in plugin.desc.json plus the special Controller suffix that tells the backend that this should be exposed as a REST controller.

Setup REST Proxy and expose new endpoint

Create a file named rest-proxy/cmsbs-restproxy.properties that configures the REST Proxy:

Codeblock
languagetext
cmsbs.resturl=http://localhost:8080/cmsbs/rest

cmsbs.restproxy.limit.controller.whitelist.tut1 = "de.acme.tutorial"

Insert the following cp lines to your build.gradle file:

Codeblock
languagegroovy
setup.doLast {
    constructor() {...
    
    allowActions(this, 'index_GET');
 // UM REST Proxy
  }      index_GET() {
    }
}

...

Reload and you should get an empty page with a status code of 200.

Enable auto-reloading

If you are tired of restarting your UM instance for each and every little code manipulation to take effect, simply add the following line to your ~/UM/cmsbs-conf/cmsbs.properties file and restart one more time:

Codeblock
cmsbs.cse.autoreload = true

From now on CSE scripts will be reloaded automatically as soon as one of the .js or .es6 files changes.

JSON response

Now, make your index action return a static JSON response:

Codeblock
languagejs
    index_GET() {
        renderJson({
            shoutOut: 'This is a working REST endpoint!'
        }, 200);
    }

You can replace the 200 by whichever status code you want to return.
Include the global params and request variable in your response to make it a little more dynamic:

Codeblock
languagejs
...
    index_GET() {
        renderJson({
            shoutOut: 'This is a working REST endpoint!',
            params,
            request
        }, 200);
    }
...

...

cp('UM/web-integration/cmsbs-restproxy.war', new File(pinuts.um.webappsDir, 'p.war'))
    cp('rest-proxy/cmsbs-restproxy.properties', new File(pinuts.um.serverHome, 'cmsbs-restproxy.properties'))
}

Setup and run your UM instance:

Codeblock
gradle setup run

Your new REST endpoint should now be publicly available via REST proxy:

http://localhost:8080/cmsbs/restp/de.acme.firststeps.Lists/index/aaa/bbb/ccc?a=123&b=456 in your browser and try to identify the additional path components and URL parameters in the request property returned within the response body.tutorial/hello

Next steps

You can now progress to implement more useful endpoints. See also: Functional REST endpoints