JNW Toolkit overview
JNW Toolkit is a collection of libraries that simplify development with the Java Native Worker (JNW). Each library can be used independently and implements some specific feature that can be used when needed and ignored when it is not.
Bill of Materials
Each version of JNW Toolkit is built for compatibility with a specific version of the JNW. The jnw-tookit-bom module is a Bill of Materials or BOM. When imported, it provides versions for all JNW modules, transitive dependencies required by it, and other compatible utilities like the worker-task-test library.
To use jnw-tookit-bom, complete the following steps:
Add a version of
jnw-toolkitto the<properties>section of your Maven project:<properties>
<wf.jnw-toolkit.version>1.0.0.17</wf.jnw-toolkit.version>
<!--
1.0.0.17 is the earliest version that supports all features described in the article.
1.0.0.17.1 is the earliest version that supports all features described in the article for Platform version 10.2.8.
You might need to look for the recent version.
-->
</properties>If your project is a part of the workfusion-meta pipeline, add a dependency to jnw-toolkit to the
components.yamlfile of theworkfusion-metaproject:your-project:
dependencies:
- jnw-toolkitImport
jnw-toolkit-parentin the<dependencyManagement>section of the Maven project.<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-bom</artifactId>
<version>${wf.jnw-toolkit.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
You can add any module of JNW Toolkit, the JNW, the worker-task-test library, or any other dependency mentioned in jnw-tookit-bom as a project dependency without worrying about which version to use, for example:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-auto-task-processor</artifactId>
</dependency>
</dependencies>
Other chapters of the article are written with the assumption that jnw-tookit-bom is imported into the project, so dependency versions are not mentioned.
Code generation
The jnw-toolkit-auto-task-processor and jnw-toolkit-auto-task-processor-xml modules are responsible for the auto-generation of Task Processor classes and other boilerplate code required for running Bot Tasks on the JNW.
Configuration
Add the jnw-toolkit-configuration module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-configuration</artifactId>
</dependency>
</dependencies>
Now, you can inject an object of the TaskConfigurationProvider class:
@Autowired
TaskConfigurationProvider taskConfigurationProvider;
You can call the TaskConfigurationProvider methods to get an instance of the JsonConfiguration class:
TaskConfigurationProvider.getDigitalWorkerConfiguration()returns an object containing configuration data for the AI Agent (or AI Digital Worker).TaskConfigurationProvider.getTaskConfiguration(TaskConfiguration)returns an object containing configuration data for a currently running task.TaskConfigurationProvider.getMergedConfiguration(TaskConfiguration)returns an object that tries to read the configuration first from the context of the task and then from the context of the AI Digital Worker.
The JsonConfiguration instances must not be stored between executions of the task. Every time your code needs to access the configuration, TaskConfigurationProvider.get... must be called to retrieve a fresh up-to-date instance.
JsonConfiguration offers the following methods:
Optional<String> getProperty(String name);
String getRequiredProperty(String name);
<T> Optional<T> getProperty(String name, Class<T> valueClass);
<T> T getRequiredProperty(String name, Class<T> valueClass);
<T> List<T> getArrayProperty(String name, Class<T> valueClass);
They are well documented in the source code and designed like counterparts in ODF 2. You can use the JsonPath expressions to retrieve data from complex and nested JSON data structures.
Overriding configuration
You can provide additional configuration data to JNW Toolkit through Spring configuration properties. First, all configurations returned by TaskConfigurationProvider read properties from the additional data and only then from the task or AI Digital Worker configuration.
There are several options you can use:
- Add JSON to the
jnw.configuration.json.stringproperty. - Add the name of the file with the JSON content to the
jnw.configuration.json.fileproperty.
If used simultaneously, jnw.configuration.json.string takes precedence over jnw.configuration.json.file.
See example
A JsonConfiguration object returned by TaskConfigurationProvider.getMergedConfiguration() searches for properties in the following order:
In the content passed in the
jnw.configuration.json.stringproperty (if present).In the content of the file passed in the
jnw.configuration.json.fileproperty (if present).In the configuration data for a currently running Bot Task.
In the configuration data for the AI Digital Worker that contains the Business Process with the currently running Bot Task.
Execution context
Add the jnw-toolkit-context module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-context</artifactId>
</dependency>
</dependencies>
Now, you can inject an object of the TaskExecutionContext class:
@Autowired
TaskExecutionContext taskExecutionContext;
You can use the class methods to get the assorted context and configuration information for a currently running task:
TaskExecutionContext.getBpExecutionUuid()gets a UUID of a current Business Process execution.TaskExecutionContext.getDigitalWorkerConfigurationJson()gets a raw configuration JSON for the AI Digital Worker used byTaskConfigurationProvider.getDigitalWorkerConfiguration().
Control Tower services
Add the jnw-toolkit-control-tower-services module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-control-tower-services</artifactId>
</dependency>
</dependencies>
Now, you can inject objects of the ControlTowerBpService and ControlTowerTaskService classes:
@Autowired
ControlTowerBpService controlTowerBpService;
@Autowired
ControlTowerTaskService ControlTowerTaskService;
ControlTowerBpService sends a request to Control Tower for information on any Business Process by its ID.
ControlTowerTaskService starts a task or Business Process in Control Tower by providing a Campaign ID and input data.
For more details on API, refer to its documentation in the source code.
Access to Control Tower database
Add the jnw-toolkit-datastores module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-datastores</artifactId>
</dependency>
</dependencies>
Now, all Spring-compatible database frameworks are by default configured to access the Control Tower database (DB). You can use Spring Data JDBC, JPA or Hibernate, or any other compatible library to access the DB in any way you like.
If you port a project from ODF 2 and would like to continue to use ORMLite and ODF 2 Repository classes, use a compatibility tool in ODF 2. For more details, see Use ODF 2 Data Stores in Java Native Worker.
S3 Client
Add the jnw-toolkit-s3-client module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-s3-client</artifactId>
</dependency>
</dependencies>
Now, you can inject an object of the S3Service class:
@Autowired
com.workfusion.jnw.toolkit.s3.S3Service s3Service;
S3Service is a convenience API wrapper for the S3 client library by Amazon. It is configured by default to access Control Tower's MinIO instance.
For more details on API, refer to the documentation in the source code. It is designed in the same way as its counterpart in ODF 2.
You can also inject AmazonS3 or AmazonS3ClientBuilder if you need some low-level API that is not provided by S3Service. The objects are also configured by default to access Control Tower's MinIO instance.
Bot Task lifecycle
Add the jnw-toolkit-lifecycle module as a project dependency:
<dependencies>
<dependency>
<groupId>com.workfusion.jnw.toolkit</groupId>
<artifactId>jnw-toolkit-lifecycle</artifactId>
</dependency>
</dependencies>
Now, you can create your Bot Task like in ODF 2, with init(), shouldRun(), and other lifecycle methods. To do this, implement the ClassicLifecycle interface and inject the ClassicLifecycleRunner object:
@TaskProcessor(id = "lifecycle-demo-task")
public class LifecycleDemoTaskProcessor implements ITaskProcessor, ClassicLifecycle {
@Autowired
ClassicLifecycleRunner lifecycle;
@Override
public TaskOutputData process(TaskInputData taskInputData) throws TaskProcessorException {
// will call lifecycle methods according to logic similar to one in ODF 2
return lifecycle.run(this, taskInputData);
}
@Override
public void init(TaskInputData input) {
// do something here
}
@Override
public boolean shouldRun(TaskInputData input) {
// do something here
}
@Override
public TaskOutputData run(TaskInputData input) {
// do something here
}
@Override
public TaskOutputData handleException(TaskInputData input, Exception e) {
// do something here
}
}
For more details on API, refer to the ClassicLifecycle and ClassicLifecycleRunner source code.