iKnowBase Development Toolkit

The iKnowBase Development Toolkit enables you to develop iKnowBase Plugins in your IDE and assemble a customer specific edition of the iKnowBase application including the required plugin changes.

While the development toolkit does not replace the standard iKnowBase declarative development model, it provides the developer with a supplement and alternative.

Getting started

Developers are strongly encouraged to participate in a workshop with the iKnowBase product development team before starting with the Development Toolkit.

Read the other chapters after “Getting started” for detailed information about iKnowBase plugins and technology.

About the build system

The Development Toolkit uses the Gradle build system for

Gradle is supported by several of the major IDEs, enabling you to import the Gradle project into the IDE.

Requirements

Your should already have (or do it now):

Distribution files for development

The iKnowBase distribution files for development are

sample-build-root

The sample-build-root is a complete example of a Gradle setup for plugin development. You may use it as is, or develop your own build based on elements in the sample.

sample-plugin-projects

The sample-plugin-projects zip contains a set of technology samples to help you get started developing plugins for iKnowBase.

Step-by-step setup

1. Extract the provided development .zip files

Start with the sample-build-root to create a build workspace. If you want to add the sample projects, we suggest an extraction directory structure like this:

sample-build-root
    sample-plugins
        // contents of sample-plugin-projects here

2. Configure build

gradle.properties

We use Artifactory for dependency resolution for both external 3rd party and
iKnowBase artifacts.

The gradle.properties file is by default configured with the required settings for accessing artifactory.

settings.gradle

Add your plugin projects here. The file contains examples for including the iKnowBase samples as well as set up your custom plugins.

When adding your own plugins, you need to create the project structure that goes with it. The directory structure depends on the type of plugins you create. Each project should contain a build.gradle file (see next section for build.gradle description).

Example:
For the project definition in settings.gradle:

    include 'custom-plugins'
    include 'custom-plugins:custom-java-jar-plugin'
    include 'custom-plugins:custom-groovy-jar-plugin'
    include 'custom-plugins:custom-java-war-plugin'

You need to create the project structure:

    sample-build-root

        custom-plugins

            custom-java-jar-plugin
                build.gradle
                src
                    main
                        java
                        resources
                        
            custom-groovy-jar-plugin
                build.gradle
                src
                    main
                        groovy
                        resources                        

            custom-java-war-plugin
                build.gradle
                src
                    main
                        java
                        resources
                        webapp


              
build.gradle for your plugin projects

We recommend using a build.gradle file per project as shown above. The build.gradle will set up plugin project specifics such as:

For a java (.jar) project:

apply plugin: 'java'

dependencies {
	provided "com.iknowbase:iknowbase-webapp:$ikbVersion"
}

For a groovy (.jar) project:

apply plugin: 'groovy'

dependencies {
	provided "com.iknowbase:iknowbase-webapp:$ikbVersion"
}

For a java web application (.war) project:

apply plugin: 'java'
apply plugin: 'war'

dependencies {
    // use 'providedCompile' instead of 'provided' for war projects
	providedCompile "com.iknowbase:iknowbase-webapp:$ikbVersion"
}

// Customized war that will add module source as jar to WEB-INF/lib instead of the usual WEB-INF/classes
// This avoids name collision for war resources with the same name (like "spring.factories") when patching
// with multiple war files
war {
	// First we'll remove the main build output from the classpath
	classpath = classpath.filter {!(it.name.equals('main'))}
	// And then add the module's jar archive
	classpath jar
}

See sample projects for relevant build.gradle content.

build.gradle for your root project

Include your plugin projects in the dependencies section (NOT in buildscript dependencies!).

3. Configure iKnowBase properties

- Set db.URL, db.ikbUser and db.ikbPassword to match your existing iKnowBase database repository

4. Test from command line

Start a command prompt in the sample-build-root.

The first gradle command entered will trigger download of the gradle binaries and iKnowBase dependencies.

To provide a list of build tasks available to you:

    gradlew tasks

To list all projects in your build:

    gradlew projects

To start the iKnowBase web server with all plugins (that you’ve added to the root project runtime) on localhost port 80:

    gradlew ikbRun

You can access the iKnowBase installation at http://localhost and verify that everything is up and running.

5. Import in your favorite IDE

Now that you know that the base build is OK, it’s time to import to an IDE and start development.

Note: If you change gradle build scripts (settings.gradle, build.gradle) you may need to re-import / refresh to get the updates in your IDE.

