Joget DX 8 Stable Released
The stable release for Joget DX 8 is now available, with a focus on UX and Governance.
Table of Contents |
---|
In this tutorial, we will follow the guideline for developing a plugin to develop our Amazon S3 Datalist Binder plugin. Please also refer to the very first tutorial 如何开发一个Bean Shell Hash Variable插件 for more details steps.
We want to retrieve the files information in Amazon S3.
We can either develop a Datalist Binder 插件 or 用户界面菜单插件 for this purpose. In this tutorial, we will develop a Datalist Binder 插件 to retrieve the files information and populate it using 列表设计器.
Note |
---|
Datalist Binder is not a suitable plugin type for this purpose as the Amazon S3 Client API does not able to get the total number of files and not able to support datalist action like sort, paging and filtering. We are writing this for learning purpose and not encourage for production usage as it will have performance issue. Better way to do this is to develop an Userview Menu which can display the file as a Tree Structure and load additional files when the tree expanded. |
To develop an Amazon S3 Datalist Binder plugin, we will need to provide the input as below:
We will do it a little bit different here as some of the inputs will be putting in a properties file and retrieve it from the properties file when needed. Please refer to how is done in 文件上传表单元素与Amazon S3集成.
A datalist which will list the files in Amazon S3 bucket based on configuration.
We will use the AWS SDK for Java.
We need to always have our Joget Workflow Source Code ready and builded by following this guideline.
The following tutorial is prepared with a Macbook Pro and the Joget Source Code is version 5.0.1. Please refer to the 如何开发插件 article for other platform commands.
Let's say our folder directory is as follows.
Code Block |
---|
- Home
- joget
- plugins
- jw-community
-5.0.1 |
The "plugins" directory is the folder we will create and store all our plugins and the "jw-community" directory is where the Joget Workflow Source code is stored.
Run the following command to create a maven project in "plugins" directory.
Code Block | ||
---|---|---|
| ||
cd joget/plugins/
~/joget/jw-community/5.0.1/wflow-plugin-archetype/create-plugin.sh org.joget amazon_s3_datalist_binder 5.0.1 |
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.
Code Block | ||
---|---|---|
| ||
Define value for property 'version': 1.0-SNAPSHOT: : 5.0.0
[INFO] Using property: package = org.joget
Confirm properties configuration:
groupId: org.joget
artifactId: amazon_s3_datalist_binder
version: 5.0.0
package: org.joget
Y: : y |
We should get a "BUILD SUCCESS" message shown in our terminal and a "amazon_s3_datalist_binder" folder created in the "plugins" folder.
Open the maven project with your favourite IDE. I will be using NetBeans.
Create a "AmazonS3DatalistBinder" class under "org.joget" package. Then, extend the class with org.joget.apps.datalist.model.DataListBinderDefault abstract class. Please refer to Datalist Binder 插件. We will need to implement org.joget.plugin.base.PluginWebSupport interface class as well to provide an Ajax validation in plugin properties page. Please refer to Web Service 插件.
As usual, we have to implement all the abstract methods. We will using AppPluginUtil.getMessage method to support i18n and using constant variable MESSAGE_PATH for message resource bundle directory.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.joget;
import org.joget.apps.app.service.AppPluginUtil;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.datalist.model.DataListBinderDefault;
import org.joget.plugin.base.PluginWebSupport;
public class AmazonS3DatalistBinder extends DataListBinderDefault implements PluginWebSupport {
private final static String MESSAGE_PATH = "message/AmazonS3DatalistBinder";
@Override
public String getName() {
return "Amazon S3 Datalist Binder";
}
@Override
public String getVersion() {
return "5.0.0";
}
@Override
public String getClassName() {
return getClass().getName();
}
@Override
public String getLabel() {
//support i18n
return AppPluginUtil.getMessage("org.joget.AmazonS3DatalistBinder.pluginLabel", getClassName(), MESSAGE_PATH);
}
@Override
public String getDescription() {
//support i18n
return AppPluginUtil.getMessage("org.joget.AmazonS3DatalistBinder.pluginDesc", getClassName(), MESSAGE_PATH);
}
@Override
public String getPropertyOptions() {
return AppUtil.readPluginResource(getClass().getName(), "/properties/amazonS3DatalistBinder.json", null, true, MESSAGE_PATH);
}
} |
Now, we have to create a UI for admin user to provide inputs for our plugin. In getPropertyOptions method, we already specify our 插件属性选项与配置 definition file is located at "/properties/amazonS3DatalistBinder.json". Let us create a directory "resources/properties" under "amazon_s3_datalist_binder/src/main" directory. After creating the directory, create a file named "amazonS3DatalistBinder.json" in the "properties" folder.
In the properties definition options file, we will need to provide options as below. Please note that we can use "@@message.key@@" syntax to support i18n in our properties options. As mentioned previously, some of the properties will put in a properties file, so only 1 property exist in our 插件属性选项与配置 definition file. We will have an AJAX validation to validate the properties file is exist and able to connect to Amazon S3 service.
Code Block | ||
---|---|---|
| ||
[{
title : '@@AmazonS3DatalistBinder.config@@',
properties : [{
name : 'folder',
label : '@@AmazonS3DatalistBinder.folder@@',
type : 'textfield'
}],
validators : [{
type : 'AJAX',
url : '[CONTEXT_PATH]/web/json/app[APP_PATH]/plugin/org.joget.AmazonS3DatalistBinder/service?action=validate'
}]
}] |
Other properties will put in awsS3.properties file. This properties file will need to put in your wflow folder.
After completing the properties option to collect inputs, we can work on the main methods of the plugin which are getColumns, getPrimaryKeyColumnName, getData and getDataTotalRowCount method.
在本教程中,我们将遵循开发插件的 指南 来开发我们的Amazon S3 Datalist Binder插件。 有关更多详细信息步骤,请参阅第一个教程 如何开发一个Bean Shell哈希变量插件。
我们要检索Amazon S3中的文件信息。
我们可以为此开发一个Datalist Binder插件或用户界面菜单插件。在本教程中,我们将开发一个 Datalist Binder插件 来检索文件信息并使用列表设计器填充它。
Note |
---|
Datalist Binder不适合用于此目的的插件类型,因为Amazon S3客户端API无法获取文件的总数,也无法支持排序,分页和过滤等数据列表操作。我们这样写是为了学习的目的,不鼓励生产使用,因为它会有性能问题。 更好的方法是开发一个用户视图菜单,该菜单可以将文件显示为树结构,并在扩展树时加载额外的文件。 |
要开发Amazon S3 Datalist Binder插件,我们需要提供如下输入:
我们将在这里做一些不同的事情,因为一些输入将被放置在属性文件中,并在需要时从属性文件中检索。请参考如何在 文件上传表单元素与Amazon S3集成。
一个数据列表,它将根据配置列出Amazon S3存储桶中的文件。
我们需要始终准备好我们的Joget工作流程源代码,并按照这个指导方针建立起来 。
下面的教程是用Macbook Pro编写的,Joget源代码是5.0.1版本。 其他平台命令请参阅 如何开发插件文章。
假设我们的文件夹目录如下所示。
Code Block |
---|
- Home
- joget
- plugins
- jw-community
-5.0.1 |
“插件”目录是我们将创建和存储我们所有插件的文件夹,“jw-community”目录是Joget Workflow源代码的存储位置。
运行以下命令在“plugins”目录下创建一个maven项目。
Code Block | ||
---|---|---|
| ||
cd joget/plugins/
~/joget/jw-community/5.0.1/wflow-plugin-archetype/create-plugin.sh org.joget amazon_s3_datalist_binder 5.0.1 |
然后,shell脚本会要求我们输入插件的版本号,并在生成maven项目之前要求我们确认。
Code Block | ||
---|---|---|
| ||
Define value for property 'version': 1.0-SNAPSHOT: : 5.0.0
[INFO] Using property: package = org.joget
Confirm properties configuration:
groupId: org.joget
artifactId: amazon_s3_datalist_binder
version: 5.0.0
package: org.joget
Y: : y |
我们应该在终端上显示“BUILD SUCCESS”消息,并在“plugins”文件夹中创建一个“amazon_s3_datalist_binder”文件夹。
用你最喜欢的IDE打开maven项目。我将使用 NetBeans。
在“org.joget”包下创建一个“AmazonS3DatalistBinder”类。然后,使用org.joget.apps.datalist.model.DataListBinderDefault 抽象类来扩展 该类。请参阅 Datalist活页夹插件。我们还需要实现 org.joget.plugin.base.PluginWebSupport 接口类,以在插件属性页面中提供Ajax验证。请参考 Web服务插件。
像往常一样,我们必须执行所有的抽象方法。我们将使用AppPluginUtil.getMessage方法来支持i18n,并使用常量变量MESSAGE_PATH作为消息资源包目录。
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.joget;
import org.joget.apps.app.service.AppPluginUtil;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.datalist.model.DataListBinderDefault;
import org.joget.plugin.base.PluginWebSupport;
public class AmazonS3DatalistBinder extends DataListBinderDefault implements PluginWebSupport {
private final static String MESSAGE_PATH = "message/AmazonS3DatalistBinder";
@Override
public String getName( | ||||||
Code Block | ||||||
| ||||||
protected static AmazonS3 s3; protected static Properties properties; protected static DataListColumn[] columns; protected List<Map<String, Object>> cacheData; protected static String getPropertiesPath() { return SetupManager.getBaseSharedDirectory() + "awsS3.properties"; } public static AmazonS3 getClient() throws Exception { if (s3 == null) { FileInputStream fis = null; try { properties = new Properties(); fis = new FileInputStream(new File(getPropertiesPath())); properties.load(fis); BasicAWSCredentials awsCreds = new BasicAWSCredentials(properties.getProperty("access_key_id"), properties.getProperty("secret_access_key")); s3 = new AmazonS3Client(awsCreds); Region region = Region.getRegion(Regions.fromName(properties.getProperty("region"))); s3.setRegion(region); if (!s3.doesBucketExist(properties.getProperty("bucket"))) { Bucket bucket = s3.createBucket(properties.getProperty("bucket")); if (bucket == null) { throw new RuntimeException(AppPluginUtil.getMessage("AmazonS3DatalistBinder.bucketFilToCreate", AmazonS3DatalistBinder.class.getName(), MESSAGE_PATH)); } } } catch (Exception e) { LogUtil.error(AmazonS3DatalistBinder.class.getName(), e, ""); s3 = null; if (e instanceof FileNotFoundException) { throw new RuntimeException(AppPluginUtil.getMessage("AmazonS3DatalistBinder.configureationFileIsMissing", AmazonS3DatalistBinder.class.getName(), MESSAGE_PATH)); } else { throw e; } } finally { try { if (fis != null) { return "Amazon S3 Datalist Binder"; } @Override fis.closepublic String getVersion(); { return "5.0.0"; } } @Override public String getClassName() { } catchreturn (Exception e) {} getClass().getName(); } }@Override public String getLabel() }{ return s3;//support i18n } protected List<Map<String, Object>> getCacheData() {return AppPluginUtil.getMessage("org.joget.AmazonS3DatalistBinder.pluginLabel", getClassName(), MESSAGE_PATH); } if (cacheData == null) {@Override public String getDescription() { cacheData = new ArrayList<Map<String, Object>>();//support i18n return AppPluginUtil.getMessage("org.joget.AmazonS3DatalistBinder.pluginDesc", try {getClassName(), MESSAGE_PATH); } @Override AmazonS3 clientpublic =String getClientgetPropertyOptions(); { return AppUtil.readPluginResource(getClass().getName(), String prefix = getPropertyString("folder""/properties/amazonS3DatalistBinder.json", null, true, MESSAGE_PATH); if (prefix.isEmpty()) } } |
现在,我们必须为管理员用户创建一个UI,为我们的插件提供输入。在getPropertyOptions方法中,我们已经指定了我们的 插件属性选项和配置 定义文件位于“/properties/amazonS3DatalistBinder.json”。让我们在“amazon_s3_datalist_binder / src / main”目录下创建一个目录“resources / properties”。创建目录后,在“properties”文件夹中创建一个名为“amazonS3DatalistBinder.json”的文件。
在属性定义选项文件中,我们需要提供如下的选项。请注意,我们可以在我们的属性选项中使用“@@ message.key @@”语法来支持i18n。如前所述,某些属性将放入一个属性文件中,因此我们的插件属性选项和配置 定义文件中只存在一个 属性。我们将通过AJAX验证来验证属性文件是否存在并能够连接到Amazon S3服务。
Code Block | ||
---|---|---|
| ||
[{ title : '@@AmazonS3DatalistBinder.config@@', properties prefix = null;: [{ name }: 'folder', label ObjectListing listing = client.listObjects(properties.getProperty("bucket"), prefix); : '@@AmazonS3DatalistBinder.folder@@', type : 'textfield' }], booleanvalidators cont; : [{ type : 'AJAX', do { url : '[CONTEXT_PATH]/web/json/app[APP_PATH]/plugin/org.joget.AmazonS3DatalistBinder/service?action=validate' }] }] |
其他属性将放在 awsS3.properties 文件中。这个属性文件将需要放在您的wflow文件夹中。
完成收集输入的属性选项后,我们可以使用getColumns,getPrimaryKeyColumnName,getData和getDataTotalRowCount方法来处理插件的主要方法。
Code Block | ||
---|---|---|
| ||
protected static AmazonS3 s3; protected static Properties properties; protected static DataListColumn[] columns; protected List<Map<String, contObject>> = falsecacheData; protected static String getPropertiesPath() { return SetupManager.getBaseSharedDirectory() + "awsS3.properties"; } public static AmazonS3 getClient() throws Exception { if (s3 == null) { FileInputStream List<S3ObjectSummary> summaries fis = listing.getObjectSummaries()null; try { for (S3ObjectSummaryproperties s= :new summariesProperties() {; fis = new FileInputStream(new File(getPropertiesPath())); Map<String, Object> obj = new HashMap<String, Object>properties.load(fis); String BasicAWSCredentials keyawsCreds = s.getKey()new BasicAWSCredentials(properties.getProperty("access_key_id"), properties.getProperty("secret_access_key")); s3 = new AmazonS3Client(awsCreds); int pos = key.lastIndexOf("/"); Region region = Region.getRegion(Regions.fromName(properties.getProperty("region"))); objs3.put("key", keysetRegion(region); obj.put("path", (pos > 0)?(key.substring(0, pos-1)):""); if (!s3.doesBucketExist(properties.getProperty("bucket"))) { Bucket bucket obj.put("filename", (pos > 0)?(key.substring(pos+1)):key)= s3.createBucket(properties.getProperty("bucket")); if (bucket == obj.put("owner", s.getOwner().getDisplayName());null) { throw new objRuntimeException(AppPluginUtil.putgetMessage("md5AmazonS3DatalistBinder.bucketFilToCreate", sAmazonS3DatalistBinder.class.getETag(getName(), MESSAGE_PATH)); } obj.put("size", s.getSize()); } } catch (Exception e) { obj.put("storageClass", s.getStorageClass()LogUtil.error(AmazonS3DatalistBinder.class.getName(), e, ""); s3 obj.put("lastModified", s.getLastModified())= null; if (e instanceof FileNotFoundException) { throw new cacheData.add(obj); RuntimeException(AppPluginUtil.getMessage("AmazonS3DatalistBinder.configureationFileIsMissing", AmazonS3DatalistBinder.class.getName(), MESSAGE_PATH)); } else { throw e; } if (listing.isTruncated())} finally { try { cont = true; if (fis != null) { listing = clientfis.listNextBatchOfObjectsclose(listing); } } } catch (Exception e) {} } while (cont);} } return s3; } protected List<Map<String, }Object>> catch getCacheData(Exception e) {} if (cacheData == null) }{ return cacheData; = new } ArrayList<Map<String, Object>>(); public DataListColumn[] getColumns() try { if (columns AmazonS3 client == nullgetClient() {; Collection<DataListColumn>String listprefix = new ArrayList<DataListColumn>(getPropertyString("folder"); list.add(newif DataListColumn("key", AppPluginUtil.getMessage("AmazonS3DatalistBinder.key", getClassName(), MESSAGE_PATH), true));(prefix.isEmpty()) { list.add(new DataListColumn("path", AppPluginUtil.getMessage("AmazonS3DatalistBinder.path", getClassName(), MESSAGE_PATH), true)); prefix = null; } ObjectListing listing = listclient.add(new DataListColumn("filename", AppPluginUtil.getMessage("AmazonS3DatalistBinder.filename", getClassName(), MESSAGE_PATH), true)); listObjects(properties.getProperty("bucket"), prefix); list.add(new DataListColumn("owner", AppPluginUtil.getMessage("AmazonS3DatalistBinder.owner", getClassName(), MESSAGE_PATH), true));boolean cont; do { list.add(new DataListColumn("md5", AppPluginUtil.getMessage("AmazonS3DatalistBinder.md5", getClassName(), MESSAGE_PATH), false)); cont = false; list.add(new DataListColumn("size", AppPluginUtil.getMessage("AmazonS3DatalistBinder.size", getClassName(), MESSAGE_PATH), true)); list.add(new DataListColumn("storageClass", AppPluginUtil.getMessage("AmazonS3DatalistBinder.storageClass", getClassName(), MESSAGE_PATH), true)); List<S3ObjectSummary> summaries = listing.getObjectSummaries(); list.add(new DataListColumn("lastModified", AppPluginUtil.getMessage("AmazonS3DatalistBinder.lastModified", getClassName(), MESSAGE_PATH), true)); for (S3ObjectSummary s : summaries) { Map<String, Object> obj = columnsnew = list.toArray(new DataListColumn[]{}HashMap<String, Object>(); } return columns; String } key public String getPrimaryKeyColumnName() { = s.getKey(); return "key"; } public DataListCollectionint getData(DataList dataList, Map properties, DataListFilterQueryObject[] filterQueryObjects, String sort, Boolean desc, Integer start, Integer rows) { pos = key.lastIndexOf("/"); //TODO: handle filterQueryObjects obj.put("key", key); List list = PagingUtilsobj.sortAndPage(getCacheData()put("path", sort, desc, start, rows(pos > 0)?(key.substring(0, pos-1)):""); DataListCollection data = new DataListCollection(); data.addAll(list obj.put("filename", (pos > 0)?(key.substring(pos+1)):key); return data; }obj.put("owner", s.getOwner().getDisplayName()); public int getDataTotalRowCount(DataList dataList, Map properties, DataListFilterQueryObject[] filterQueryObjects) { //TODO: handle filterQueryObjects obj.put("md5", s.getETag()); return getCacheData().sizeobj.put("size", s.getSize()); } |
In our plugin properties, we have an AJAX validation to test the properties file and the connection to Amazon S3 Client. Let implement the webService method to provide an API for validation.
Code Block | ||
---|---|---|
| ||
public void webService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { obj.put("storageClass", s.getStorageClass()); boolean isAdmin = WorkflowUtilobj.isCurrentUserInRole(WorkflowUserManager.ROLE_ADMINput("lastModified", s.getLastModified()); if (!isAdmin) { responsecacheData.sendError(HttpServletResponse.SC_UNAUTHORIZEDadd(obj); return; } } String action = request.getParameter("action"); if ("validate"listing.equalsisTruncated(action)) { String message cont = ""true; boolean successlisting = trueclient.listNextBatchOfObjects(listing); try { } } while AmazonS3DatalistBinder.getClient(cont); } catch (Exception e) {} } return cacheData; } public LogUtil.error(this.getClassNameDataListColumn[] getColumns(), e, ""); { if (columns == null) { success = false; Collection<DataListColumn> list = new ArrayList<DataListColumn>(); message = StringUtil.escapeString(e.getMessagelist.add(new DataListColumn("key", AppPluginUtil.getMessage("AmazonS3DatalistBinder.key", getClassName(), StringUtil.TYPE_JAVASCIPTMESSAGE_PATH), nulltrue)); list.add(new }DataListColumn("path", AppPluginUtil.getMessage("AmazonS3DatalistBinder.path", getClassName(), MESSAGE_PATH), true)); list.add(new DataListColumn("filename", AppPluginUtil.getMessage("AmazonS3DatalistBinder.filename", try {getClassName(), MESSAGE_PATH), true)); list.add(new DataListColumn("owner", JSONObject jsonObject = new JSONObject(AppPluginUtil.getMessage("AmazonS3DatalistBinder.owner", getClassName(), MESSAGE_PATH), true)); list.add(new jsonObject.accumulate("statusDataListColumn("md5", AppPluginUtil.getMessage("AmazonS3DatalistBinder.md5", (success?"success":"fail"getClassName(), MESSAGE_PATH), false)); JSONArray messageArr = new JSONArray(list.add(new DataListColumn("size", AppPluginUtil.getMessage("AmazonS3DatalistBinder.size", getClassName(), MESSAGE_PATH), true)); list.add(new DataListColumn("storageClass", AppPluginUtil.getMessage("AmazonS3DatalistBinder.storageClass", getClassName(), messageArr.put(messageMESSAGE_PATH), true)); list.add(new jsonObject.put("message", messageArrDataListColumn("lastModified", AppPluginUtil.getMessage("AmazonS3DatalistBinder.lastModified", getClassName(), MESSAGE_PATH), true)); jsonObject.write(response.getWriter() columns = list.toArray(new DataListColumn[]{}); } return columns; } public String getPrimaryKeyColumnName() { return "key"; } catch public DataListCollection getData(ExceptionDataList e) { dataList, Map properties, DataListFilterQueryObject[] filterQueryObjects, String sort, Boolean desc, Integer start, Integer rows) { //ignore TODO: handle filterQueryObjects List } list = PagingUtils.sortAndPage(getCacheData(), } else {sort, desc, start, rows); DataListCollection data = new DataListCollection(); responsedata.setStatus(HttpServletResponse.SC_NO_CONTENTaddAll(list); return data; } public int } |
We need to include "jsp-api" and "aws-java-sdk-s3" libraries in our POM file.
Code Block |
---|
<!-- Change plugin specific dependencies here -->getDataTotalRowCount(DataList dataList, Map properties, DataListFilterQueryObject[] filterQueryObjects) { //TODO: handle filterQueryObjects return getCacheData().size(); } |
在我们的插件属性中,我们有一个AJAX验证来测试属性文件和连接到Amazon S3客户端。让我们实现webService方法来提供一个用于验证的API。
Code Block | ||
---|---|---|
| ||
public void webService(HttpServletRequest request, HttpServletResponse <dependency> response) throws ServletException, IOException { boolean isAdmin = WorkflowUtil.isCurrentUserInRole(WorkflowUserManager.ROLE_ADMIN); if (!isAdmin) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return; } String action = request.getParameter("action"); if ("validate".equals(action)) { String message = ""; boolean success = true; try { AmazonS3DatalistBinder.getClient(); } catch (Exception e) { LogUtil.error(this.getClassName(), e, ""); success = false; message = StringUtil.escapeString(e.getMessage(), StringUtil.TYPE_JAVASCIPT, null); } try { JSONObject jsonObject = new JSONObject(); jsonObject.accumulate("status", (success?"success":"fail")); JSONArray messageArr = new JSONArray(); messageArr.put(message); jsonObject.put("message", messageArr); jsonObject.write(response.getWriter()); } catch (Exception e) { //ignore } } else { response.setStatus(HttpServletResponse.SC_NO_CONTENT); } } |
我们需要在我们的POM文件中包含“jsp-api”和“aws-java-sdk-s3”库。
Code Block |
---|
<!-- Change <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.10.56</version> </dependency> <!-- End change plugin specific dependencies here --> |
We are using i18n message key in getLabel and getDescription method. We will use i18n message key in our properties options definition as well. Then, we will need to create a message resource bundle properties file for our plugin.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.10.56</version>
</dependency>
<!-- End change plugin specific dependencies here --> |
我们在getLabel和getDescription方法中使用i18n消息密钥。我们将在我们的属性选项定义中使用i18n消息密钥。然后,我们将需要为我们的插件创建一个消息资源包属性文件。
在“amazon_s3_datalist_binder / src / main”目录下创建一个目录“resources / message”。然后,在该文件夹中创建一个“AmazonS3DatalistBinder.properties”文件。在属性文件中,添加所有消息密钥及其标签,如下所示。Create a directory, "resources/message", under "amazon_s3_datalist_binder/src/main" directory. Then, create a "AmazonS3DatalistBinder.properties" file in the folder. In the properties file, add all the message keys and its label as below.
Code Block |
---|
org.joget.AmazonS3DatalistBinder.pluginLabel=Amazon S3 Datalist Binder
org.joget.AmazonS3DatalistBinder.pluginDesc=Used to retrieve the available files in Amazon S3.
AmazonS3DatalistBinder.config=Configure Amazon S3 Datalist Binder
AmazonS3DatalistBinder.configureationFileIsMissing=AWS S3 configuration file is missing.
AmazonS3DatalistBinder.bucketFilToCreate=AWS Bucket fail to create.
AmazonS3DatalistBinder.key=Key
AmazonS3DatalistBinder.path=Path
AmazonS3DatalistBinder.filename=File Name
AmazonS3DatalistBinder.owner=Owner
AmazonS3DatalistBinder.md5=MD5 Hash
AmazonS3DatalistBinder.size=Size
AmazonS3DatalistBinder.storageClass=Storage Class
AmazonS3DatalistBinder.lastModified=Last Modified
AmazonS3DatalistBinder.folder=Folder |
.lastModified=Last Modified
AmazonS3DatalistBinder.folder=Folder |
接下来,我们将需要在Activator类(在同一个类包中自动生成)中注册我们的插件类,以告诉Felix框架这是一个插件。Next, we will have to register our plugin class in the Activator class (Auto generated in the same class package) to tell the Felix Framework that this is a plugin.
Code Block | ||
---|---|---|
| ||
public void start(BundleContext context) { registrationList = new ArrayList<ServiceRegistration>(); //Register plugin here registrationList.add(context.registerService(AmazonS3DatalistBinder.class.getName(), new AmazonS3DatalistBinder(), null)); } |
} |
让我们建立我们的插件。构建过程完成后,我们将在“amazonLet's build our plugin. Once the building process is done, we will find a "amazon_s3_datalist_binder -5.0.0.jar" file created under "amazon/ target”目录下找到一个“amazon_s3_datalist_binder/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.
Check the Amazon S3 Datalist Binder plugin is available in 列表设计器.
Select and configure the Amazon S3 Datalist Binder.
Press ok. It the awsS3.properties properties file is missing or invalid. Error message will shown.
Design the datalist.
Check the result.
-5.0.0.jar”文件。
然后,让我们上传插件jar到 管理插件。上传jar文件后,再次检查插件是否正确上传并激活。
检查Amazon S3 Datalist Binder插件可在 列表设计器中找到。
选择并配置Amazon S3 Datalist活页夹。
按下确定。它的awsS3.properties 属性文件丢失或无效。将显示错误消息。
设计数据表。
检查结果。
您可以从You can download the source code from amazon_s3_datalist_binder_src.zip.下载源代码 。