Tag Archive beanshell

JoGet: Bean Shell Create Json

วิธีดีที่สุดในการให้ข้อมูลจำนวนมากให้ javascript คือรูปแบบ json ไม่เว้นแม้แต่ใน JoGet เพราะถึงแม้จะสามารถดึงข้อมูลจาก input หรือ grid ได้ แต่มันจะถูกบันทึกลง database ไปด้วยแถมดูรก

วิธีที่ดีอีกวิธีคือให้ beanshell ใน section ดึงข้อมูลจาก query แล้วแสดงออกมาใน input ตัวเดียว

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.form.model.Element;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.model.FormRow;
import org.joget.apps.form.model.FormRowSet;
import org.joget.apps.form.service.FormUtil;
import org.joget.commons.util.LogUtil;
import org.json.simple.JSONObject;

public FormRowSet load(Element element, String username, FormData formData) {

 FormRowSet rows = new FormRowSet();

 Connection con = null;
 try {
  DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
  con = ds.getConnection();

  sql = "SELECT appId, appVersion, name FROM jwdb.app_app WHERE published = 1;";
  //LogUtil.info("Bean Shell Create Json", "sql = " + sql);

  if (!con.isClosed()) {
   PreparedStatement stmt = con.prepareStatement(sql);
   ResultSet rs = stmt.executeQuery();

   /* create json */
   JSONObject json = new JSONObject();
   while (rs.next()) {
    JSONObject item = new JSONObject();

    item.put("appVersion", rs.getObject("appVersion"));
    item.put("name", rs.getObject("name"));

    json.put(rs.getObject("appId"), item);
   }

   /* add json to input */
   FormRow row = new FormRow();
   rows.add(row);
   row.put("json", json.toString());
  }

 } catch (Exception e) {
  LogUtil.error(getClassName(), e, "Bean Shell Create Json");
 } finally {
  try {
   if (con != null) {
    con.close();
   }
  } catch (SQLException e) {}
 }

 return rows;
}

return load(element, primaryKey, formData);

ตัวอย่างฟอร์ม

{
    "className": "org.joget.apps.form.model.Form",
    "properties": {
        "noPermissionMessage": "",
        "loadBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "name": "Bean Shell Create Json",
        "description": "",
        "postProcessorRunOn": "both",
        "permission": {
            "className": "",
            "properties": {}
        },
        "id": "BeanShellCreateJson",
        "postProcessor": {
            "className": "",
            "properties": {}
        },
        "storeBinder": {
            "className": "org.joget.apps.form.lib.WorkflowFormBinder",
            "properties": {}
        },
        "tableName": "prototypes"
    },
    "elements": [
        {
            "elements": [
                {
                    "elements": [
                        {
                            "className": "org.joget.apps.form.lib.TextArea",
                            "properties": {
                                "readonly": "",
                                "validator": {
                                    "className": "",
                                    "properties": {}
                                },
                                "workflowVariable": "",
                                "id": "json",
                                "label": "JSON",
                                "placeholder": "",
                                "rows": "10",
                                "value": "",
                                "cols": "100",
                                "readonlyLabel": ""
                            }
                        }
                    ],
                    "className": "org.joget.apps.form.model.Column",
                    "properties": {
                        "width": "100%"
                    }
                }
            ],
            "className": "org.joget.apps.form.model.Section",
            "properties": {
                "readonly": "",
                "loadBinder": {
                    "className": "org.joget.apps.form.lib.BeanShellFormBinder",
                    "properties": {
                        "useAjax": "",
                        "cacheIdlePause": "120",
                        "cacheInterval": "",
                        "script": "import java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.joget.apps.app.service.AppUtil;\nimport org.joget.apps.form.model.Element;\nimport org.joget.apps.form.model.FormData;\nimport org.joget.apps.form.model.FormRow;\nimport org.joget.apps.form.model.FormRowSet;\nimport org.joget.apps.form.service.FormUtil;\nimport org.joget.commons.util.LogUtil;\nimport org.json.simple.JSONObject;\n\npublic FormRowSet load(Element element, String username, FormData formData) {\n\n FormRowSet rows = new FormRowSet();\n\n Connection con = null;\n try {\n  DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean(\"setupDataSource\");\n  con = ds.getConnection();\n\n  sql = \"SELECT appId, appVersion, name FROM jwdb.app_app WHERE published = 1;\";\n  //LogUtil.info(\"Bean Shell Create Json\", \"sql = \" + sql);\n\n  if (!con.isClosed()) {\n   PreparedStatement stmt = con.prepareStatement(sql);\n   ResultSet rs = stmt.executeQuery();\n\n   /* create json */\n   JSONObject json = new JSONObject();\n   while (rs.next()) {\n    JSONObject item = new JSONObject();\n\n    item.put(\"appVersion\", rs.getObject(\"appVersion\"));\n    item.put(\"name\", rs.getObject(\"name\"));\n\n    json.put(rs.getObject(\"appId\"), item);\n   }\n\n   /* add json to input */\n   FormRow row = new FormRow();\n   rows.add(row);\n   row.put(\"json\", json.toString());\n  }\n\n } catch (Exception e) {\n  LogUtil.error(getClassName(), e, \"Bean Shell Create Json\");\n } finally {\n  try {\n   if (con != null) {\n    con.close();\n   }\n  } catch (SQLException e) {}\n }\n\n return rows;\n}\n\nreturn load(element, primaryKey, formData);"
                    }
                },
                "permissionReadonly": "",
                "permission": {
                    "className": "",
                    "properties": {}
                },
                "comment": "",
                "id": "section1",
                "label": "Bean Shell Create Json",
                "storeBinder": {
                    "className": "",
                    "properties": {}
                },
                "readonlyLabel": ""
            }
        }
    ]
}

