Orbeon:使用文件系统存储 Form Builder 表单
Orbeon: Using a filesystem for storing Form Builder forms
我们已经开始使用 Orbeon Form Builder 创建表单,但是我们希望能够使用源代码管理 (Git) 来管理我们创建的表单。因此,我们希望将表单存储在文件系统中而不是数据库中(作为旁注,来自表单的数据正在单独处理)。
我已经看到 the/a 方法是为其创建一个(自定义)持久层 (http://doc.orbeon.com/configuration/properties/persistence.html http://doc.orbeon.com/form-runner/api/persistence/index.html)。
有没有一种 documented/available 方法可以轻松做到这一点而无需重新发明轮子 (Orbeon 4.2 Form Builder makes /crud/orbeon/builder/form/form.xhtml request to the custom persistence layer)?
实现此目的的一种方法是利用资源持久层。目前资源持久层只支持读操作,需要improved to also support write operations。这样,您就可以使用 Form Builder 创建、编辑和发布表单。这会将文件写入磁盘,然后您可以分别 add/commit/push 和 Git.
(持久层也可以为您在 Git 上执行这些操作,但我想大多数 Git 用户希望那里有比全自动系统提供的更多控制。 )
为了完成,这是我们已经实现的。
我们正在使用 Git 存储库来存储我们对 Orbeon 安装所做的更改(在新的 Orbeon 安装中,我们将文件夹初始化为 git 存储库,将我们的存储库添加为远程存储库,然后拉入存储库)。
对于开发实例,我们使用默认的 eXist 数据库,因此开发人员必须在首次启动时或其他人对表单进行更改时手动将表单复制到表单生成器中。
当开发人员准备好将更改提交到存储库时,他们可以使用 Node.js 脚本(如下)拉取表单(草稿版本和已发布版本),该脚本使用 CRUD API,获取 XML 并将其存储在资源持久层的正确位置。
在非开发实例中,使用资源持久层而不是 eXist,因此 Orbeon 从文件系统中获取表单 (WEB-INF/resource/forms/<APP_NAME>/<FORM_NAME>/form/form.xhtml
)。我们不使用 Orbeon 存储任何数据(这全部由其他服务处理)。
目前这对我们来说已经足够好了——如果两个人在同一个表单上工作,合并可能会让人望而生畏,因为表单 xml 不是最简单的。 development/non-development 环境中的差异存储在 properties-local-dev.xml
和 properties-local-prod.xml
中(通过更改 运行 模式(在 WEB-INF/web.xml
中选择)
Node.js getForm.js
脚本
#!/usr/bin/env node
var get = require('get');
var mkdirp = require('mkdirp');
var fs = require('fs');
var path = require('path');
if (process.argv.length !== 6) {
console.error("usage: getForm.sh <url> <application> <form> <editFormId>");
console.error("Gets the latest version of a form from Orbeon");
console.error("<editFormId> is the id of the latest version of the form in form ");
console.error(" eg, the last part of the edit form url");
console.error(" http://localhost/orbeon/fr/orbeon/builder/edit/<editFormId>");
console.error("eg: getForm.sh http://127.0.0.1:8080/orbeon APP FORM 72e300fe7d8f2d2604f31b690760865a23dbeaed");
return 1;
}
// Check for WEB-INF folder so we know we are running from the right folder
try {
fs.accessSync('WEB-INF', fs.R_OK);
} catch (err) {
console.error('Problem finding WEB-INF folder. Need to run from base of '
+ 'Orbeon folder', err.stack);
return 2;
}
// Create folders if required
var publishedFolder = path.join('WEB-INF/resources/forms/', process.argv[3],
process.argv[4], 'form');
var draftFolder = path.join('src/forms/', process.argv[3]);
var folders = [publishedFolder, draftFolder];
var f;
for (f in folders) {
try {
fs.accessSync(folders[f], fs.R_OK);
} catch (err) {
if (err.code === 'ENOENT') {
// Try creating the folder
try {
mkdirp.sync(folders[f]);
} catch (err) {
console.error("Error creating folder", folders[f], err.stack);
return 3;
}
} else {
console.error("Error checking access permissions to folder", folders[f], err.stack);
return 4;
}
}
}
try {
// Add http to url if it doesn't already contain it
if (!process.argv[2].match(/^https?:\/\//)) {
process.argv[2] = 'http://' + process.argv[2];
}
var publishedURL = process.argv[2] + '/fr/service/persistence/'
+ 'crud/' + process.argv[3] + '/' + process.argv[4] + '/form/form.xhtml';
var publishedFile = path.join(publishedFolder, 'form.xhtml');
console.log('Getting the latest published version of the form from '
+ publishedURL + ' and saving it to', publishedFile);
var published = get(publishedURL);
// Write to file
published.toDisk(publishedFile, function(err, filename) {
if (err) {
console.error('Error storing the latest published version of the form',
publishedURL, ' > ', publishedFile, err.stack);
}
return 5;
});
} catch (err) {
console.error('Error getting the latest published version of the form',
publishedURL, ' > ', publishedFile, err.stack);
return 6;
}
try {
var draftURL = process.argv[2] + '/fr/service/persistence/crud/'
+ 'orbeon/builder/data/' + process.argv[5] + '/data.xml';
console.log(draftURL);
var draftFile = path.join(draftFolder,
process.argv[4] + '.xhtml');
console.log('Getting the latest draft version of the form from '
+ draftURL + ' and saving it to', draftFile);
var draft = get(draftURL);
// Write to file
draft.toDisk(draftFile, function(err, filename) {
if (err) {
console.error('Error storing the latest draft version of the form',
draftURL, ' > ', draftFile, err.stack);
}
return 7;
});
} catch (err) {
console.error('Error getting the latest draft version of the form',
draftURL, ' > ', draftFile, err.stack);
return 8;
}
启用对 CRUD 的访问 API
<property
as="xs:string"
processor-name="oxf:page-flow"
name="page-public-methods"
value="GET HEAD POST PUT DELETE"/>
<property
as="xs:string"
processor-name="oxf:page-flow"
name="service-public-methods"
value="GET HEAD POST PUT DELETE"/>
我们已经开始使用 Orbeon Form Builder 创建表单,但是我们希望能够使用源代码管理 (Git) 来管理我们创建的表单。因此,我们希望将表单存储在文件系统中而不是数据库中(作为旁注,来自表单的数据正在单独处理)。
我已经看到 the/a 方法是为其创建一个(自定义)持久层 (http://doc.orbeon.com/configuration/properties/persistence.html http://doc.orbeon.com/form-runner/api/persistence/index.html)。
有没有一种 documented/available 方法可以轻松做到这一点而无需重新发明轮子 (Orbeon 4.2 Form Builder makes /crud/orbeon/builder/form/form.xhtml request to the custom persistence layer)?
实现此目的的一种方法是利用资源持久层。目前资源持久层只支持读操作,需要improved to also support write operations。这样,您就可以使用 Form Builder 创建、编辑和发布表单。这会将文件写入磁盘,然后您可以分别 add/commit/push 和 Git.
(持久层也可以为您在 Git 上执行这些操作,但我想大多数 Git 用户希望那里有比全自动系统提供的更多控制。 )
为了完成,这是我们已经实现的。
我们正在使用 Git 存储库来存储我们对 Orbeon 安装所做的更改(在新的 Orbeon 安装中,我们将文件夹初始化为 git 存储库,将我们的存储库添加为远程存储库,然后拉入存储库)。
对于开发实例,我们使用默认的 eXist 数据库,因此开发人员必须在首次启动时或其他人对表单进行更改时手动将表单复制到表单生成器中。
当开发人员准备好将更改提交到存储库时,他们可以使用 Node.js 脚本(如下)拉取表单(草稿版本和已发布版本),该脚本使用 CRUD API,获取 XML 并将其存储在资源持久层的正确位置。
在非开发实例中,使用资源持久层而不是 eXist,因此 Orbeon 从文件系统中获取表单 (WEB-INF/resource/forms/<APP_NAME>/<FORM_NAME>/form/form.xhtml
)。我们不使用 Orbeon 存储任何数据(这全部由其他服务处理)。
目前这对我们来说已经足够好了——如果两个人在同一个表单上工作,合并可能会让人望而生畏,因为表单 xml 不是最简单的。 development/non-development 环境中的差异存储在 properties-local-dev.xml
和 properties-local-prod.xml
中(通过更改 运行 模式(在 WEB-INF/web.xml
中选择)
Node.js getForm.js
脚本
#!/usr/bin/env node
var get = require('get');
var mkdirp = require('mkdirp');
var fs = require('fs');
var path = require('path');
if (process.argv.length !== 6) {
console.error("usage: getForm.sh <url> <application> <form> <editFormId>");
console.error("Gets the latest version of a form from Orbeon");
console.error("<editFormId> is the id of the latest version of the form in form ");
console.error(" eg, the last part of the edit form url");
console.error(" http://localhost/orbeon/fr/orbeon/builder/edit/<editFormId>");
console.error("eg: getForm.sh http://127.0.0.1:8080/orbeon APP FORM 72e300fe7d8f2d2604f31b690760865a23dbeaed");
return 1;
}
// Check for WEB-INF folder so we know we are running from the right folder
try {
fs.accessSync('WEB-INF', fs.R_OK);
} catch (err) {
console.error('Problem finding WEB-INF folder. Need to run from base of '
+ 'Orbeon folder', err.stack);
return 2;
}
// Create folders if required
var publishedFolder = path.join('WEB-INF/resources/forms/', process.argv[3],
process.argv[4], 'form');
var draftFolder = path.join('src/forms/', process.argv[3]);
var folders = [publishedFolder, draftFolder];
var f;
for (f in folders) {
try {
fs.accessSync(folders[f], fs.R_OK);
} catch (err) {
if (err.code === 'ENOENT') {
// Try creating the folder
try {
mkdirp.sync(folders[f]);
} catch (err) {
console.error("Error creating folder", folders[f], err.stack);
return 3;
}
} else {
console.error("Error checking access permissions to folder", folders[f], err.stack);
return 4;
}
}
}
try {
// Add http to url if it doesn't already contain it
if (!process.argv[2].match(/^https?:\/\//)) {
process.argv[2] = 'http://' + process.argv[2];
}
var publishedURL = process.argv[2] + '/fr/service/persistence/'
+ 'crud/' + process.argv[3] + '/' + process.argv[4] + '/form/form.xhtml';
var publishedFile = path.join(publishedFolder, 'form.xhtml');
console.log('Getting the latest published version of the form from '
+ publishedURL + ' and saving it to', publishedFile);
var published = get(publishedURL);
// Write to file
published.toDisk(publishedFile, function(err, filename) {
if (err) {
console.error('Error storing the latest published version of the form',
publishedURL, ' > ', publishedFile, err.stack);
}
return 5;
});
} catch (err) {
console.error('Error getting the latest published version of the form',
publishedURL, ' > ', publishedFile, err.stack);
return 6;
}
try {
var draftURL = process.argv[2] + '/fr/service/persistence/crud/'
+ 'orbeon/builder/data/' + process.argv[5] + '/data.xml';
console.log(draftURL);
var draftFile = path.join(draftFolder,
process.argv[4] + '.xhtml');
console.log('Getting the latest draft version of the form from '
+ draftURL + ' and saving it to', draftFile);
var draft = get(draftURL);
// Write to file
draft.toDisk(draftFile, function(err, filename) {
if (err) {
console.error('Error storing the latest draft version of the form',
draftURL, ' > ', draftFile, err.stack);
}
return 7;
});
} catch (err) {
console.error('Error getting the latest draft version of the form',
draftURL, ' > ', draftFile, err.stack);
return 8;
}
启用对 CRUD 的访问 API
<property
as="xs:string"
processor-name="oxf:page-flow"
name="page-public-methods"
value="GET HEAD POST PUT DELETE"/>
<property
as="xs:string"
processor-name="oxf:page-flow"
name="service-public-methods"
value="GET HEAD POST PUT DELETE"/>