Tag Archive process

SQL Server: Kill process ของข้าให้หมด

มีแก้งานที่เขียน query ได้โหดยูเครนมาก (รัสเซียได้พิสูจน์ให้เห็นแล้วว่ากาก) ใช้ cpu สูงมาก ใช้ ram เกือบหมดเม็ค แล้วมีคนใช้งานอยู่พร้อม ๆ กัน T-T เลยหา script มาจัดการดีด connection ที่ใช้อยู่ในเครื่องตัวเองทิ้งยกเว้นที่ใช้อยู่ใน sql server management studio (ssms) และโปรแกรม app ที่กำลังเขียนอยู่

DECLARE @SqlCmd VARCHAR(1000)
  
	,@HostName VARCHAR(100)-- Set the hostname name from which to kill the connections

  
	--SET @HostName = 'Pitt_P'

SET @HostName = HOST_NAME()

SET @SqlCmd = ''  SELECT @Sqlcmd = @SqlCmd + CHAR(13) + CHAR(10) + 'KILL ' + convert(CHAR(10), spid) + ' '
 
FROM master.dbo.sysprocesses
 
WHERE hostname = @HostName
 
	AND DBID <> 0
 
	AND spid <> @@spid PRINT @sqlcmd EXEC(@Sqlcmd)
 
GO

แก้จากต้นแบบ Kill all processes associated with a hostname โดยดึงข้อมูล HOST HOST_NAME แทนที่จะใส่ชื่อเครื่องตัวเองไป

joGet: Pending Process Activity and Assignees

ต้องการสร้าง List ใน joGet เพิ่อที่จะได้ดูสถานะและเข้าไปดู form ใน process ตามขั้นตอนต่างๆ ใน workflow

ทำได้โดยใช้ความรู้ 2 เรื่องคือ

การใช้ query เพิ่อดู process activity

process ที่กำลังอยู่ระหว่างสถานะต่างๆ จะถูกบันทึกลงใน database สามารถ query มาดูได้โดยใช้ตัวอย่าง เช่น

SELECT
a.*,
sact.Name AS activityName,
GROUP_CONCAT(DISTINCT sass.ResourceId
SEPARATOR ', ') AS assignee
FROM
app_fd_hr_expense_claim a
JOIN
SHKActivities sact ON a.id = sact.ProcessId
JOIN
SHKActivityStates ssta ON ssta.oid = sact.State
INNER JOIN
SHKAssignmentsTable sass ON sact.Id = sass.ActivityId
WHERE
ssta.KeyValue = 'open.not_running.not_started'
GROUP BY a.id

ตามตัวอย่างใน List Pending Activity and Assignees อย่าลืมเปลี่ยนตาราง a เป็นตารางที่ใช้ใน process จริงๆ

การใช้ link ไปยังฟอร์มตาม activity
ลิงค์ของ joget จะอยู่ในรูปแบบ /jw/web/userview/ {app id} / {userview id} /_/ {process_id} ?_action=assignmentView

ตัวอย่าง list ที่เสร็จแล้ว

{"id":"activity_and_assignees","name":"Activity And Assignees","pageSize":"0","order":"","orderBy":"","showPageSizeSelector":"true","pageSizeSelectorOptions":"10,20,30,40,50,100","buttonPosition":"bottomLeft","checkboxPosition":"left","useSession":"false","hidePageSize":"true","description":"","rowActions":[{"name":"Data List Hyperlink Action","className":"org.joget.apps.datalist.lib.HyperlinkDataListAction","label":"Hyperlink","type":"text","id":"rowAction_0","properties":{"href":"\/jw\/web\/userview\/vehicle\/carpark\/_\/car_park_registration?_action=assignmentView","target":"_self","hrefParam":"activityId","hrefColumn":"activityId","label":"Run Process","confirmation":"","visible":"","rules":[]}}],"actions":[],"filters":[],"binder":{"className":"org.joget.plugin.enterprise.JdbcDataListBinder","properties":{"jdbcDatasource":"default","sql":"SELECT \n    a.*,\n    sass.activityId,\n    sact.Name AS activityName,\n    GROUP_CONCAT(DISTINCT sass.ResourceId\n        SEPARATOR ', ') AS assignee\nFROM\n    app_fd_cars AS a\n        JOIN\n    SHKActivities AS sact ON a.id = sact.ProcessId\n        JOIN\n    SHKActivityStates AS ssta ON ssta.oid = sact.State\n        INNER JOIN\n    SHKAssignmentsTable AS sass ON sact.Id = sass.ActivityId\nWHERE\n    ssta.KeyValue = 'open.not_running.not_started'\nGROUP BY a.id","primaryKey":"id"}},"columns":[{"id":"column_0","label":"id","displayLabel":"id","name":"id"},{"id":"column_1","label":"c_licensePlate","displayLabel":"c_licensePlate","name":"c_licensePlate"},{"id":"column_2","label":"c_brand","displayLabel":"c_brand","name":"c_brand"},{"id":"column_3","label":"c_approve","displayLabel":"c_approve","name":"c_approve"},{"id":"column_4","label":"activityName","displayLabel":"activityName","name":"activityName"},{"id":"column_5","label":"assignee","displayLabel":"assignee","name":"assignee"}]}