JoGet: Save PDF From Jasper Report

ตัวอย่างการ save pdf file ที่สร้างมาจาก JasperReports ก่อนที่จะส่งให้ user ทางอีเมล์ เพื่อที่ฝ่ายที่เกี่ยวข้องจะได้นำไฟล์มาตรวจสอบความถูกต้องในภายหลังว่ารีพอร์ตที่เป็น pdf ไฟล์ที่ส่งไปมีเนื่้อหายังไงจากไฟล์ที่บันทึกเอาไว้

เราสามารถทำได้โดยใช้ plugin Bean Shell Tool ตามตัวอย่าง

import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import org.joget.apps.app.service.AppUtil;

public Object execute() {

/* get parameters from outside activity tools box */
String id = "#variable.id#";

String documentRoot = "C:\\Joget-v5-Enterprise\\apache-tomcat-8.0.20\\webapps\\jw\\";

/* connection to default datasource */
DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
con = ds.getConnection();

/* load JasperReports template */
String sourceFileName = documentRoot + "assets\\JasperReports\\app.jasper";

Map parameters = new HashMap();

/* send parameters to jasper report */
parameters.put("id", id);

/* genrate pdf file and save to local directory */
printFileName = JasperFillManager.fillReportToFile(sourceFileName, parameters, con);
if (printFileName != null) {
JasperExportManager.exportReportToPdfFile(printFileName, documentRoot + "datas\\policies\\" + id + ".pdf");
}

return null;
}

//call execute method
return execute();

อธิบายการทำงาน จะเรียกใช้ beanshell เข้าไปเรียก class เดียวกับที่ joget ใช้ จึงมั่นใจได้ว่ารีพอร์ตที่ออกมาจะเหมือนกับที่ joget ใช้จริงๆ โดยจะอ่านไฟล์ .jasper มาจาก “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\assets\JasperReports\app.jasper” จากนั้นจะสรุปออกมาเป็นไฟล์ .jrprint เอาไว้ใน “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\assets\JasperReports\” เหมือนกัน แต่ชื่อไฟล์อาจจะต่างกันโดยจะตั้งตาม atrbut name ที่อยู่ใน tag jasperReport และสร้างไฟล์ pdf เก็บไว้ที่ “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\datas\policies” ตาม ที่กำหนดไว้ที่ใน JasperExportManager.exportReportToPdfFile

