Versions Compared

Key

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

...

ในบทนี้ เราจะทำตาม guideline for developing a plugin เพื่อพัฒนาปลั๊กอิน Bean Shell Hash Variable ของเรา 

1.

...

ปัญหาคืออะไร?

Hash variable is convenient to use, but sometime we want to do some condition check before displaying a value. But, Hash variable does not provide the ability for condition checking.

2. How to solve the problem?

By looking at the Plugin Types that are currently supported by Joget Workflow, we can develop a Hash Variable Plugin to allow us to write our scripting for condition checking. There are quite a number of Bean Shell plugins provided as default plugin for several plugin types. We can do one for Hash Variable plugin as well.

3. What is the input needed for your plugin?

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 script. 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 also. We can consider using a URL query parameters syntax to pass in our variables because it is easier to parse later on.

สะดวกในการใช้งาน แต่บางครั้งเราต้องการตรวจสอบางเงื่อนไขก่อนที่จะแสดงค่า แต่ตัวแปร Hash variable ไม่สามารถตรวจสอบได้

2. วิธีการแก้ปัญหา?

โดยดูที่ Plugin Types ได้ที่รับการสนับสนุนโดย Joget Workflow เราสามารถพัฒนา Hash Variable Plugin เพื่อให้เราสามารถเขียนสคริปต์เพื่อตรวจสอบเงื่อนไขได้ มีปลั๊กอิน Bean Shell จำนวนหนึ่งที่ให้ไว้เป็นปลั๊กอินเริ่มต้นสำหรับปลั๊กอินหลายประเภท เราสามารถทำปลั๊กอิน Hash Variable ได้เช่นกัน

3. อินพุตที่จำเป็นสำหรับปลั๊กอินของคุณคืออะไร?

ปลั๊กอิน Hash Variable  ไม่มีส่วนต่อประสานสำหรับผู้ใช้ในการกำหนดค่า แต่เพื่อการพัฒนาปลั๊กอิน Bean Shell Hash Variable เราต้องการใส่ Bean Shell script ของเรา เราสามารถนำ Environment Variable มาใช้ใหม่เพื่อจัดเก็บสคริปต์ของเรา ดังนั้นไวยากรณ์ Hash Variable จะเป็นคำนำหน้าด้วยคีย์ตัวแปรสภาพแวดล้อม

เช่น. #beanshell.EnvironmentVariableKey#

แต่นี่อาจไม่เพียงพอ เราอาจต้องการวิธีอื่นในการส่งผ่านตัวแปรบางตัวเช่นกัน เราสามารถพิจารณาการใช้ไวยากรณ์พารามิเตอร์การสืบค้น URL เพื่อส่งผ่านตัวแปรของเราเพราะง่ายต่อการแยกวิเคราะห์ในภายหลัง

เช่นE.g. #beanshell.EnvironmentVariableKey[name=Joget&email=info@joget.org&message={form.sample.message?url}]#

4.

...

ผลลัพธ์และผลลัพธ์ที่คาดหวังของปลั๊กอินของคุณคืออะไร?

เราคาดหวังอะไรจากปลั๊กอิน What do we expected from this Bean Shell Hash variable plugin? The Bean ปลั๊กอิน Bean Shell Hash Variable plugin is for ใช้สำหรับ admin/developer user to use when ที่จะใช้เมื่อ building/developing an app. Once used, the Hash Variable will be replaced by the output return from the Bean Shell interpreter. So that the admin user can do condition check before display something to normal user.

E.g. Display a welcome message for logged in user but display nothing when the user is an anonymous.

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

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 the Environment Variable Hash Variable plugin on how to retrieve environment variable using a variable key. We can also refer to the Bean Shell Tool or Bean Shell Form Binder plugin on what to execute the script with Bean Shell interpreter. 

แอป. เมื่อใช้แล้ว ตัวแปร Hash Variable จะถูกแทนที่ด้วยผลลัพธ์ที่ส่งคืนจาก Bean Shell interpreter. เพื่อให้ผู้ใช้ที่เป็นผู้ดูแลระบบสามารถทำการตรวจสอบสภาพก่อนที่จะแสดงบางสิ่งกับผู้ใช้ปกติ

เช่น แสดงข้อความต้อนรับสำหรับผู้ใช้ที่ล็อกอิน แต่ไม่แสดงสิ่งนี้เมื่อผู้ใช้ไม่ระบุชื่อ

5. มีทรัพยากร / API ใด ๆ ที่สามารถนำกลับมาใช้ใหม่ได้หรือไม่?