นอกจากนี้ยังสามารถหาตัวอย่างได้จาก app Process Monitor Utility ได้อีกด้วย

joGet: ฟอร์มส่งอีเมล์

ตัวอย่างฟอร์มส่งอีเมล์โดยใน joget ผู้ใช้สามารถแนบไฟล์เพิ่มเติม เลือกไฟล์จากที่มีโดยจะมีตัวอย่างไฟล์ที่จะแนบไปด้วย ให้เห็นก่อนตัดสินใจส่งอีเมล์

สร้างฟอร์มที่จะส่งอีเมล์ได้โดยใช้ json

{"className":"org.joget.apps.form.model.Form","properties":{"id":"sendEmail","loadBinder":{"className":"org.joget.apps.form.lib.WorkflowFormBinder","properties":{}},"tableName":"prototypes","description":"","name":"Send Email","postProcessorRunOn":"both","storeBinder":{"className":"org.joget.apps.form.lib.WorkflowFormBinder","properties":{}},"postProcessor":{"className":"","properties":{}},"permission":{"className":"","properties":{}},"noPermissionMessage":""},"elements":[{"elements":[{"elements":[{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"mailTo","workflowVariable":"mailTo","readonlyLabel":"","maxlength":"","encryption":"","validator":{"className":"org.joget.apps.form.lib.DefaultValidator","properties":{"message":"","custom-regex":"","mandatory":"true","type":"email"}},"value":"","label":"To","readonly":"","size":""}},{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"mailCc","readonlyLabel":"","workflowVariable":"mailCc","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"CC","readonly":"","size":""}},{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"mailBcc","readonlyLabel":"","workflowVariable":"mailBcc","maxlength":"","encryption":"","validator":{"className":"","properties":{}},"value":"","label":"BCC","readonly":"","size":""}},{"className":"org.joget.apps.form.lib.TextField","properties":{"id":"mailSubject","workflowVariable":"mailSubject","readonlyLabel":"","maxlength":"","encryption":"","validator":{"className":"org.joget.apps.form.lib.DefaultValidator","properties":{"message":"","custom-regex":"","mandatory":"true","type":""}},"value":"","label":"Subject","readonly":"","size":""}},{"className":"org.joget.apps.form.lib.TextArea","properties":{"id":"mailMessage","workflowVariable":"mailMessage","readonlyLabel":"","cols":"20","validator":{"className":"org.joget.apps.form.lib.DefaultValidator","properties":{"message":"","custom-regex":"","mandatory":"true","type":""}},"value":"","label":"Message","readonly":"","rows":"5"}},{"className":"org.joget.apps.form.lib.FileUpload","properties":{"id":"mailAttach1","fileType":"","validator":{"className":"","properties":{}},"label":"Attach","attachment":"","multiple":"","readonly":"","maxSize":"","maxSizeMsg":"File size limit exceeded","fileTypeMsg":"Invalid file type","permissionType":"","size":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachName1","workflowVariable":"mailAttachName1","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachPath1","workflowVariable":"mailAttachPath1","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachName2","workflowVariable":"mailAttachName2","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachPath2","workflowVariable":"mailAttachPath2","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachName3","workflowVariable":"mailAttachName3","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachPath3","workflowVariable":"mailAttachPath3","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachName4","workflowVariable":"mailAttachName4","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.HiddenField","properties":{"id":"mailAttachPath4","workflowVariable":"mailAttachPath4","value":"","useDefaultWhenEmpty":""}},{"className":"org.joget.apps.form.lib.CustomHTML","properties":{"id":"sendEmailTemplateA","autoPopulate":"","value":"<link href=\"\/jw\/plugin\/org.joget.plugin.enterprise.RichTextEditorField\/css\/jquery.richtext.css\" rel=\"stylesheet\" \/>\n<script src=\"\/jw\/js\/tiny_mce\/jquery.tinymce.js\"><\/script>\n<script src=\"\/jw\/plugin\/org.joget.plugin.enterprise.RichTextEditorField\/js\/jquery.richtext.js\"><\/script>\n<script src=\"\/jw\/assets\/scripts.js\"><\/script>\n<b>File Attached :: <\/b>\n<div class=\"accordion\" id=\"accordionA\"><\/div>\n<script>\n    $(document).ready(function() {\n\n        let mailMessage = $('#mailMessage');\n\n        let message = 'Dear'
+\n            '<br><br>The quick brown fox jumps over the lazy dog<br>' +\n            '<br><br>regard' +\n            '<br><br>Pitt Phunsanit';\n\n        mailMessage.val(message);\n        mailMessage.richtext({\n            \"contextPath\": \"\/jw\"\n        });\n\n        emailAttachment([{\n                \"name\": \"JasperReport 1\",\n                \"url\": \"#request.scheme#:\/\/#request.serverName#:#request.serverPort#\/jw\/web\/json\/plugin\/org.joget.plugin.enterprise.JasperReportsMenu\/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport1&type=pdf&userviewId=prototypes\"\n            },\n            {\n                \"name\": \"JasperReport 2\",\n                \"url\": \"#request.scheme#:\/\/#request.serverName#:#request.serverPort#\/jw\/web\/json\/plugin\/org.joget.plugin.enterprise.JasperReportsMenu\/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport2&type=pdf&userviewId=prototypes\"\n            },\n            {\n                \"name\": \"JasperReport 3\",\n                \"url\": \"#request.scheme#:\/\/#request.serverName#:#request.serverPort#\/jw\/web\/json\/plugin\/org.joget.plugin.enterprise.JasperReportsMenu\/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport3&type=pdf&userviewId=prototypes\"\n            },\n            {\n                \"name\": \"JasperReport 4\",\n                \"url\": \"#request.scheme#:\/\/#request.serverName#:#request.serverPort#\/jw\/web\/json\/plugin\/org.joget.plugin.enterprise.JasperReportsMenu\/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport4&type=pdf&userviewId=prototypes\"\n            }\n        ]);\n\n    });\n<\/script>","label":""}}],"className":"org.joget.apps.form.model.Column","properties":{"width":"100%"}}],"className":"org.joget.apps.form.model.Section","properties":{"id":"SendEmail","loadBinder":{"className":"","properties":{}},"visibilityControl":"","regex":"","visibilityValue":"","storeBinder":{"className":"","properties":{}},"label":"Send Email","permission":{"className":"","properties":{}}}}]}

การทำงานจะมี 2 ส่วนคือ ส่วนที่เรียกใช้ function สำเร็จรูป

<link href="/jw/plugin/org.joget.plugin.enterprise.RichTextEditorField/css/jquery.richtext.css" rel="stylesheet" />
<script src="/jw/js/tiny_mce/jquery.tinymce.js"></script>
<script src="/jw/plugin/org.joget.plugin.enterprise.RichTextEditorField/js/jquery.richtext.js"></script>
<script src="/jw/assets/scripts.js"></script>
<b>File Attached :: </b>
<div class="accordion" id="accordionA"></div>
<script>
$(document).ready(function() {

let mailMessage = $('#mailMessage');

let message = 'Dear' +
'<br><br>The quick brown fox jumps over the lazy dog<br>' +
'<br><br>regard' +
'<br><br>Pitt Phunsanit';

mailMessage.val(message);
mailMessage.richtext({
"contextPath": "/jw"
});

emailAttachment([{
"name": "JasperReport 1",
"url": "#request.scheme#://#request.serverName#:#request.serverPort#/jw/web/json/plugin/org.joget.plugin.enterprise.JasperReportsMenu/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport1&type=pdf&userviewId=prototypes"
},
{
"name": "JasperReport 2",
"url": "#request.scheme#://#request.serverName#:#request.serverPort#/jw/web/json/plugin/org.joget.plugin.enterprise.JasperReportsMenu/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport2&type=pdf&userviewId=prototypes"
},
{
"name": "JasperReport 3",
"url": "#request.scheme#://#request.serverName#:#request.serverPort#/jw/web/json/plugin/org.joget.plugin.enterprise.JasperReportsMenu/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport3&type=pdf&userviewId=prototypes"
},
{
"name": "JasperReport 4",
"url": "#request.scheme#://#request.serverName#:#request.serverPort#/jw/web/json/plugin/org.joget.plugin.enterprise.JasperReportsMenu/service?action=report&appId=prototypes&appVersion=1&key=_&menuId=JasperReport4&type=pdf&userviewId=prototypes"
}
]);

});
</script>
  • let message จะสร้างเนื้อหาอีเมล์เป็น template ให้ก่อน user จะได้ไม่ต้องเขียนเองใหม่ทุกครั้ง
  • .richtext() ทำหน้าที่เปลี่ยน textarea เป็น rich text box แทนที่จะใช้ rich text box ของ joGet เอง เพราะจะไม่มีที่ผูก workflow Variable ได้ (งงกับการออกแบบ tools ของพี่แกจริงๆ)
  • emailAttachment() จะสร้างส่วน ui ให้ user เลือกที่จะแนบไฟล์หรือไม่แนบไฟล์และแสดง preview pdf ให้ดูก่อนที่จะส่งอีเมล์ออกไป

และส่วน javascript ที่แยกออกไปเพื่อใช้ซ้ำในฟอร์มอื่นๆ

/*
pitt phunsanit
email attachment preview
version 1
*/
function emailAttachment(lists) {
let accordionA = $("#accordionA");
let expaned = "";

$.each(lists, function(a, item) {
let itemNo = a + 1;

$("#mailAttachName" + itemNo).val(item.name);
$("#mailAttachPath" + itemNo).val(item.url);

let id = "attach" + itemNo;

if (a == 0) {
expaned = " in";
} else {
expaned = "";
}

let card =
'<div class="accordion-group">' +
'<div class="accordion-heading">' +
'<input checked style="float: left; margin: 10px 10px 0 10px;" type="checkbox" value="' +
itemNo +
'">' +
'<a class="accordion-toggle" data-parent="#accordionA" data-toggle="collapse"  href="#' +
id +
'" style="margin: 0px 10px; width: 80%;">' +
item.name +
'</a><a class="fa fa-download" href="' +
item.url +
'" style="float: right; font-size: 30px; margin: -32px 20px;" target="_blank"></a></div>' +
'<div class="accordion-body collapse' +
expaned +
'" id="' +
id +
'"><div class="accordion-inner">' +
'<iframe frameborder="0" height="842" id="attachIframe" src="' +
item.url +
'" width="100%"></iframe>' +
"</div></div></div>" +
"</div>";
accordionA.append(card);
});

accordionA.on("change", 'input[type="checkbox"]', function() {
let checkbox = $(this);

let itemNo = checkbox.val();

let mailAttachName = $("#mailAttachName" + itemNo);
let mailAttachPath = $("#mailAttachPath" + itemNo);
if (checkbox.is(":checked")) {
mailAttachPath.prop("disabled", false);
mailAttachName.prop("disabled", false);
} else {
mailAttachPath.prop("disabled", true);
mailAttachName.prop("disabled", true);
}
});
}

เรื่องที่เกี่ยข้อง

joGet: ส่งอีเมล์ด้วย Email Tool

อีเมล์ Email Tool เป็น plugin ที่สามารถ add เข้าไปใน process เพื่อส่งอีเมล์ได้จากข้อมูลใน process

การ configurationg

  1. เริ่มจากการ SMTP server โดย joGet จะไม่มีติดมาให้ ตัวทีติดตั้งง่ายที่สุดน่าจะเป็น Mercury Mail Transport System ที่ติดมากับ XAMPP
  2. กรอกข้อมูลการติดต่อ SMTP SERVER โดยควรจะใช้ Environment Variable Hash Variable เพราะเวลาเปลี่ยน smtp server จะได้ไม่ต้องมาไล่แก้ที่ละกล่องเช่น
    SMTP Host
    #envVariable.smtpHost# แทน smtp server ที่จะ connection เข้าไปใช้
    SMTP Port
    #envVariable.smtpPort# โดยปกติจะใช้ 25, 79, 105, 106, 110, 143, 224 แล้วแต่จะเซ้ตไว้แบบไหน
    Security
    บางระบบไม่ต้องเซ็ต
    SMTP Username
    #envVariable.smtpUsername# แทน smtp username
    SMTP Password
    #envVariable.smtpPort# แทนรหัสผ่าน smtp

    ทดลองการติดต่อกับ smtp server โดยคลิก Send Test Email ถ้าเห็น alert “Test email is sent.” ถือว่าการส่งอีเมล์ได้แล้ว

  3. คลิก next>
  4. กรอกรายละเอียดของอีเมล์ที่จะส่ง โดยใช้ Workflow Variable Hash Variable ในการส่งค่ามาจากฟอร์มอื่นๆ เช่น หรือจะใส่ค่าลงไปตรงๆก็ได้
    From *
    #variable.mailFrom# แทนจะส่งโดยใช้อีเมล์อะไร บาง smtp server จะบังคับด้วยว่าอีเมล์ตัวไหนจึงจะส่งข้อมูลได้
    To (Specific email address)
    #variable.mailTo# แทนผู้รับ
    To (Participant ID)
    #variable.mailTo# แทนผู้รับแต่ละคน จะส่งได้พร้อมกันหลายคนโดยแบ่งด้วย ;
    CC
    #variable.mailCc# แทนผู้รับแบบสำเนา (Carbon copy) ส่งได้พร้อมกันหลายคนโดยแบ่งด้วย ;
    BCC
    #variable.mailBcc# แทนผู้รับแบบสำเนาลับ (Blind carbon copy) ส่งได้พร้อมกันหลายคนโดยแบ่งด้วย ;
    Subject
    #variable.mailSubject# แทนชื่อเรื่องอีเมล์
    Message
    #variable.mailMessage# แทนเนื้ออีเมล์
    HTML Content?
    ถ้าติ๊กไว้ จะส่งอีเมล์โดยบอกว่าเนื้อหาเป็น html ไม่ใช่ plain text
  5. คลิก next>
  6. ส่วนไฟล์แนบ (Attachments)
    • ส่งไฟล์จากฟอร์ม
      Form
      ฟอร์มที่จะใช้แนบไฟล์มา
      Form Upload Fields
      คือ id ของ input ที่จะส่งไฟล์มา มีได้หลาย input เช่น mailAttach1, mailAttach2, mailAttach3, mailAttach4
    • ส่งไฟล์จากไฟล์พาร์ทสามารถส่งได้หลายไฟล์เหมือนกัน
      Path
      #variable.mailAttachPath1, #variable.mailAttachPath2#, #variable.mailAttachPath3#, #variable.mailAttachPath4# แทน file path
      Type
      มี 2 แบบคือ

      System Path
      file path ที่เก็บไฟล์เอาไว้ เช่น C:\Joget-v5-Enterprise\apache-tomcat-8.0.20\webapps\jw\images\cover.jpg
      URL
      url ที่สามาร���ดูไฟล์ เช่น http://localhost:8080/jw/images/cover.jpg
      File Name
      #variable.mailAttachName1#, #variable.mailAttachName2#, #variable.mailAttachName3#, #variable.mailAttachName1# แทนชื่อไฟล์ที่จะแสดงตอนที่ส่งเมล์ไปให้ผู้รับ

เท่านี้ก็สามารถใช้ ่ joGet ส่งอีเมล์ได้แล้ว

เรื่องที่เกี่ยข้อง