Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

There following questions and steps are to help you plan and develop a plugin to fulfill a custom requirement.

Table of Contents

1.

...

You have a custom requirement and you found that none of the built-in plugins provided by Joget Workflow nor plugins available in Marketplace are able to fulfill your requirement. 

Example 1: Download a PDF version of a form when click on a button in a list.

Example 2: Provide a Gantt Chart view of your collected form data. 

Example 3: Hash variable is convenient in used, but it does not provide the ability to do condition checking.

2. How to solve the problem?

Refer to the Plugin Types that supported by Joget Workflow, find the most appropriate plugin type that can help you to fulfill the custom requirement.

Example 1: Develop a Datalist Action plugin to display a button for generate form PDF.

Example 2: Develop an Userview Menu plugin that can use to display form data as Gantt Chart.

Example 3: Develop a Hash Variable plugin that can do Bean Shell scripting.

3. What is the input needed for your plugin?

Find out what are the information needed by your plugin to function/work. Look at it from the user's perspective; how are you going to use the plugin. Then, look at it from a developer's perspective; to make the plugin reusable in more use cases.

You can refer to Plugin Properties Options on what type of input field you can provide to your plugin user.

Example 1: To develop a PDF Download Datalist Action plugin, we can consider providing the following as input.

    1. Form ID : The form that will be used to generate the PDF file.
    2. Record ID : Use the id of the datalist row or a column value to load the record.
    3. File Name : File name of the the generated PDF file.
    4. Formatting options : Options to format and customise the PDF output. 

Example 2: To develop an Gantt Chat Userview Menu plugin, we can consider providing the following as input.

    1. Datalist Binder : We can reuse datalist binder in our plugin to retrieve the data needed by the Gantt Chart.
    2. Mapping : A field to map the columns that will be returned from the datalist binder to the data needed by the Gantt Chart.
    3. Styling : Options to style the Gantt Chart.

Example 3: Hash Variable plugin does not provide interface for user to configure, but to develop a Bean Shell Hash Variable plugin, we need somewhere to put our Bean Shell script. We can reuse the Environment Variable to store our scripts. So the Hash Variable syntax will be a prefix with environment variable key.

E.g. #beanshell.EnvironmentVariableKey#

But, this may not be enough. We may need some other way to pass in some variable too. We can consider using a URL query parameters syntax to pass in our variables because it is easier to parse later on.

问题是什么?

您有自定义要求,但是您发现Joget Workflow中提供的任何内置插件和Marketplace中提供的插件,都不能满足您的要求。

示例1:单击列表中的按钮时,下载表单的PDF版本。

示例2:提供收集的表单数据的甘特图视图。 

示例3:哈希变量在使用中方便,但不提供进行条件检查的功能。

2. 如何解决问题?

请参阅Joget Workflow支持的  插件类型,找到最适合的插件类型,可以帮助您满足自定义要求。

示例1:开发一个Datalist Action插件以显示用于生成表单PDF的按钮。

示例2:开发一个用户视图菜单插件,可用于将表单数据显示为甘特图。

示例3:开发可以执行Bean Shell脚本的Hash Variable插件。

3. 你的插件需要输入什么?

找出插件所需的功能/工作所需的信息。从用户的角度来看; 你将如何使用插件。然后,从开发者的角度来看它; 使插件在更多的用例中可重用。

您可以参考  插件属性选项,了解您可以为插件用户提供什么类型的输入字段。

示例1:要开发PDF下载Datalist Action插件,我们可以考虑提供以下内容作为输入。

    1. 表单ID:用于生成PDF文件的表单。
    2. 记录ID:使用datalist行的id或列值来加载记录。
    3. 文件名:生成的PDF文件的文件名。
    4. 格式化选项:格式化和自定义PDF输出的选项。 

示例2:要开发Gantt Chat Userview菜单插件,我们可以考虑提供以下内容作为输入。

    1. Datalist Binder:我们可以在我们的插件中重用datalist binder来检索甘特图所需的数据。
    2. 映射:一个字段,用于映射将从数据记录器绑定器返回到甘特图所需数据的列。
    3. 造型:甘特图风格选择。

示例3:Hash Variable插件不提供用户配置的界面,但是要开发一个Bean Shell Hash Variable插件,我们需要在某处放置我们的Bean Shell脚本。我们可以重用环境变量来存储我们的脚本。所以哈希变量语法将是带有环境变量键的前缀。

e.g.g.  #beanshell.EnvironmentVariableKey#

但是,这可能还不够。我们可能需要一些其他方式来传递一些变量。我们可以考虑使用URL查询参数语法来传入我们的变量,因为以后更容易解析。

例如#beanshellE.g. #beanshell.EnvironmentVariableKey [name=Joget&email=info@jogetinfo@joget.org&message= {form.sample.message?urlmessage?url}]#