เพราะว่าไฟล์ใน “C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw” สามารถเรียกดูได้จาก url จึงควรระวังเรื่อง Information leakage เอาไว้ด้วย

joget: Bean Shell Form Binder

ตัวอย่างการใช้ bean shell ดึงค่าจาก database มาแสดง

สร้าง table app_fd_prototype โดยใช้

--
-- Table structure for table `app_fd_prototype`
--

CREATE TABLE `app_fd_prototype` (
`id` varchar(255) NOT NULL,
`dateCreated` datetime DEFAULT NULL,
`dateModified` datetime DEFAULT NULL,
`c_Checkbox` longtext NOT NULL,
`c_DatePicker` longtext NOT NULL,
`c_FileUpload` longtext NOT NULL,
`c_HiddenField` longtext NOT NULL,
`c_PasswordField` longtext NOT NULL,
`c_Radio` longtext NOT NULL,
`c_SelectBox` longtext NOT NULL,
`c_TextArea` longtext NOT NULL,
`c_TextField` longtext NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `app_fd_prototype`
--

INSERT INTO `app_fd_prototype` (`id`, `dateCreated`, `dateModified`, `c_Checkbox`, `c_DatePicker`, `c_FileUpload`, `c_HiddenField`, `c_PasswordField`, `c_Radio`, `c_SelectBox`, `c_TextArea`, `c_TextField`) VALUES
('399895e8-ac15e1b1-2ddac962-1ca1ea8b', '2017-10-02 00:00:00', '2017-10-27 00:00:00', 'permanent', '10/09/2017', '04a972cda3440360b437a67d3a0dbb9d.jpg ', 'HiddenField	', 'PasswordField', 'male', 'programmer', 'โปรแกรมเมอร์ธรรมดาที่อยากเขียนสิ่งที่ไม่ธรรมดา ลูกค้า ผู้ชมเข้ามาดูต้องบอกว่า ดี แจ๋ง ง่าย แต่คนเขียนต้องไม่ลำบากกับชีวิต', 'pitt phunsanit');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `app_fd_prototype`
--
ALTER TABLE `app_fd_prototype`
ADD PRIMARY KEY (`id`);
COMMIT;

สร้างฟอร์มโดยใช้

{"className":"org.joget.apps.form.model.Form","properties":{"id":"BeanShellFormBinder","loadBinder":{"className":"org.joget.apps.form.lib.BeanShellFormBinder","properties":{"useAjax":"","script":"import java.sql.Connection;\r\nimport java.sql.PreparedStatement;\r\nimport java.sql.ResultSet;\r\nimport java.sql.SQLException;\r\nimport javax.sql.DataSource;\r\nimport org.joget.apps.app.service.AppUtil;\r\nimport org.joget.apps.form.model.Element;\r\nimport org.joget.apps.form.model.FormData;\r\nimport org.joget.apps.form.model.FormRow;\r\nimport org.joget.apps.form.model.FormRowSet;\r\nimport org.joget.commons.util.LogUtil;\r\n\r\npublic FormRowSet load(Element element, String primaryKey, FormData formData) {\r\n    FormRowSet rows = new FormRowSet();\r\n    if (primaryKey != null && !primaryKey.isEmpty()) {\r\n        Connection con = null;\r\n        try {\r\n            \/*retrieve connection from the default datasource*\/\r\n            DataSource ds = (DataSource)AppUtil.getApplicationContext().getBean(\"setupDataSource\");\r\n            con = ds.getConnection();\r\n\r\n            \/*execute SQL query*\/\r\n            if(!con.isClosed()) {\r\n                String sql = \"SELECT c_Checkbox, c_DatePicker, c_FileUpload, c_HiddenField, c_PasswordField, c_Radio, c_SelectBox, c_TextArea, c_TextField FROM app_fd_prototype WHERE id = ?\";\r\n                PreparedStatement stmt = con.prepareStatement(sql);\r\n                stmt.setObject(1, primaryKey);\r\n\r\n                ResultSet rs = stmt.executeQuery();\r\n                while (rs.next()) {\r\n                    FormRow row = new FormRow();\r\n \r\n                System.out.println(rs.getObject(\"c_Checkbox\"));\r\n\r\n                    row.put(\"Checkbox\", (rs.getObject(\"c_Checkbox\") != null) ? rs.getObject(\"c_Checkbox\").toString() : \"\");\r\n                    row.put(\"DatePicker\", (rs.getObject(\"c_DatePicker\") != null) ? rs.getObject(\"c_DatePicker\").toString() : \"\");\r\n                    row.put(\"FileUpload\", (rs.getObject(\"c_FileUpload\") != null) ? rs.getObject(\"c_FileUpload\").toString() : \"\");\r\n                    row.put(\"HiddenField\", (rs.getObject(\"c_HiddenField\") != null) ? rs.getObject(\"c_HiddenField\").toString() : \"\");\r\n                    row.put(\"PasswordField\", (rs.getObject(\"c_PasswordField\") != null) ? rs.getObject(\"c_PasswordField\").toString() : \"\");\r\n                    row.put(\"Radio\", (rs.getObject(\"c_Radio\") != null) ? rs.getObject(\"c_Radio\").toString() : \"\");\r\n                    row.put(\"SelectBox\", (rs.getObject(\"c_SelectBox\") != null) ? rs.getObject(\"c_SelectBox\").toString() : \"\");\r\n                    row.put(\"TextArea\", (rs.getObject(\"c_TextArea\") != null) ? rs.getObject(\"c_TextArea\").toString() : \"\");\r\n                    row.put(\"TextField\", (rs.getObject(\"c_TextField\") != null) ? rs.getObject(\"c_TextField\").toString() : \"\");\r\n \r\n                    rows.add(row);\r\n                    break;\r\n                }\r\n            }\r\n        } catch(Exception e) {\r\n            LogUtil.error(\"Sample app - Form 1\", e, \"Error loading user data in load binder\");\r\n        } finally {\r\n            \/*always close the connection after used*\/\r\n            try {\r\n                if(con != null) {\r\n                    con.close();\r\n                }\r\n            } catch(SQLException e) {\/*ignored*\/}\r\n        }\r\n    }\r\n    return rows;\r\n}\r\n \r\n\/*call load method with injected variable*\/\r\nreturn load(element, primaryKey, formData);"}},"description":"","tableName":"prototype","postProcessorRunOn":"both","name":"Bean Shell Form Binder","postProcessor":{"className":"","properties":{}},"storeBinder":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"noPermissionMessage":""},"elements":[{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.CheckBox","properties":{"id":"Checkbox","workflowVariable":"","readonlyLabel":"","optionsBinder":{"className":"","properties":{}},"validator":{"className":"","properties":{}},"controlField":"","value":"","label":"Checkbox","readonly":"","options":[{"grouping":"","value":"freelance","label":"freelance"},{"grouping":"","value":"permanent","label":"permanent"}]}},{"className":"org.joget.apps.form.lib.DatePicker","properties":{"readonlyLabel":"","validator":{"className":"","properties":{}},"endDateFieldId":"","label":"Date Picker","format":"","startDateFieldId":"","allowManual":"","id":"DatePicker","workflowVariable":"","value":"","dataFormat":"","readonly":"","yearRange":"c-10:c+10","currentDateAs":""}},{"className":"org.joget.apps.form.lib.FileUpload","properties":{"id":"FileUpload","fileType":"","validator":{"className":"","properties":{}},"label":"FileUpload","attachment":"","readonly":"","multiple":"","permissionType":"","fileTypeMsg":"Invalid file type","maxSizeMsg":"File size limit exceeded","maxSize":"","size":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"HiddenField","workflowVariable":"","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.PasswordField","properties":{"id":"TextField","readonlyLabel":"","maxlength":"","validator":{"className":"","properties":{}},"value":"","label":"TextField","readonly":"","size":""}},{"className":"org.joget.apps.form.lib.Radio","properties":{"id":"Radio","workflowVariable":"","readonlyLabel":"","optionsBinder":{"className":"","properties":{}},"validator":{"className":"","properties":{}},"controlField":"","value":"","label":"Radio","readonly":"","options":[{"grouping":"","value":
"female","label":"female"},{"grouping":"","value":"male","label":"male"}]}},{"className":"org.joget.apps.form.lib.SelectBox","properties":{"id":"SelectBox","readonlyLabel":"","workflowVariable":"","optionsBinder":{"className":"","properties":{}},"validator":{"className":"","properties":{}},"value":"","controlField":"","label":"SelectBox","multiple":"","readonly":"","options":[{"grouping":"","value":"programmer","label":"programmer"},{"grouping":"","value":"tester","label":"tester"}],"size":""}},{"className":"org.joget.apps.form.lib.TextArea","properties":{"id":"TextArea","cols":"20","readonlyLabel":"","workflowVariable":"","validator":{"className":"","properties":{}},"value":"","label":"TextArea","readonly":"","rows":"5"}},{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"TextField","readonlyLabel":"","workflowVariable":"","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"TextField","readonly":"","size":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"section1","label":"Section"}}]}

ใส่ Edit Form > Advanced > Configure Bean Shell Form Binder

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.form.model.Element;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.model.FormRow;
import org.joget.apps.form.model.FormRowSet;
import org.joget.commons.util.LogUtil;

public FormRowSet load(Element element, String primaryKey, FormData formData) {
FormRowSet rows = new FormRowSet();
if (primaryKey != null && !primaryKey.isEmpty()) {
Connection con = null;
try {
/*retrieve connection from the default datasource*/
DataSource ds = (DataSource)AppUtil.getApplicationContext().getBean("setupDataSource");
con = ds.getConnection();

/*execute SQL query*/
if(!con.isClosed()) {
String sql = "SELECT c_Checkbox, c_DatePicker, c_FileUpload, c_HiddenField, c_PasswordField, c_Radio, c_SelectBox, c_TextArea, c_TextField FROM app_fd_prototype WHERE id = ?";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setObject(1, primaryKey);

ResultSet rs = stmt.executeQuery();
while (rs.next()) {
FormRow row = new FormRow();

System.out.println(rs.getObject("c_Checkbox"));

row.put("Checkbox", (rs.getObject("c_Checkbox") != null) ? rs.getObject("c_Checkbox").toString() : "");
row.put("DatePicker", (rs.getObject("c_DatePicker") != null) ? rs.getObject("c_DatePicker").toString() : "");
row.put("FileUpload", (rs.getObject("c_FileUpload") != null) ? rs.getObject("c_FileUpload").toString() : "");
row.put("HiddenField", (rs.getObject("c_HiddenField") != null) ? rs.getObject("c_HiddenField").toString() : "");
row.put("PasswordField", (rs.getObject("c_PasswordField") != null) ? rs.getObject("c_PasswordField").toString() : "");
row.put("Radio", (rs.getObject("c_Radio") != null) ? rs.getObject("c_Radio").toString() : "");
row.put("SelectBox", (rs.getObject("c_SelectBox") != null) ? rs.getObject("c_SelectBox").toString() : "");
row.put("TextArea", (rs.getObject("c_TextArea") != null) ? rs.getObject("c_TextArea").toString() : "");
row.put("TextField", (rs.getObject("c_TextField") != null) ? rs.getObject("c_TextField").toString() : "");

rows.add(row);
break;
}
}
} catch(Exception e) {
LogUtil.error("Sample app - Form 1", e, "Error loading user data in load binder");
} finally {
/*always close the connection after used*/
try {
if(con != null) {
con.close();
}
} catch(SQLException e) {/*ignored*/}
}
}
return rows;
}

/*call load method with injected variable*/
return load(element, primaryKey, formData);

Injected Variables:

element
Element that this binder is tie to. (org.joget.apps.form.model.Element)
primaryKey
The primary key provided by the element to load data. (java.lang.String)
formData
The data holder of the whole form. (org.joget.apps.form.model.FormData)