Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

This documentation is written for developers and administrators and describes how to implement auto-complete logic which is used by the client.

Introduction

Beginning with yuuvis® RAD 10.6, the client-service can be extended by auto-complete plug-ins. This feature will be used by the client in one of the next minor releases. A new string field property URL for auto-complete service was introduced in the schema in version 10.4 and can be maintained with the help of the designer.

image-20240613-113235.png

This URL will be resolved and used by the client if it is found in a form and offers the user a behavior similar to a dynamic list field.

Including a Plug-in in the Client-Service

The jar file of the plug-in must be stored in the directory <yuuvis-rad-data-dir>/autocomplete-plugins:

The client-service must be restarted to enable the plug-in.
The plug-ins will automatically be registered and be listed via this endpoint: <host>/app/api/autocomplete/info

Result of info endpoint

Any number of plug-in files can be stored in this directory.

Checking the Logging of the Plug-in

As soon as the client-service has been restarted, available plug-ins are detected. Information on these plug-ins can be found in the log.

In this example the “dummy” plug-in is resolved and started:

... org.pf4j.DefaultPluginStatusProvider     : Enabled plugins: []
... org.pf4j.DefaultPluginStatusProvider     : Disabled plugins: []
... org.pf4j.DefaultPluginManager            : PF4J version 3.11.0 in 'deployment' mode
... org.pf4j.AbstractPluginManager           : Plugin 'AutocompleteCatalog-Dummy-Plugin@10.0.0' resolved
... org.pf4j.AbstractPluginManager           : Start plugin 'AutocompleteCatalog-Dummy-Plugin@10.0.0'
... c.o.s.a.p.t.DummyPlugin$DummyProducer    : Start

Result of the Request

The result of all plug-ins will look like this:

 {
  "entries": [
    {
      "value": "alpha",
      "description": "first letter",
      "selectable": true
    },
    {
      "value": "beta",
      "description": "second letter",
      "selectable": true
    },
    ....
  ]
}

Creating a Plug-in

This section describes how to set up and configure a new plug-in including its deployment and check.

The plug-in capability of the client-service is based on the PF4J framework.

The plug-in must comply with the interface defined by PF4J-Spring. In particular, this is a constructor with a PluginWrapper as a parameter:

	public DummyPlugin(PluginWrapper wrapper) {
        super(wrapper);
    }

Including the Library for the Definition of the Plug-in Interface

OPTIMAL SYSTEMS provides a library for the definition of the plug-in interface. The autocomplete-plugin-interface.jar file is available for download below and must be added to the project. It defines the interface for the client-service and also brings the plug-in capability of PF4J.

It is important that the dependency of the plug-in to the interface library is defined as provided (in gradle compileOnly):

<dependency>
			<groupId>com.os.enaio.services.extraction</groupId>
			<artifactId>autocomplete-plugin-interface</artifactId>
			<version>10.0.4</version>
			<scope>provided</scope>
		</dependency>

Implementing the Plug-in

The following example operates with JSON files as source.

Plug-in example code:

package com.os.services.autocomplete.plugin.test;

import com.os.services.autocomplete.plugin.ListEntry;
import com.os.services.autocomplete.plugin.ListProducer;
import com.os.services.autocomplete.plugin.AutocompleteInfo;
import com.os.services.autocomplete.plugin.PluginContext;
import org.apache.commons.lang.StringUtils;
import org.pf4j.Extension;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class DummyPlugin extends Plugin {

    /**
     * Constructor to be used by plugin manager for plugin instantiation.
     * Your plugins have to provide constructor with this exact signature to
     * be successfully loaded by manager.
     *
     * @param wrapper
     */
    public DummyPlugin(PluginWrapper wrapper) {
        super(wrapper);
    }
    private final static Logger LOGGER = LoggerFactory.getLogger(DummyProducer.class);

    @Override
    public void start() {
        LOGGER.info("Start");
    }

    @Override
    public void stop() {
        LOGGER.info("Stop");
    }

    @Extension
    public static class DummyProducer implements ListProducer {
        private final static Logger LOGGER = LoggerFactory.getLogger(DummyProducer.class);

        AutocompleteInfo info = new AutocompleteInfo("dummy", null);

        @Override
        public AutocompleteInfo info() {
            return info;
        }

        @Override
        public List<ListEntry> getList(PluginContext context) {
            List<ListEntry> stage = new LinkedList<>();

            stage.add(new ListEntry("alpha", null));
            //... the other letters...
            stage.add(new ListEntry("omega", null));

            List<ListEntry> result = new LinkedList<>();
            if (StringUtils.isNotBlank(context.getQuery())) {
                String query = context.getQuery().replace("*", "");
                for (ListEntry e: stage) {
                    if (e.getValue().toLowerCase().contains(query.toLowerCase())) {
                        result.add(e);
                    }
                }
            } else {
                result = stage;
            }

            return result;
        }
    }
}

Building the jar File

If the plug-in is packaged in a jar file, there are important points to note:
The following attributes must be specified in the MANIFEST.MF file (in the example plug-in):

Plugin-Class: com.os.services.autocomplete.plugin.demo.DummyPlugin
Plugin-Dependencies:
Plugin-Id: Dummy-Plugin
Plugin-Provider: os
Plugin-Version: 10.0.0

For these values to be automatically inserted into the jar file, the maven-assembly-plugin can be configured accordingly:

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-assembly-plugin</artifactId>
				<version>3.1.0</version>
				<configuration>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
					<finalName>${project.artifactId}-${project.version}-all</finalName>
					<appendAssemblyId>false</appendAssemblyId>
					<attach>false</attach>
					<archive>
						<manifest>
							<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
							<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
						</manifest>
						<manifestEntries>
							<Plugin-Id>${plugin.id}</Plugin-Id>
							<Plugin-Version>${plugin.version}</Plugin-Version>
							<Plugin-Provider>${plugin.provider}</Plugin-Provider>
							<Plugin-Class>${plugin.class}</Plugin-Class>
							<Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies>
						</manifestEntries>
					</archive>
				</configuration>
				<executions>
					<execution>
						<id>make-assembly</id>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

The jar file must contain all required libraries (except autocomplete-plugin-interface and thus also pf4j).
The MANIFEST.MF file must have the appropriate entries.
The extensions.idx file must be included. It is automatically generated by PF4J during build.

This generated jar file can now be placed in the appropriately configured directory of the client-service.

Checking the Plug-in

To check the new plugin, it must be placed in the directory described above and the client-service must be restarted.

Form script usage for dynamic list fields

The endpoints can be directly used for string properties which are classified as a dynamic list. The following form script gives an example:

// fill a dynamic list field with catalog data
var greekalphabet = scope.model.stringc1
scope.api.http.get('/dummy','/app/api/autocomplete').then(
	function(result) {
		greekalphabet.setList({
			entries: result.data.entries
		});
	},
	function(error) {
		scope.api.util.notifier.error('Failed to load greek alphabet',error+'');
	}
)

To produce the data used by the script, the following plug-in must be placed in the folder “autocomplete-plugins”.

The data looks like this:

{
  "entries": [
    {
      "value": "alpha",
      "selectable": true
    },
    {
      "value": "beta",
      "selectable": true
    },
    ...
  ]
}

  • No labels