IntelliJ IDEA

Open the sample-build-root/build.gradle. The IDE will import and setup the project for you.

Eclipse

Eclipse requires additional gradle plugin: https://github.com/spring-projects/eclipse-integration-gradle/. Once installed, import the sample-build-root as a gradle build. After import select all projects and adjust project properties for Gradle: Project > Properties > Gradle: Classpath sorting strategy: As returned by build script

6. Setup iKnowBase web server run configuration in IDE

Note: If you skipped “ikbRun” step on the command line, you must run the gradle task “ikbPrepare” before starting.

To start iKnowBase with all plugins from the IDE, add an application run configuration with:

Assemble your plugins

All projects may be assembled using:

    gradlew assemble

The resulting jar/war will be generated in <project dir>/build/libs/.

Patch iKnowBase web application with your plugins

When you want to deploy iKnowBase with custom plugins to test/production, you need to create a new patched .war file. The iKnowBase wrapper script (iknowbase.sh|.bat) is recommended for adding assembled plugins to your existing iknowbase-webapp-7.0.4.war.

Given the standard iKnowBase installation directory structure (See Quick installation and upgrade overview ):

    iknowbase-7.0.4
        // extracted distribution files
        
    production (named runtime directory)
        iknowbase.properties
        iknowbase.sh
        
        plugins
            // all plugins should go here
            plugin-1.jar
            plugin-2.war
            
        wars
            // your new patched .war files should go here
            