เพื่อการพัฒนาปลั๊กอิน Bean Shell Hash Variable  เราสามารถอ้างอิงถึง source code จากทั้งหมดปลั๊กอิน Hash Variable และปลั๊กอิน Bean Shell Especially, เราสามรถอ้างอิงถึงตัวแปรปลั๊กอิน Environment Variable Hash Variable  เกี่ยวกับวิธีเรียกข้อมูลตัวแปร environment variable โดยใช้ตัวแปร variable key. เราสามารถอ้างอิงถึง Bean Shell Tool หรือปลั๊กอิน Bean Shell Form Binder  สิ่งที่จะรันสคริปต์ด้วย Bean Shell interpreter. 

เราสามารถใช้วิธี getUrlParams method ได้ จาก StringUtil เพื่อช่วยเราวิเคราะห์ parameters ที่ส่งผ่านด้วย We can use getUrlParams method from StringUtil to help us parse parameters passed in with URL query parameters syntax.

6.

...

เตรียมสภาพแวดล้อมการพัฒนาของคุณ

เราจำเป็นต้องมี We need to always have our Joget Workflow Source Code ready and builded by following ให้พร้อม และสร้างโดยทำตาม this guideline นี้

บทช่วยสอนต่อไปนี้จัดทำขึ้นด้วย Macbook Pro และ The following tutorial is prepared with a Macbook Pro and Joget Source Code version 5.0.0. Please refer to the แนวทางสำหรับการพัฒนาปลั๊กอิน article for other platform commands.

Let say our folder directory is as following. 

โปรดดูที่ แนวทางสำหรับการพัฒนาปลั๊กอิน บทความสำหรับคำสั่งแพลตฟอร์มอื่น ๆ

สมมติว่าไดเรกทอรีโฟลเดอร์ของเรามีดังต่อไปนี้

Code Block
- Home
  - joget
    - plugins
    - jw-community
      -5.0.0

The "plugins" directory is the folder we will create and store all our plugins and the directory คือโฟลเดอร์ที่เราจะสร้างและจัดเก็บปลั๊กอินทั้งหมดของเราและ "jw-community" directory is where the directory คือที่เก็บซอร์สโค้ด Joget Workflow Source code stored.

เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างโครงการ maven ในไดเรกทอรี Run the following command to create a maven project in "plugins" directory.

Code Block
languagebash
cd joget/plugins/
~/joget/jw-community/5.0.0/wflow-plugin-archetype/create-plugin.sh org.joget.tutorial beanshell_hash_variable 5.0.0

Then, the shell script will ask us to key in a version number for the plugin and ask us for a confirmation before it generates the maven project.จากนั้น the shell script จะขอให้เราใส่หมายเลขเวอร์ชันสำหรับปลั๊กอินและขอให้เรายืนยันก่อนที่จะสร้างโครงการ Maven

Code Block
languagebash
Define value for property 'version':  1.0-SNAPSHOT: : 5.0.0
[INFO] Using property: package = org.joget.tutorial
Confirm properties configuration:
groupId: org.joget.tutorial
artifactId: beanshell_hash_variable
version: 5.0.0
package: org.joget.tutorial
Y: : y

We should get เราควรได้รับข้อความ "BUILD SUCCESS" message shown in our terminal and a ที่แสดงใน terminal ของเราและ "beanshell_hash_variable" folder created in สร้างโฟลเดอร์ใน "plugins" folder.

Open the เปิด maven project with your favour ของคุณด้วย IDE ที่ชื่นชอบ. I will be usingเราแนะนำ NetBeans.  

7.

...

เริ่มโค้ด!

a. Extending the abstract class of a plugin type

Create a สร้าง "BeanShellHashVariable" ภายใต้ class under "org.joget.tutorial" package.

Then, based on จากนั้น ขึ้นอยู่กับเอกสาร Hash Variable Plugin document, we will have to extends  ,เราจะต้องขยาย org.joget.apps.app.model.DefaultHashVariablePlugin abstract class.

...

Code Block
languagejava
titleImplementation of all basic abstract methods
collapsetrue
package org.joget.tutorial;
 
import org.joget.apps.app.model.DefaultHashVariablePlugin;
import org.joget.apps.app.service.AppPluginUtil;
 
public class BeanShellHashVariable extends DefaultHashVariablePlugin {
    
    private final static String MESSAGE_PATH = "messages/BeanShellHashVariable";
 
    public String getName() {
        return "BeanShellHashVariable";
    }
 
    public String getVersion() {
        return "5.0.0";
    }
 
    public String getClassName() {
        return getClass().getName();
    }
    
    public String getLabel() {
        //support i18n
        return AppPluginUtil.getMessage("org.joget.tutorial.BeanShellHashVariable.pluginLabel", getClassName(), MESSAGE_PATH);
    }
    
