Joget DX 8 Stable Released
The stable release for Joget DX 8 is now available, with a focus on UX and Governance.
在本教程中,我们将遵循开发插件 来开发我们的JDBC Form Load Binder插件的 指导原则。请参考本教程, 如何开发一个Bean Shell Hash变量插件, 以及一个JDBC相关的插件,如何开发一个JDBC选项绑定器 以获得更多的细节步骤。
为了集成的目的,我们想从不同的数据库表中加载我们的表单数据,而不是Joget表单数据表。
Joget Workflow提供了一个名为Form Load Binder Plugin的插件类型 。我们将参考前者开发一个插件来支持JDBC连接和自定义查询来加载表单数据。
为了开发一个JDBC加载绑定器,我们需要JDBC连接设置以及自定义查询来基于主键或外键(对于网格)填充表单数据。
查询还应该支持注入主键(对于Form / Section)或外键(对于Grid元素)的语法,
例:
所有检索到的列自动映射到列名称等于字段ID的字段。
我们可以参考其他可用的 Form Load Binder插件的实现。可以使用AppUtil.getApplicationContext().getBean("setupDataSource")来检索Joget的默认数据源。
我们需要始终准备好Joget Workflow Source Code,并按照这个指导方针建立起来 。
以下教程是使用Macbook Pro和Joget源代码5.0.0版编写的。 其他平台命令请参考 如何开发插件。
假设我们的文件夹目录如下所示。
- Home - joget - plugins - jw-community -5.0.0
“plugins”目录是我们要创建和存储我们所有插件的文件夹,“jw-community”目录是Joget Workflow源代码存储的地方。
运行以下命令在“plugins”目录下创建一个maven项目。
cd joget /plugins/ ~ /joget/jw-community/5 .0.0 /wflow-plugin-archetype/create-plugin .sh org.joget.tutorial jdbc_load_binder 5.0.0 |
然后,shell脚本将要求我们为您的插件输入一个版本,并在生成maven项目之前要求我们确认。
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: jdbc_load_binder version: 5.0.0 package: org.joget.tutorial Y: : y |
我们应该“使成功”,在我们的终端和“插件”文件夹中创建一个“jdbc_load_binder”文件夹中显示的信息。
用你喜欢的IDE打开maven项目。我将使用 NetBeans。
在“org.joget.tutorial”包下创建一个“JdbcLoadBinder”类。然后,使用org.joget.apps.form.model.FormBinder 抽象类来扩展 该类。
为了使它作为一个表单加载活页夹,我们将需要实现 org.joget.apps.form.model.FormLoadBinder 接口。然后,我们需要实现 org.joget.apps.form.model.FormLoadElementBinder接口,使这个插件显示为一个选择,在载入活页夹选择框中实现 org.joget.apps.form.model.FormLoadMultiRowElementBinder接口,将其列在加载网格元素的活页夹选择框。
请参阅 表单加载活页夹插件。
像往常一样,我们必须执行所有的抽象方法。我们将使用AppPluginUtil.getMessage方法来支持i18n,并使用常量变量MESSAGE_PATH作为消息资源包目录。
然后,我们必须为管理员用户提供一个UI来为我们的插件提供输入。在getPropertyOptions方法中,我们已经指定了我们的 插件属性选项和配置 定义文件位于“/properties/jdbcLoadBinder.json”。让我们在“jdbc_load_binder / src / main”目录下创建一个目录“resources / properties”。创建目录后,在“properties”文件夹中创建一个名为“jdbcLoadBinder.json”的文件。
在属性定义选项文件中,我们需要提供如下的选项。请注意,我们可以在我们的属性选项中使用“@@ message.key @@”语法来支持i18n。
[{ title : '@@form.jdbcLoadBinder.config@@' , properties : [{ name : 'jdbcDatasource' , label : '@@form.jdbcLoadBinder.datasource@@' , type : 'selectbox' , options : [{ value : 'custom' , label : '@@form.jdbcLoadBinder.customDatasource@@' },{ value : 'default' , label : '@@form.jdbcLoadBinder.defaultDatasource@@' }], value : 'default' },{ name : 'jdbcDriver' , label : '@@form.jdbcLoadBinder.driver@@' , description : '@@form.jdbcLoadBinder.driver.desc@@' , type : 'textfield' , value : 'com.mysql.jdbc.Driver' , control_field: 'jdbcDatasource' , control_value: 'custom' , control_use_regex: 'false' , required : 'true' },{ name : 'jdbcUrl' , label : '@@form.jdbcLoadBinder.url@@' , type : 'textfield' , control_field: 'jdbcDatasource' , control_value: 'custom' , control_use_regex: 'false' , required : 'true' },{ name : 'jdbcUser' , label : '@@form.jdbcLoadBinder.username@@' , type : 'textfield' , control_field: 'jdbcDatasource' , control_value: 'custom' , control_use_regex: 'false' , value : 'root' , required : 'true' },{ name : 'jdbcPassword' , label : '@@form.jdbcLoadBinder.password@@' , type : 'password' , control_field: 'jdbcDatasource' , control_value: 'custom' , control_use_regex: 'false' , value : '' },{ name : 'sql' , label : '@@form.jdbcLoadBinder.sql@@' , description : '@@form.jdbcLoadBinder.sql.desc@@' , type : 'codeeditor' , mode : 'sql' , required : 'true' }], buttons : [{ name : 'testConnection' , label : '@@form.jdbcLoadBinder.testConnection@@' , ajax_url : '[CONTEXT_PATH]/web/json/app[APP_PATH]/plugin/org.joget.tutorial.JdbcLoadBinder/service?action=testConnection' , fields : [ 'jdbcDriver' , 'jdbcUrl' , 'jdbcUser' , 'jdbcPassword' ], control_field: 'jdbcDatasource' , control_value: 'custom' , control_use_regex: 'false' }] }] |
与JDBC Options Binder相同 ,我们需要添加一个测试连接按钮来进行自定义的JDBC设置。请参阅 如何开发一个JDBC选项绑定器上的 Web服务插件实现。
一旦我们完成了收集输入的属性选项和Web服务来测试连接,我们可以在插件的主要方法,这是加载方法。
public FormRowSet load(Element element, String primaryKey, FormData formData) { FormRowSet rows = new FormRowSet(); rows.setMultiRow( true ); //Check the sql. If require primary key and primary key is null, return empty result. String sql = getPropertyString( "sql" ); if ((primaryKey == null || primaryKey.isEmpty()) && sql.contains( "?" )) { return rows; } Connection con = null ; PreparedStatement pstmt = null ; ResultSet rs = null ; try { DataSource ds = createDataSource(); con = ds.getConnection(); pstmt = con.prepareStatement(sql); //set query parameters if (sql.contains( "?" ) && primaryKey != null && !primaryKey.isEmpty()) { pstmt.setObject( 1 , primaryKey); } rs = pstmt.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); int columnsNumber = rsmd.getColumnCount(); // Set retrieved result to Form Row Set while (rs.next()) { FormRow row = new FormRow(); //get the name of each column as field id for ( int i = 1 ; i <= columnsNumber; i++) { String name = rsmd.getColumnName(i); String value = rs.getString(name); if (FormUtil.PROPERTY_ID.equals(name)) { row.setId(value); } else { row.setProperty(name, (value != null )?value: "" ); } } rows.add(row); } } catch (Exception e) { LogUtil.error(getClassName(), e, "" ); } finally { try { if (rs != null ) { rs.close(); } if (pstmt != null ) { pstmt.close(); } if (con != null ) { con.close(); } } catch (Exception e) { LogUtil.error(getClassName(), e, "" ); } } return rows; } /** * To creates data source based on setting * @return * @throws Exception */ protected DataSource createDataSource() throws Exception { DataSource ds = null ; String datasource = getPropertyString( "jdbcDatasource" ); if ( "default" .equals(datasource)) { // use current datasource ds = (DataSource)AppUtil.getApplicationContext().getBean( "setupDataSource" ); } else { // use custom datasource Properties dsProps = new Properties(); dsProps.put( "driverClassName" , getPropertyString( "jdbcDriver" )); dsProps.put( "url" , getPropertyString( "jdbcUrl" )); dsProps.put( "username" , getPropertyString( "jdbcUser" )); dsProps.put( "password" , getPropertyString( "jdbcPassword" )); ds = BasicDataSourceFactory.createDataSource(dsProps); } return ds; } |
我们的插件使用dbcp,javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse类,所以我们需要将jsp-api和commons-dbcp库添加到我们的POM文件中。
<!-- Change plugin specific dependencies here --> < dependency > < groupId >javax.servlet</ groupId > < artifactId >jsp-api</ artifactId > < version >2.0</ version > </ dependency > < dependency > < groupId >commons-dbcp</ groupId > < artifactId >commons-dbcp</ artifactId > < version >1.3</ version > </ dependency > <!-- End change plugin specific dependencies here --> |
我们在getLabel和getDescription方法中使用i18n消息密钥。我们还在我们的属性选项定义中使用了i18n消息密钥。所以,我们需要为我们的插件创建一个消息资源包属性文件。
在“jdbc_load_binder / src / main”目录下创建目录“resources / messages”。然后,在该文件夹中创建一个“JdbcLoadBinder.properties”文件。在属性文件中,让我们添加所有的消息键和它的标签如下。
org.joget.tutorial.JdbcLoadBinder.pluginLabel=JDBC Binder org.joget.tutorial.JdbcLoadBinder.pluginDesc=Used to load form data using JDBC form.jdbcLoadBinder.config=Configure JDBC Binder form.jdbcLoadBinder.datasource=Datasource form.jdbcLoadBinder.customDatasource=Custom Datasource form.jdbcLoadBinder.defaultDatasource=Default Datasource form.jdbcLoadBinder.driver=Custom JDBC Driver form.jdbcLoadBinder.driver.desc=Eg. com.mysql.jdbc.Driver (MySQL), oracle.jdbc.driver.OracleDriver (Oracle), com.microsoft.sqlserver.jdbc.SQLServerDriver (Microsoft SQL Server) form.jdbcLoadBinder.url=Custom JDBC URL form.jdbcLoadBinder.username=Custom JDBC Username form.jdbcLoadBinder.password=Custom JDBC Password form.jdbcLoadBinder.sql=SQL SELECT Query form.jdbcLoadBinder.sql.desc=Use question mark (?) in your query to represent primary key or foreign key form.jdbcLoadBinder.testConnection=Test Connection form.jdbcLoadBinder.connectionOk=Database connected form.jdbcLoadBinder.connectionFail=Not able to establish connection. |
我们将不得不在Activator类(在同一个类包中自动生成)中注册我们的插件类,以告诉Felix框架这是一个插件。
public void start(BundleContext context) { registrationList = new ArrayList<ServiceRegistration>(); //Register plugin here registrationList.add(context.registerService(JdbcLoadBinder. class .getName(), new JdbcLoadBinder(), null )); } |
让我们建立我们的插件。一旦构建过程完成,我们将在“jdbc_load_binder / target”目录下创建一个“jdbc_load_binder-5.0.0.jar”文件。
然后,让插件jar上传到 管理插件。上传jar文件后,仔细检查插件是否正确上传和激活。
让我们创建一个表单,根据用户名从dir_user表中加载firstName,lastName和email,以测试加载联编程序。
然后,将表单的加载联编程序配置为使用JDBC联编程序和以下查询。
select * from dir_user where username = ? |
让我们创建一个用户视图并拖动一个表单菜单元素来显示我们的表单。然后,发布它并用“id”参数测试我们的表单。
接下来,让我们添加一个网格元素,并使用以下查询进行测试。
再次检查我们的结果。
有用!请记住测试插件的其他功能。
您可以从jdbc_load_binder_src.zip下载源代码 。
要下载现成的插件jar,请在http://marketplace.joget.org/上找到它 。