Assemble your new war with ./iknowbase.sh <config> assembleWar <input> <output> <extensions>:

    cd production
    ./iknowbase.sh iknowbase.properties assembleWar ../iknowbase-7.0.4/wars/iknowbase-webapp-7.0.4.war ./wars/iknowbase-webapp-7.0.4-custom.war ./plugins/*

Run using the iKnowBase web server

Custom .war files, like the one you just created, must explicitly be specified in the iKnowBase properties file.

An alternative for .jar plugins when target server is the iKnowBase web server , is using the web.extraClasspath setting instead of patching the .war file. Point it to your jar files and they will be available in the classpath when the server has started.

    web.extraClasspath=./plugins/*.jar

Deploy

Deploy the new iknowbase-webapp war file to you application server. No special requirements.

Plugin assembly

By using the toolkit, you’ll be able to develop your own as well as include externally developed plugins.

Once developed, a plugin will be assembled to one of two forms:

.jar plugin

A .jar plugin contains

and is the typical choice if you do not require additional libraries.

You may still use the .jar plugin if you require additional libraries, but you must then collect all the library .jars yourself when patching the iKnowBase application war.

build.gradle:

    apply plugin: 'java' // and/or 'groovy', if you prefer groovy development
	
	dependencies {
		provided "com.iknowbase:iknowbase-webapp:$ikbVersion"
	}

.war plugin

A .war plugin contains:

and is the typical choice if you need more than what is offered through a .jar.

Note: The content in the resulting plugin .war file will override the existing content in the source iKnowBase .war file when patching.

build.gradle:

    apply plugin: 'java' // and/or 'groovy', if you prefer groovy development
    apply plugin: 'war'
	
	dependencies {
		// use 'providedCompile' instead of 'provided' for war projects
		providedCompile "com.iknowbase:iknowbase-webapp:$ikbVersion"
	}

	// Customized war that will add module source as jar to WEB-INF/lib instead of the usual WEB-INF/classes
    // This avoids name collision for war resources with the same name (like "spring.factories") when patching
    // with multiple war files
    war {
    	// First we'll remove the main build output from the classpath
    	classpath = classpath.filter {!(it.name.equals('main'))}
    	// And then add the module's jar archive
    	classpath jar
    }

Libraries

Note: All libraries in use by the iKnowBase web application are, due to the current build system, available to your plugin at both compile and runtime. However, all “com.iknowbase” packages except “com.iknowbase.api” are considered internal to iKnowBase and use of these packages are prohibited and without support.

All dependencies are managed in your project’s build.gradle file.

The plugin projects will get all libraries distributed through the iKnowBase application with this dependency:

    // use one of
    provided        "com.iknowbase:iknowbase-webapp:$ikbVersion" //for groovy/java
    providedCompile "com.iknowbase:iknowbase-webapp:$ikbVersion" //for war (even if you java groovy/java plugin activated)

The project may also bring additional libraries, provided they are not conflicting with the existing libraries.

Additional libraries will automatically be included in the resulting plugin .war file when using the .war plugin.

The iKnowBase application container

The iKnowBase application is a java web application based on the Spring Framework (http://projects.spring.io/spring-framework/). Your code will need to be deployed into this application, and can then be used from several points and for several purposes.

Extension points

The table shows what type of extensions and modifications are available

Extension type Language
Spring Configuration Java, Groovy
Spring Bean Java, Groovy
Spring MVC Controller Java, Groovy
Spring MVC View Java, Groovy, Freemarker
Spring MVC Static plugin-resources N/A
Java extension Java
Java Activiti extension Java
Groovy extension Groovy
Freemarker extension Freemarker
Log4j configuration Log4j
Web application override Any

Configuring the application container

The Spring container keeps track of java beans for the lifetime of the iKnowBase application, and many plugins will need to provide their own beans. To expose your beans, you will need to create and expose a configuration class:

In your source code, this typically looks like this:

The Spring Configuration classes are plain Java/Groovy classes annotated with @Configuration (org.springframework.context.annotation.Configuration). A configuration class allows Spring Bean generation and web application context customizations. The class contains methods annotated with @Bean (org.springframework.context.annotation.Bean) where the resulting bean name is the name of the method and the bean type is the declared and returned object.

To load the Spring Configuration class, create src/main/resources/META-INF/spring.factories in your plugin project with:

com.iknowbase.api.server.SpringModule=<YOUR_PACKAGE/YOUR_SPRING_CONFIGURATION_MODULE>

Spring @Beans

Spring beans are objects managed by the Spring container. Beans are generated using the Spring factory pattern described in the “Spring plugin bootstrap” section above.

Inject services

The table below shows the iKnowBase specific services that you can @Autowire in your Spring beans, typically in you @Configuration class. Note that these services are not available as resolved method arguments in a Spring Controller.

Service Description
com.iknowbase.api.contentservices.ContentServicesEngine iKnowBase Content Services API for accessing the iKnowBase ContentServices engine.
com.iknowbase.presentationservices.PresentationServicesEngine iKnowBase Presentation Services API for accessing the iKnowBase PresentationServices engine.

The services below are available directly for backward compatibility reasons. They can (and should) be accessed through the ContentServicesEngine or PresentationServicesEngine above.

Service Description
javax.sql.DataSource DataSource for accessing the iKnowBase Database Repository.
com.iknowbase.api.contentservices.v2.service.DocumentService iKnowBase Content Services API for accessing the iKnowBase Content Repository.

Inject configuration

The iKnowBase applications can be configured as described in Installation Guide > Configuration . You may also add your own configuration keys to this set.

The configurations can be injected in the @Configuration’s @Bean methods using @Value-annotation. You pass the values to your actual bean when constructing the bean.:

Configuration option Default value
@Value(“${JAVA_HOME}”) String javaHome not set
@Value(“${JAVA_HOME:#{null}}”) String javaHome null
@Value(“${JAVA_HOME:null}”) String javaHome “null”
@Value(“${com.iknowbase.pageEngine.contentCacheEnabled:false}”) boolean contentCacheEnabled false
@Value(“${thisKeyShouldNotBePresentUseDefault:default_value}”) String thisKeyShouldNotBePresentUseDefault “default_value”

If a default value has not been specified, the configuration MUST exist.

Spring MVC Controller

The Spring MVC Controller is used to expose your extension at the specified web request path. See the Spring documentation and the provided iKnowBase Development Toolkit samples.

The concept of using a Spring MVC Controller is as follows:

NOTE: DO NOT use the @Controller annotation. Construct your controller bean in the @Configuration class and annotate the Controller itself with @RequestMapping,if you require @RequestMapping support.

Inject services and configurations

Since a Spring MVC Controller is just a regular Spring Bean, you can inject services and configurations as for any @Bean.

Inject method arguments

When Spring runs your @RequestMapping method, it will automatically pass parameter values to that method. In addition to the default argument resolving available for Spring MVC (like HttpServletRequest, HttpServletResponse, etc), the iKnowBase web application supports it’s own set of services and resolved arguments.

The following table shows the iKnowBase specific services available to you in the Spring configuration and controller classes and where it can be injected.

Service Description
com.iknowbase.api.contentservices.ContentServicesClient iKnowBase Content Services Client for accessing the iKnowBase Content Services.
com.iknowbase.api.presentationservices.PresentationServicesClient iKnowBase Presentation Services Client for accessing the iKnowBase Presentation Services.
com.iknowbase.api.presentationservices.client.ActivitiClient iKnowBase Activiti Client for accessing the Activiti process engine.
com.iknowbase.api.presentationservices.client.SolrSearchClientProvider iKnowBase Solr Search Client Provider for accessing the configured Solr Search Clients.
com.iknowbase.api.presentationservices.client.SpringMvcPageEngineClient iKnowBase Spring MVC Page Client for accessing the iKnowBase Page Engine.

Security

Controllers may be annotated with Spring Security annotations if you want to restrict access to a controller method.

Some examples of standard expressions included with Spring Security:

Configuration option Default value
@PreAuthorize(“isAnonymous()”) Access as public user
@PreAuthorize(“isAuthenticated()”) Access as non-public user

In addition to the standard Spring Security annotations, the following iKnowBase specific annotations are supported:

Configuration option Default value
@PreAuthorize(“hasPermission('[ACL_EXTERNAL_KEY]', 'ACL', 'READ')”) ACL membership and privilege READ
@PreAuthorize(“hasPermission('[ACL_EXTERNAL_KEY]', 'ACL', 'MODIFY')”) ACL membership and privilege MODIFY
@PreAuthorize(“hasPermission('[ACL_EXTERNAL_KEY]', 'ACL', 'DELETE')”) ACL membership and privilege DELETE
@PreAuthorize(“hasPermission('executionUser', 'ADMIN')”) Current effective user has administrator privileges
@PreAuthorize(“hasPermission('authenticatedUser', 'ADMIN')”) Real authenticated user has administrator privileges

executionUser and authenticatedUser will normally be the same, but if an administrator has switched to a different user in the current session, the authenticatedUser will be the administrator and the executionUser will be the switched to user.

Static web resources

Static web resources, such as css, javascript and images, can be included in your plugin project. The resources will be assembled and served from jar files.

Note! The static resources namespace will be shared among all plugins. Be sure to use plugin specific directories for your static content.

Alternatively, static web resources may be served as an additional war project of your choosing, like /custom-resources. The /ressurs is by default taken by the iknowbase-resources. See iknowbase.properties if you need to override this behavior.

Activiti

Activiti processes can be extended using Execution Listeners , Task Listeners and Service Tasks .

The iKnowBase Repository Model is accessible from task and execution listeners and service tasks, provided is has been mapped in the process definition.

Using a plugin from iKnowBase Development Studio groovy components

Java or Groovy classes may be used from groovy components you define in iKnowBase Development Studio. This enables you to create reusable components in plugins and access them in both the plugin and the traditional development model.

Logging configuration

Log4j configuration files are present under WEB-INF/classes in the iKnowBase application and you may add additional configurations or override configurations. When overriding, make sure the plugin war has the configurations files defined in WEB-INF/classes as files added here take presedence over files found in library files in WEB-INF/lib.

You may also start the iKnowBase web server with a specific log4j configuration by adding the jvm option -Dlog4j.configuration=file://<your configuration file> to the run configuration in your IDE.

Solr Server

The iKnowBase application server provides a SolrClient-object for easy access to the search functionality of a Solr server. This is often configured using the installation properties of an installation, but if you need more control of the SolrServer connection, you can use the Development Toolkit to configure the server yourself:

@Bean(name="acmeInternetSearch")
public SolrServer createSolrServer() {
    CloudSolrServer cloudSolrServer = new CloudSolrServer("zookeeper.solr.acme.com");
    cloudSolrServer.setParser(new XMLResponseParser());
    return cloudSolrServer;
}

When the above @Bean is exposed to the application container (through a @Configuration class), iKnowBase will automatically discover it, and use it as the basis of a search connection. The name specified in the @Bean will be used for the search server.

Form

iKnowBase simplifies form development that targets iKnowBase documents with

See sample: sample-plugin-form

Bean-to-document mapping

To easily convert between an iKnowBase document and a standard Java Bean (Not a Spring Bean), iKnowBase provides annotations for use in the Java Bean that enables automatic conversion and efficient development.

Annotation Description
@AttributeMapping For mapping iKnowBase attributes to properties. Processed by the BeanProcessor class. Use on getter methods.
@Init For methods that needs to be invoked during initialization of the form backing bean.
@BindingError For methods that needs to be invoked after binding and validation of the form backing bean.
@BeforeBeanToAttributesMapping For methods that needs to be invoked before a bean is converter to DocumentAttributes.
@BeforeInsert For methods that needs to be invoked after conversion to document attributes and before save to iKnowBase repository as new document.
@BeforeUpdate For methods that needs to be invoked after conversion to document attributes and before save to iKnowBase repository updating an existing document.
@AfterLoad For methods that needs to be invoked after load from iKnowBase repository.
@AfterInsert For methods that needs to be invoked after save of new document to iKnowBase repository.
@AfterUpdate For methods that needs to be invoked after save of existing document to iKnowBase repository.

Form Processor

The iKnowBase Presentation Services Form Processor aids with conversion, loading, insert and update of iKnowBase AttributeMapping annotated beans (see previous section). It also provides FreeMarker macros to ease integration with the Java Bean and iKnowBase Metadata.

Form integration with iKnowBase Classic components

An iKnowBase Classic Form may now also be configured as an External Form. An External Form supports mapping against a URL path, where the plugin containing the requested form is available.

If you store the External Form reference on the document, the plugin form will be used in generic iKnowBase Classic edit links.

An External Form may also be connected to document types and set as default form to allow using the plugin form on documents that have no specific form registration.

Normal Quicklink and Target integration for forms also applies to an External Form.

You may convert a Clasic Form component between Classic Form and External Form and thus keep the preexisting form GUID used on the documents.

Java based versions of News Article and Admin Form are available in iKnowBase Content Studio and External Form data has been registered. The form is classic by default, but may easily be converted to an External Form supported by Java. See source code for the forms and their required metadata.

Available samples

The following samples are included when installing the Development Toolkit:

Sample name Description
sample-plugins:sample-activiti-controllers Demonstrates using DataSource, DocumentService and ActivitiClient.
sample-plugins:sample-activiti-process-definitions Demonstrates a project containing Activiti process definitions. Also demonstrates how to map the iKnowBase RepositoryModel, listeners and service task.
sample-plugins:sample-activiti-extensions Demonstrates task and execution listeners for Activiti. Also demonstrates how to use the iKnowBase RepositoryModel.
sample-plugins:sample-plugin-config Demonstrates accessing iKnowBase Configuration options.
sample-plugins:sample-plugin-freemarker Demonstrates various ways of using freemarker as presentation view technology.
sample-plugins:sample-plugin-groovy Demonstrates writing controllers in groovy and use freemarker as presentation view technology as well as various ways of using groovy as presentation view technology.
sample-plugins:sample-plugin-hello Demonstrates a very simple controller for a minimal start.
sample-plugins:sample-plugin-msoffice Demonstrates using a third party library for generating Excel files.
sample-plugins:sample-plugin-static-content Demonstrates using static content, such as css, js and images.
sample-plugins:sample-plugin-form Demonstrates developing forms. See form section for details.

iKnowBase Reference Plugins

While the samples listed above are focused on demonstration of technology, the iKnowBase distribution includes two complete real life plugins that you may use as reference. The source code is provided alongside the distribution.

Sample name Description
iknowbase-content-studio The iKnowBase Content Studio (/cs).
iknowbase-process-studio The iKnowBase Process Studio (/ps).

Troubleshooting

Classpath issues in Eclipse based IDEs

When importing the iknowbase-plugins project with subprojects in Eclipse, the classpath defaults generated by the eclipse plugin is not correctly ordered.

Resolve the issue with

Out of memory issues when building gradle project model

You may encounter issues when building the gradle project model during import in Eclipse. Adjust your gradle.properties file and enable

org.gradle.jvmargs=-Xms128m -Xmx256m

Accented (Norwegian) text loaded using resource bundle has wrong encoding

Make sure the property files (*.properties) are located in source tree ‘src/main/resources’ and NOT ‘src/main/java’. Encode all accented characters using unicode notation "\u".

My Spring MVC Controller is not available as expected on the mapped path

iKnowBase will NOT do any Spring component scanning. To load a Spring controller and expose the methods you need to

NOTE: iKnowBase versions up to and including 6.6 had component scan for the “com.iknowbase.plugin” package. This has been removed and replaced with the spring.factories and @Configuration.

Run from IDE does not start iKnowBase. Seems like application is missing.

The “ikbPrepare” gradle task downloads and unpacks all required iKnowBase web app resources. If you skipped “ikbRun” step on the command line, you must run the gradle task “ikbPrepare” before starting. “ikbRun” will call “ikbPrepare”.