    public String getDescription() {
        //support i18n
        return AppPluginUtil.getMessage("org.joget.tutorial.BeanShellHashVariable.pluginDesc", getClassName(), MESSAGE_PATH);
    }
 
    public String getPropertyOptions() {
        //Hash variable plugin do not support property options
        return "";
    }
    
    public String getPrefix() {
        return "beanshell";
    }
    
    public String processHashVariable(String variableKey) {
        throw new UnsupportedOperationException("Not supported yet."); 
    }
}

Now, let's focus on the main method of our Hash Variable plugin which is processHashVariable. We will refer to the source code of ตอนนี้ เรามาดูวิธีการหลักของปลั๊กอิน Hash Variable ซึ่งเป็น processHashVariable. เราจะอ้างถึง source code ของ Environment Variable Hash Variable plugin on how to retrieve the เกี่ยวกับวิธีดึงข้อมูล Environment variable. Thenจากนั้น, refer to the อ้างถึง source code of ของ Bean Shell Form Binder on how to execute a เกี่ยวกับการดำเนินการ bean shell script.

Code Block
languagejava
    public String processHashVariable(String variableKey) {
        try {
            String environmentVariableKey = variableKey;
            
            //first check and retrieve parameters passed in with URL query parameters syntax wrapped in square bracket []
            String queryParams = null;
            if (variableKey.contains("[") && variableKey.contains("]")) {
                queryParams = variableKey.substring(variableKey.indexOf("[") + 1, variableKey.indexOf("]"));
                environmentVariableKey = variableKey.substring(0, variableKey.indexOf("["));
            }
 
            //Parse the query parameters to a map
            Map<String, String[]> parameters = null;
            if (queryParams != null && !queryParams.isEmpty()) {
                parameters = StringUtil.getUrlParams(queryParams);
                
                //put all parameters to plugin properties
                getProperties().putAll(parameters);
            }
 
            //Retrieve the environment variable based on environmentVariableKey
            AppDefinition appDef = (AppDefinition) getProperty("appDefinition");
            if (appDef != null) {
                ApplicationContext appContext = AppUtil.getApplicationContext();
                EnvironmentVariableDao environmentVariableDao = (EnvironmentVariableDao) appContext.getBean("environmentVariableDao");
                EnvironmentVariable env = environmentVariableDao.loadById(environmentVariableKey, appDef);
                if (env != null) {
                    String script = env.getValue();
                    //execute the script with all plugin properties
                    return executeScript(script, getProperties());
                } else {
                    //environment variable not found, return empty value
                    return "";
                }
            }
        } catch (Exception e) {
            //log the exception using LogUtil
            LogUtil.error(getClassName(), e, "#beanshell."+variableKey+"# fail to parse.");
        }
        
        //return null to by pass the replacing
        return null;
    }
    
    protected String executeScript(String script, Map properties) throws Exception {
        Interpreter interpreter = new Interpreter();
        interpreter.setClassLoader(getClass().getClassLoader());
        for (Object key : properties.keySet()) {
            interpreter.set(key.toString(), properties.get(key));
        }
        LogUtil.debug(getClass().getName(), "Executing script " + script);
        return (String) interpreter.eval(script);
    }

c.

...

จัดการ dependency libraries

...

ปลั๊กอินของคุณ

คลาสปลั๊กอินของเราไม่สามารถแก้ไขได้ Our plugin class cannot resolve "bsh.Interpreter". So, we will have to add ดังนั้นเราจะต้องเพิ่ม bean shell library to our ในไฟล์ POM file.ของเรา

Code Block
languagexml
<!-- Change plugin specific dependencies here -->
<dependency>
    <groupId>org.beanshell</groupId>
    <artifactId>bsh</artifactId>
    <version>2.0b4</version>
</dependency>
<!-- End change plugin specific dependencies here -->

d.

...

เตรียมปลั๊กอิน internationalization (i18n)

...

ให้พร้อม

เรากำลังใช้ AppPluginUtilWe are using AppPluginUtil.getMessage method to display เพื่อแสดง i18n value for our สำหรับ getLabel and และ getDescription method . We will have to create a message resource bundle properties file for it. Create ของเรา. เราจะต้องสร้างไฟล์คุณสมบัติทรัพยากรสำหรับมัน Create directory "resources/messages" under ภายใต้"beanshell_hash_variable/src/main" directory. Then, create a ดังนั้น สร้างไฟล์ "BeanShellHashVariable.properties" file in the folder.ในโฟลเดอร์

In our properties file, we will need to add the key we have used.

ในไฟล์คุณสมบัติของเราเราจะต้องเพิ่มคีย์ที่เราใช้ ลงไป