4.

...

你的插件的输出和预期结果是什么?

普通用户(不是使用插件提供功能的管理员用户)将如何以及何种方式使用并查看您的插件结果。

示例1:当PDF下载Datalist Action用作数据行列操作或列操作时,普通用户将看到一个链接,以便在datalist的每一行中下载PDF文件。点击链接后,将提示PDF下载。

当插件用作整个数据记录操作时,将提示包含每个选定行的所有生成的PDF的zip文件被下载。

示例2:当使用甘特图用户视图菜单插件的菜单被点击时,普通用户可以看到甘特图。用户可以浏览甘特图或与甘特图交互。 

示例3:Bean Shell Hash Variable插件适用于管理员用户。一旦使用,Hash变量将被Bean Shell解释器的输出返回所替代。

5. 有没有可以重用的资源/ API?

总是参考  现有的插件教程,以寻找类似的插件/插件类型,尽可能引用它们。Joget团队将尽力丰富教程部分的内容。

您可能需要查看实用程序和服务方法文档  ,  JSON API,  Javascript API和  Bean Shell编程指南。这些文件可能包含一些可能有助于您开发的方法/示例。

示例1:要开发PDF下载Datalist Action插件,我们可以重用FormPdfUtil中的方法  来生成PDF格式的表单。我们也可以参考Datalist Form Data Action Action插件的源代码。除此之外,我们可以参考导出表单电子邮件工具  ,在导出表单电子邮件工具使用FormPdfUtil中的方法时,我们可以在插件中提供什么样的插件属性选项。

示例2:要开发甘特图用户视图菜单插件,我们可以参考所有Userview Menu插件的源代码。从那里,我们可以更好地了解如何使用FreeMaker 语法为插件创建模板  。 

示例3:要开发Bean Shell Hash Variable插件,我们可以参考所有Hash Variable插件和Bean Shell插件的源代码。特别是,我们可以参考环境变量哈希变量插件关于如何使用变量键检索环境变量。我们还可以参考Bean Shell工具或Bean Shell Form Binder插件,使用Bean Shell解释器执行脚本。

6. 准备你的开发环境

a. 您将需要  准备好构建Joget工作流开放源码. 我们将使用“wflow-plugin-archetype”模块为我们的插件生成一个maven项目。

b. 生成一个maven项目

生成的项目文件将放置在命令提示符中指定的目录中,例如:在“C:\”中运行命令将项目文件放在C盘的根目录下。

要获取正确的jogetDependencyVersion以便构建具有正确依赖关系的正确的项目文件,请检查目录下的“.m2”文件夹中指定的文件名,例如:

C:\ Users \(您的计算机名)

How and what a normal user (Not the admin user who use the plugin to provide functionality) will use and see your plugin result.

Example 1: When PDF Download Datalist Action is used as a datalist row action or column action, a normal user will see a link to download the PDF file in every rows of a datalist. Once the link is clicked, a PDF will be prompted to be downloaded.

When the plugin is used as a whole datalist action, a zip file containing all the generated PDF of every selected rows will be prompted to be downloaded.

Example 2: A normal user can see a Gantt Chart when a menu using the Gantt Chart Userview Menu plugin is clicked. User may navigate or interact with the Gantt Chart. 

Example 3: The Bean Shell Hash Variable plugin is for the admin user. Once it is used, the Hash Variable will be replaced by the output return from the Bean Shell interpreter.

5. Are there any resources/API that can be reused?

Always refer to existing plugins and tutorials to look for a similar plugin/plugin type that you can refer to whenever possible.  The Joget team will try their best to enrich the contents in the tutorials section.

You may need to check out the document of Utility & Service MethodsJSON APIJavascript API and Bean Shell Programming Guide as well. These documents may contains some methods/examples that may help you in the development.

Example 1: To develop the PDF Download Datalist Action plugin, we can reuse the methods in FormPdfUtil to generate a form as PDF. We can also refer to the source code of the Datalist Form Data Delete Action plugin as well. Other than that, we can refer to the Export Form Email Tool on what kind of plugin properties options we can provide in the plugin as the Export Form Email Tool are using the methods in FormPdfUtil as well.

Example 2: To develop a Gantt Chart Userview Menu plugin, we can refer to the source code of all the Userview Menu plugin. From there, we can have a better understanding on how to make a template for a plugin using FreeMaker syntax. 

Example 3: To develop Bean Shell Hash Variable plugin, we can refer to the source code of all the Hash Variable plugin and Bean Shell plugin. Especially, we can refer to Environment Variable Hash Variable plugin on how to retrieve environment variable using a variable key. We can also refer to Bean Shell Tool or Bean Shell Form Binder plugin on what to execute the script with Bean Shell interpreter.

6. Prepare your development environment

a. You will need to have the Joget Workflow 开放源码 ready and built. We will use the "wflow-plugin-archetype" module to generate a maven project for our plugin.

b. Generate a maven project.

The project file generated will be placed at the directory specified in the command prompt, eg: running the command in "C:\" will place the project file in the root of C drive.

To get the correct jogetDependencyVersion in order to build a proper project file with correct dependencies, check the file name specified in the ".m2" folder under directory of, eg:

C:\Users\(your computer name)\.m2 \ repository \ org \ joget \ wflow-core \ "5.0.111"

Run the following for Window 

...

c. Open/Import the maven project with your favorite IDE. Joget team recommends NetBeans IDE.  

7.

...

仅仅是去编码!

a.

...

扩展插件类型的抽象类

Refer to the document of the plugin type listed in Plugin Types. Find the abstract class and interface that need to be extended and implemented by your plugin.

Example: To develop a Userview Menu plugin, the plugin class need to extends the org.joget.apps.userview.model.UserviewMenu abstract class.

b.

...

A plugin will have to implements the abstract method of 插件抽象类和接口 and also the abstract method of the individual abstract class and interface for the plugin type. 

实现所有抽象方法

插件必须实现  插件抽象类和接口的抽象方法,以及插件类型的抽象类和接口的抽象方法。 

示例:要开发一个  Userview菜单插件插件必须实现以下方法。有关各种方法的详细信息,请参阅插件文档。Example: To develop a Userview Menu plugin, the following methods have to be implemented by the plugin. Please refer to the plugin documents for the details of each methods.

  • getCategory
  • getClassName
  • getDecoratedMenu
  • getDescription
  • getIcon
  • getLabel
  • getName
  • getPropertyOptions
  • getRenderPage
  • getVersion
  • isHomePageSupported

c.

...

管理插件的依赖库

The generated plugin folder by "wflow-plugin-archetype" module is a maven project. So, we will using the Dependency Mechanism provided by Maven.

d.

...

使您的插件国际化(i18n)

  • 要使插件i18n准备好,我们需要为插件创建一个消息资源包属性文件。

    • 在“

To make the plugin i18n ready, we need to create a message resource bundle property file for the plugin.

  • Create a property file with the plugin class name in "
    • [Plugin project directory] / src / main / resources /
    message" directory. 
    Example: For a plugin named "GanttChartMenu", we need to create a "GanttChartMenu.properties" file under "
    • message”目录中创建一个带有插件类名称的属性文件。 

      示例:对于名为“GanttChartMenu”的插件,我们需要在“[Plugin project directory] / src / main / resources /

    message" directory
    • message”目录下创建一个“GanttChartMenu.

     
    • properties”文件。 

    Sample content for GanttChartMenu.properties file
    • GanttChartMenu.properties文件的示例内容

    Code Block
    languagejava
    org.joget.sample.GanttChartMenu.pluginLabel=Gantt Chart
    org.joget.sample.GanttChartMenu.pluginDesc=To display form data in Gantt Chart layout
    userview.ganttChart.label.title=Title
    userview.ganttChart.label.week=Week
    Use getMessage(String key, String pluginName, String translationPath) of PluginManager or AppPluginUtil to retrieve i18n label.
    Example: Use the getMessage method in getLabel and getDescription methods to return i18n label and description.
  • 使用PluginManagerAppPluginUtil的 getMessage(String key,String pluginName,String translationPath)   来检索i18n标签。

    示例:在getLabel和getDescription方法中使用getMessage方法返回i18n标签和描述。

     

    Code Block
    languagejava
    public String getLabel() {
        return AppPluginUtil.getMessage("org.joget.sample.GanttChartMenu.pluginLabel", getClassName(), "message/GanttChartMenu");
    }
    public String getDescription() {
        return AppPluginUtil.getMessage("org.joget.sample.GanttChartMenu.pluginDesc", getClassName(), "message/GanttChartMenu");
    }
  • Pass a translation file path to readPluginResource通过一个翻译文件路径readPluginResource(String pluginName, String resourceUrl, Object[] arguments, boolean removeNewLines, String translationFileName) method of AppUtil to provide the plugin properties option with i18n label.  We can use "@@message.key@@" in the JSON of Plugin Properties Options.
    Example: For property options of a GanttChartMenu plugin, the following shows the sample code implementation of getPropertyOptions method and the GanttChartMenu.json file 方法  AppUtil以提供与I18N标签插件属性选项。我们可以在“ 插件属性选项 ”的JSON中使用“@@ message.key @@”  。

    示例:对于GanttChartMenu插件的属性选项,以下显示了getPropertyOptions方法和GanttChartMenu.json文件的示例代码实现

     

    Code Block
    languagejava
    public String getPropertyOptions() {
        return AppUtil.readPluginResource(getClassName(), "/properties/GanttChartMenu.json", null, true, "message/GanttChartMenu");
    }
    Code Block
    languagejs
    [{
        title : '@@userview.ganttChart.edit@@',
        properties : [{
            name : 'id',
            label : 'Id',
            type : 'hidden'
        },
        {
            name : 'customId',
            label : '@@userview.ganttChart.customId@@',
            type : 'textfield',
            regex_validation : '^[a-zA-Z0-9_]+$',
            validation_message : '@@userview.ganttChart.invalidId@@'
        },
        {
            name : 'label',
            label : '@@userview.ganttChart.label@@',
            type : 'textfield',
            required : 'True',
            value : '@@userview.ganttChart.label.value@@'
        }]
    }]
    Pass a translation file path to getPluginFreeMarkerTemplate(Map data, final String pluginName, final String templatePath, String translationPath) method of PluginManager whenever retrieving a HTML template. Once we passed a translation file path, we can use "@@message.key@@" in the freemarker template to retrieve i18n label.
    Example: For getRenderPage method of a GanttChartMenu plugin, the following show the sample code implementation of getRenderPage method and the "GanttChartMenu.ftl" FreeMarker template.
  • 在检索HTML模板时,将PluginManager的翻译文件路径传递给getPluginFreeMarkerTemplate(Map数据,最终String pluginName,final String templatePath,String translationPath)方法  。一旦我们通过了翻译文件路径,我们可以在freemarker模板中使用“@@ message.key @@”来检索i18n标签。

    示例:对于GanttChartMenu插件的getRenderPage方法,下面显示了getRenderPage方法和“GanttChartMenu.ftl”FreeMarker模板的示例代码实现。 

     

    Code Block
    languagejava
        public String getRenderPage() {
            Map model = new HashMap();
            model.put("request", getRequestParameters());
            model.put("element", this);
            
            PluginManager pluginManager = (PluginManager)AppUtil.getApplicationContext().getBean("pluginManager");
            String content = pluginManager.getPluginFreeMarkerTemplate(model, getClasstName(), "/templates/GanttChartMenu.ftl", "message/GanttChartMenu");
            return content;
        }
    Code Block
    languagexml
    <div>
        <h1>@@userview.ganttChart.label.title@@ : ${element.properties.title!}</h1>
    </div>
  • Postfix the plugin class name with an underscore and language code to create a message resource bundle property file for other language. 
  • 使用下划线和语言代码后缀插件类名,以便为其他语言创建消息资源包属性文件