Code Block
languagetext
org.joget.tutorial.BeanShellHashVariable.pluginLabel=Bean Shell Hash Variable
org.joget.tutorial.BeanShellHashVariable.pluginDesc=Using environment variable to execute bean shell script.

e.

...

 ลงทะเบียนปลั๊กอินของคุณไปที่ Felix Framework

We will have to register our plugin class in Activator class to tell the Felix Framework that this is a plugin.เราจะต้องลงทะเบียนคลาสปลั๊กอินของเราในคลาส Activator เพื่อบอก Felix Framework ว่านี่คือปลั๊กอิน


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

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

f.

...

สร้างและทดสอบ

ให้สร้างปลั๊กอินของเรา เมื่อกระบวนการสร้างเร็จสิ้น เราจะพบไฟล์ Let build our plugin. Once the building process is done, we will find that a "beanshell_hash_variable-5.0.0.jar" file is created under สร้างขึ้นภายใน "beanshell_hash_variable/target" directory.

...

 Then, let's upload the plugin jar to Manage Plugins. After uploading the jar file, double check that the plugin is uploaded and activated correctly.

Now, let's test our plugin.

Let assume that we have a HTML menu page in a userview that wants to display the following line to logged in user. Normally, we will use "Welcome #currentUser,username#," to display a welcome message.

Image Removed

But, in this use case there is a problem, which shows "Welcome ," without an username when the user is an anonymous.

Image Removed

Now, change the whole message to our Bean Shell Hash Variable and create an environment variable to put our script.

ตอนนี้ ลองทดสอบปลั๊กอินของเรา

สมมติว่าเรามีหน้าเมนู HTML ใน userview ที่ต้องการแสดงบรรทัดต่อไปนี้เพื่อเข้าสู่ระบบผู้ใช้ โดยปกติเราจะใช้ "ยินดีต้อนรับ # currentUser ชื่อผู้ใช้ #" เพื่อแสดงข้อความต้อนรับ

Image Added

แต่ในกรณีการใช้งานนี้มีปัญหาซึ่งแสดง "ยินดีต้อนรับ" โดยไม่มีชื่อผู้ใช้เมื่อผู้ใช้ไม่ระบุชื่อ

Image Added

ตอนนี้เปลี่ยนข้อความทั้งหมดเป็น Bean Shell Hash Variable ของเราและสร้างตัวแปรสภาพแวดล้อมเพื่อใส่สคริปต์ของเรา

เปลี่ยนChange:

Code Block
Welcome #currentUser.username#,

to the following. We will need to pass the current user's username as one of our parameters and do not forget to escape it as url.ต่อไปนี้ เราจะต้องส่งชื่อผู้ใช้ของผู้ใช้ปัจจุบันเป็นหนึ่งในพารามิเตอร์ของเราและอย่าลืมที่จะหลีกเลี่ยงมันเป็น URL

Code Block
#beanshell.welcome[username={currentUser.username?url}]?html#

Then, we can create an environment variable with จากนั้นเราสามารถสร้างตัวแปรสภาพแวดล้อมด้วย ID "welcome" and use the following script. As we are using getUrlParams method from StringUtil to parse the parameters, all value from parameters are String array.ยินดีต้อนรับ" และใช้สคริปต์ต่อไปนี้ ในขณะที่เรากำลังใช้วิธี getUrlParams จาก StringUtil เพื่อแยกพารามิเตอร์ค่าทั้งหมดจากพารามิเตอร์คืออาร์เรย์สตริง

Code Block
languagejava
//all parameters passed in from Beanshell Hash Variable will converted to String array 
if (username != null && username.length == 1 && !username[0].isEmpty()) {
    return "Welcome " + username[0] + ",";
} else {
    return ""; 
}

Let go back to our HTML menu page to see the result.

When user is logged in, it shows the message correctly.

Image Removed

ให้กลับไปที่หน้าเมนู HTML ของเราเพื่อดูผลลัพธ์

เมื่อผู้ใช้เข้าสู่ระบบจะแสดงข้อความอย่างถูกต้อง

Image Added

เมื่อไม่มีผู้ใช้ที่ล็อกอินข้อความต้อนรับจะไม่ปรากฏขึ้นWhen no user is logged in, the welcome message is not shown.

8.

...

ขั้นต่อไป แชร์หรือขาย

คุณสามารถดาวน์โหลด source code จาก You can download the source code from beanshell_hash_variable.zip.

To download the ready-to-use plugin jar, please find it in หากต้องการดาวน์โหลด jar ปลั๊กอินที่พร้อมใช้งานโปรดค้นหา http://marketplace.joget.org/.