示例:GanttChartMenuExample: GanttChartMenu_zh_CN.properties

e. Register your plugin to the Felix Framework

You will find that a class named "Activator.java" is auto generated in a package of your plugin maven project. The class is used to register your plugin class to the Felix Framework. You do not need to do this if your plugin is not an OSGI Plugin.

 将您的插件注册到Felix框架

你会发现一个名为“Activator.java”的类是在您的插件maven项目的包中自动生成的。该类用于将您的插件类注册到  Felix Framework。如果您的插件不是OSGI插件,则不需要这样做。

在激活器类的start方法中,将你的插件类添加到“registrationList”变量中。In the start method of the activator class, add your plugin class to the "registrationList" variable.

Code Block
languagejava
public void start(BundleContext context) {
    registrationList = new ArrayList<ServiceRegistration>();

    //Register plugin here
    registrationList.add(context.registerService(MyPlugin.class.getName(), new MyPlugin(), null));
}

f.

...

构建和测试

完成上述所有步骤后,您可以使用Maven使用IDE构建项目。您还可以在项目目录中运行“mvn clean install”命令来构建它。构建项目后,在您的插件项目文件夹中的“目标”文件夹下创建一个jar文件。将插件jar上传到  管理插件以测试插件。

示例:在Eclipse中,右键单击项目名称,然后选择"maven clean install".

Image Added

8. 更进一步,分享或出售

你已经完成了一个非常有用的插件。不要只是把它保存在自己,在Joget Marketplace中分享或销售您的插件,  甚至,您可以在我们的知识库中编写一个教程,以便与他人分享您的工作。要分享或销售您的插件,请发送电子邮件至info@joget.org

Once you are done with all the steps above, you can build your project with your IDE using Maven. You can also run "mvn clean install" command in your project directory to build it. After building your project, a jar file is created under "target" folder in your plugin project folder. Upload the plugin jar to Manage Plugins to test your plugin.

Example: In NetBeans, right-click on the project name, then select "Clean and Build".

Image Removed

8. Take a step further, share it or sell it

You have completed a very useful plugin. Don't just keep it to yourself, share or sell your plugin in the Joget Marketplace or even better, you can write a tutorial in our Knowledge Base to share your effort with others. To share or sell your plugin, please send an email to info@joget.org.