JSP - Quick Reference

JSP Tag
Tag สำหรับ JSP ที่ใช้มีดังนี้

scriptlet - <% ... %> เป็นพื้นฐานของ JSP เลย เราสามารถเขียน code java ลงไปในนี้ได้
XML-compliant ที่ใช้แทน <% list.add("Fred"); %> จะเป็นดังนี้

<jsp:scriptlet>
list.add("Fred");
</jsp:scriptlet>

directive - <@% ...%>
DirectiveAttributeUsage
pagecontentTypeกำหนดการเข้ารหัสตัวอักษรหรือ MIME type ของ response ในกรณีที่ไม่ได้กำหนดค่าจะใช้ค่าจาก pageEncoding attribute

default = "text/html;charSet=ISO-8859-1"
importimport class อื่นเข้ามาใช้งาน

XML-compliant: <jsp:directive.page import="path/file" />
isThreadSafeถ้าเป็น "true" แปลว่า Servlet ที่ได้ หลังจาก translate JSP แล้วจะ implement SingleThreadModel เพื่อให้ Servlet เป็น thread safe (ซึ่งการทำงานจริงๆ ของ SingleThreadModel ขึ้นอยู่กับ Web Container แต่ละเจ้า จะ implement เป็นแบบไหน ซึ่งโดยลึกๆ แล้ว ไม่ค่อยได้ประโยชน์เท่าไร)
errorPageurl ของ exception page
isErrorPageบอกให้รู้ว่า JSP page ปัจจุบันเป็น errorPage หรือไม่ ถ้าเป็น "true" ก็จะมี implicit object exception ถ้าเป็น "false" ก็จะไม่สามารถใช้ object exception ใน page นี้ได้

default = "false"
isELIgnoredบอกว่าจะไม่สามารถใช้ Expression Language ใน JSP นี้ได้
languagedefine scripting language ที่ใช้ใน scriptlet และ declaration
default = Java
extendsกำหนด class ที่ JSP นี้จะ extend ซึ่งโดยปกติ จะึขึ้นอยู่กับ web containner ดังนั้นถ้าเราต้องการจะ extend ตัวอื่นจะต้องกำหนดไว้ แต่ควรจะแน่ใจจริงๆ ว่ามันทำงานได้นะจ๊ะ
sessionกำหนดว่าเอกสารนี้จะใช้ implicit object session หรือไม่ สามารถกำหนดเป็น session="false" ถ้าไม่ต้องการใช้ session

default = "true"
bufferควบคุมการใช้ buffer สำหรับ jsp ว่าต้องการ buffer หรือไม่ ค่าเริ่มต้นจะอยู่ที่ 3 KB
autoFlushเมื่อ buffer เต็มจะ cleart buffer ให้อัตโนมัติ

default = "true"
infoสามารถกำหนดเป็นค่า string ใดๆ ซึ่งจะเก็บไว้ใน servlet ที่ได้ translate จาก JSP และสามารถดึงขึ้นมาโดย Servlet.getServletInfo()
pageEncodingบอกว่า page JSP encode ด้วยรหัสอะไร ในกรณีที่ไม่กำหนดค่าจะใช้ค่าจาก contentType attribute

default = "ISO-8859-1"
includefileชื่อไฟล์ที่ต้องการนำมา include (ไฟล์ servlet ที่ได้จะเสมือนเอา included file มาแปะไว้กับ servlet เลย)
taglibtagdirdirectory ที่เก็บ tag file ไว้ (จะใช้ในกรณีที่ไม่ได้ declare tag file ไว้ใน tld)
prefixชื่อที่ใ้ช้ในการเรียก tag lib นี้ ซึ่งเป็นค่าอะไรก็ได้ ยกเว้น jsp, jspx, java, javax, servlet, sun, sunw
uriชื่อที่ต้องใช้ให้ตรงกับไฟล์ Tag Library Descriptor (TLD)
tag
*ใช้สำหรับ tag file เท่านั้น
importimport class อื่นเข้ามาใช้งาน
isELIgnoredบอกว่าจะไม่สามารถใช้ Expression Language ใน JSP นี้ได้
languagedefine scripting language ที่ใช้ใน scriptlet และ declaration

default = Java
body-contentมีค่าได้ดังนี้
  • scriptless - ไม่รับ JSP scriptlet แต่สามารถรับเป็น EL expression ได้
  • tagdependent - รับ body เสมือนว่าเป็น string
  • empty - ไม่รับ body
สังเกตว่า ไ่ม่มี JSP ในนี้ นั่นคือใน body ของ tag จะไม่สามารถเป็น scriptlet ไำด้
dynamic-attributesชื่อของ dynamic attribute ซึ่งจะรับเป็น HashMap เป็นชื่อและค่าของ attribute
attribute
*ใช้สำหรับ tag file เท่านั้น
nameชื่อของ attribute ที่รับเข้ามา
requiredเป็นค่า boolean เพื่อบอกว่าเป็น attribute ที่ต้องมีเสมอหรือไม่
rtexprvalueค่า boolean ที่บอกว่าจะ สามารถรับเป็น scriptlet ได้หรือไม่
variable
*ใช้สำหรับ tag file เท่านั้น
name-givenชื่อของตัวแปร
variable-classclass ของตัวแปร เช่น java.lang.String

expression - <%= ... %> ใช้แทน out.print() ในการแสดงผล
XML-compliant ที่ใช้แทน <%= it.next %> จะเป็นดังนี้

<jsp:expression>

it.next()
</jsp:expression>

declaration - <%! ... %> ใช้สำหรับ declare instance variable หรือ method
XML-compliant ที่ใช้แทน <%! int y = 3; %> จะเป็นดังนี้

<jsp:declaration>

int y = 3;
</jsp:declaration>

XML-compliant คือการทำให้ JSP page เป็น JSP document ความแตกต่างของสองอันนี้ก็คือ JSP document จะเป็น XML-compliant คือเป็น well-formed XML ซึ่งโดยปกติแล้ว เราจะไ่ม่ได้เขียน JSP document เอง แต่อาจจะใช้ tools ในการสร้างขึ้นมา ตัวอย่างอีก ตัวอย่างหนึ่งสำหรับ XML-compliant ก็คือการเขียน text บน JSP page ซึ่งจะใช้ตัวอย่างด้านล่างแทน

<jsp:text>

This is text.
<jsp:text>

สำหรับ comment สามารถใช้ comment ใน html คือ <!-- comment --> หรือใช้ JSP comment <% /* comment */ %> ก็ได้ แต่ถ้าใช้ html comment ข้อความก็จะถูกส่งไปที่ client เสมือนกับ html comment ทั่วไป แต่สำหรับ JSP comment จะถูกตัดทิ้งไปเมื่อ translate จาก JSP เป็น Servlet


JSP Implicit Object



APIImplicit ObjectUsed by Servlet
JspWriteroutresponse.getWriter()*
* it will get PrintWriter, not JspWriter
HttpServletRequestrequestrequest*
* depend on how to declare parameter name in service method
HttpServletResponseresponseresponse*
* depend on how to declare parameter name in service method
HttpSessionsessionrequest.getSession()
ServletContextapplicationgetServletContext()
ServletConfigconfiggetServletConfig()
Throwableexception
PageContextpageContextN/A
Object
pageN/A
page scope is not available in Servlet

tag file ก็สามารถใช้ implicit object ตัวเดียวกับ JSP file ได้เหมือนกัน ยกเว้น ServletContext ซึ่งใน tag file จะใช้เป็น jspContext ซึ่งเป็น JspContext object แทน และไม่สามารถใช้ application ซึ่งเป็น ServletContext object ได้

EL Implicit Object

Implicit ObjectUsed by Scriplet
${pageScope.name}N/A
page scope is not available in Servlet
${requestScope.name}request.getAttribute("name")
${sessionScope.name}session.getAttribute("name")
${applicationScope.name}application.getAttribute("name")
${param.name}request.getParameter("name")
${paramValues.name[index]}request.getParameterValues("name")[index]
${header.name}request.getHeader("name")
${headerValues.name[index]}
Enumeration headers
= request.getHeaders("name");
int i = 0;
while (headers.hasMoreElements()) {
if (i == index) {
String s = (String) headers.nextElement();
}
i++;
}
${cookie.name}
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
if ((cookies[i].getName()).equals("name")) {
Cookie s = cookies[i];
}
}
${initParam.name}application.getInitParameter("name")
${pageContext.name}pageContext.getName() เช่น pageContext.exception ซึ่งเป็นตัวแปรเดียวกับ exception ใน JSP Implicit Object ซึ่งจะสามารถ access ตัวแปรนี้ได้จะต้องกำหนดให้*
<%@ page isErrorPage="true" %>

*แต่ไปลองดูแล้วกับ Tomcat 6, Servlet 2.5 ปรากฎว่าถึงไม่ใส่ ก็สามารถ access ตัวแปรได้นะ ไม่แน่ใจเหมือนกัน

ซึ่ง pageScope, requestScope, sessionScope, applicationScope สามารถละไว้ได้ถ้าในกรณีที่เราไม่ต้องการระบุว่าจะใช้ attribute จาก scope ใด

${requestScope.person.name} --> ${person.name}

ยกเว้นถ้าในกรณีที่มี attribute ชื่อเดียวกันในหลาย scope และต้องการระบุว่าต้องการจาก scope ไหน หรือในกรณีที่ชื่อของ attribute ไม่เป็นไปตาม Java naming rule เช่น

request.setAttribute("foo.person", p); // ซึ่ง เราไม่สามารถใช้ ${foo.person.name} ได้

${requestScope["foo.person"].name}

EL Operation

Arimetic uses + , - , *, / or div, % or mod
Logical uses && or and, || or or, ! or not
Relational uses == or eq, != or ne, < or lt, > or gt, <= or le, >= or ge


EL Function

ใช้การกำหนด function ใน Tag Library Descriptor (TLD) file โดยเรียก public static method ใน class

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">
<tlib-version>1.2</tlib-version>
<short-name>NMTOKEN</short-name>

<uri>DiceFunction</uri>
<function>
<name>rollIt</name>
<function-class>com.amadmonster.scwcd.el.function.DiceRoller</function-class>
<function-signature>int rollDice()</function-signature>
</function>

<!-- สำหรับ function ที่รับตัวแปร -->
<function>
<name>rollWith</name>
<function-class>com.amadmonster.scwcd.el.function.DiceRoller</function-class>
<function-signature>int rollDice(int)</function-signature>
</function>
</taglib>

นอกจาก tld file จะประกอบด้วย EL Function แล้วยังสามารถใส่ custom tag ด้วย แต่จะกล่าวในตอน JSTL & Custom Tag ต่อไป

Standard Action
ActionAttributeUsage
jsp:useBeanidเป็น identifier ของ object โดยรับเป็น string name ของ JavaBean นั้นๆ ซึ่งจะแปลเป็น servlet โดยใช้ getAttribute หรือ setAttribute method ดังนั้นจึงเป็น case sensitive
scopeเป็น scope ที่ใช้ในการอ้างอิงถึง JavaBean นั้น มีค่าได้ดังนี้
  • page: ใช้ใน page นั้นๆ (default)
  • request: ใช้ในการ request ครั้งหนึ่งๆ เป็น attribute ของ request
  • session: ใช้ใน session นั้นๆ เหมือนกับ attribute ของ session
  • application: ใช้ได้ทุกๆ servlet เหมือนกับ attribute ของ applicationContext
default: page
classclass ของ bean ที่จะถูกสร้างขึ้นในกรณีที่ attribute นั้นๆ ไม่มีอยู่ใน scope ที่ ซึ่งไ่ม่สามารถกำหนดเป็น interface หรือ abstract class ได้

property นี้เป็น optional คือไม่จำเป็นต้องมีก็ได้ ซึ่งใช้ในกรณีที่เราต้องการดึงค่า attribute ขึ้นมาใช้ แต่ในกรณีที่ไม่มี attribute อยู่จะทำการสร้าง bean เพื่อจะ add attribute ก็จะ error InstantiationException
typeType ของ bean ในกรณีที่จะถูกสร้างขึ้น เมื่อไม่มีอยู่ใน scope ซึ่งอาจจะเป็นค่าเดียวกับ class property หรือว่าเป็น parent object ของ class property หรือว่าเป็น interface ก็ได้

ในกรณีที่ไม่ได้กำหนด จะถือว่าเป็นค่า default คือ เหมือนกับ class
beanNameชื่อของ Bean
jsp:setProperty

สามารถใส่ไว้ใน body ของ jsp:useBean ได้ กรณีที่ต้องการให้ set property เมื่อมีการสร้าง bean ใหม่ (ในกรณีที่มีอยู่แล้วจะไม่ set)
nameชื่อของ Bean (เป็นค่า property id ใน action jsp:useBean นั้นเอง) ที่เรา้้จะ set ค่า
propertyชื่อ property ที่เราต้องการจะ set ค่า ถ้าให้ค่าเป็น "*" คือ ให้ map ชื่อ property กับ parameter ของ request object ที่ชื่อตรงกัน
valueค่าที่จะ set ใหักับ property นั้นๆ (ถ้ามีการ set ค่าใช้กับ param attribute ก็จะต้องไม่มีการ set ค่ากับ value อีก
paramชื่อ parameter ที่จะให้ค่ากับ property นั้นๆ ในกรณีนี้จะไม่ใส่ property value หรือในกรณีที่ไม่ใส่ัทั้ง value และ param แสดงว่า param เป็นค่าเดียวกับ property (หรือให้ใช้ param ที่มีค่าเดียวกับ property สำหรับ set ค่า)
jsp:getPropertynameชือของ object Bean (ค่า property id ใน action jsp:useBean นั้นเอง) ที่เราต้องการจะรับค่า
propertyproperty ที่เราต้องการจะรับค่า
jsp:forwardpagerelative url ที่ต้องการ forward ไป ซึ่งจะเป็น JSP, servlet หรือ dynamic file อื่นๆ ก็ได้ ที่อยู่ใน application เดียวกัน
jsp:includepagerelative url ที่จะ include (jsp:include ให้ผลเหมือนกับ directive include แต่ว่าจะทำเมื่อ runtime สำหรับในกรณีที่ included file ยังมีการเปลี่ยนแปลงอยู่)
jsp:paramnameชื่อตัวแปรที่ต้องการ forward ไปพร้อมกับ jsp:forward หรือ jsp:include เช่น
<jsp:include page="Header.jsp">
<jsp:param name="subTitle"
value="Customized Title">

</jsp:include>
valueค่าของตัวแปรตามชื่อที่ต้องการส่ง
jsp:attributenameชื่อของ attribute ซึ่งตัวนี้มี body ด้วยเป็นค่าของ attribute เช่น
<jsp:attribute name="user">${userName}</jsp:attribute>
jsp:attribute สามารถใส่ใน custom tag body ได้ ถึงแม้ว่าจะกำหนด <body-content>empty</body-content>
jsp:doBody
*ใช้สำหรับ tag file เท่านั้น

สำหรับ tag file เพื่อดึงค่า body ของ tag


Reference:
JSP 2.0 Syntax Reference

Servlet: Listener

listener class เป็นคลาสที่มีลักษณะเป็น event-driven คือ method ที่อยู่ใน listener จะต้องถูกเรียกโดยอัตโนมัติ มีการเหตุการณ์เกิดขึ้น ซึ่งแต่ละ class ก็จะ support event ที่แตกต่างกันไป



ที่เราเห็นใช้กันบ่อยหน่อย ก็คงจะเป็น ServletContextListener ซึ่งจะ support event ที่เกี่ยวกับการ initialize และ destroy context หรือเมื่อเรา deploy application เราขึ้นไปบน web container หรือตอนที่ เรา undeploy หรือตอนที่ server start หรือ clash ก็จะมีการเรียก class นี้ไปใช้ ส่วน ServletContextAttributeListener ก็จะเป็นคลาสที่ทำงานเมื่อการมี add, remove, replace attribute เข้าไปที่ context (ดังนั้นจะต้องเป็น attribute ที่เป็น context scope เท่านั้น)

ส่วน ServletRequestListener และ ServletRequestAttributeListener ก็จะคล้ายกัน คือ สำหรับเมื่อมี request เกิดขึ้น หรือก่อนที่ request จะจบ และเมื่อมีการเปลี่ยนแปลงของ attribute ใน request (page scope)

ส่วนอีก 4 listener ที่เหลือ คือ HttpSessionListener, HttpSessionAttributeListner และ HttpSessionActivationListener, HttpSessionBindingListener ก็จะเป็น listener ที่เกี่ยวกับ session โดย 2 อันแรก จะคล้ายกับที่กล่าวมาข้างต้น คือเกี่ยวกับ สร้าง/ทำลาย session และเกี่ยวกับ add, remove, replace ของ session attribute

สำหรับ HttpSessionActivationListener จะเกี่ยวพันถึงการ migrate session ข้าม jvm (สำหรับบางกรณี เช่นการทำ load-balancing) และ HttpSessionBindingListener จะคล้ายกับ HttpSessionAttributeListener แต่ต่างกันที่เป็น listener ที่จะ implement โดย attribute class คือมันจะ notify ที่ attribute ที่ implement มัน เมื่อ attribute นั้นๆ ถูกผูกเข้ากับ session หรือโยนออกจาก session

ซึ่ง listener class ส่วนใหญ่จะต้อง declare ไว้ใน DD (web.xml) ยกเว้น HttpSessionBindingListener ที่ไม่ต้องใส่ไว้ใน DD

ListenerDescriptionmethod
javax.servlet.
ServletContextListener
support event ที่เกี่ยวกับการ initialize และ destroy context หรือเมื่อเรา deploy application เราขึ้นไปบน web container หรือตอนที่ เรา undeploy หรือตอนที่ server start หรือ clash ก็จะมีการเรียก class นี้ไปใช้contextInitialized(ServletContextEvent)
contextDestroyed(ServletContextEvent)
javax.servlet.
ServletContextAttributeListener
ทำงานเมื่อการมี add, remove, replace attribute เข้าไปที่ contextattributeAdded(ServletContextAttributeEvent)
attributeRemoved(ServletContextAttributeEvent)
attributeReplaced(ServletContextAttributeEvent)
javax.servlet.
ServletRequestListener
เมื่อมี request เกิดขึ้น หรือก่อนที่ request จะจบ requestInitialized(ServletRequestEvent)
requestDestroyed(ServletRequestEvent)
javax.servlet.
ServletRequestAttributeListener
เมื่อมีการเปลี่ยนแปลงของ attribute ใน request
attributeAdded(ServletRequestAttributeEvent)
attributeRemoved(ServletRequestAttributeEvent)
attributetReplaced(ServletRequestAttributeEvent)
javax.servlet.http.
HttpSessionListener
เกี่ยวกับ สร้าง/ทำลาย sessionsessionCreated(HttpSessionEvent)
sessionDestroyed(HttpSessionEvent)
javax.servlet.http.
HttpSessionAttributeListner
เกี่ยวกับ add, remove, replace ของ session attributeattributeAdded(HttpSessionBindingEvent)
attributeRemoved(HttpSessionBindingEvent)
attributeReplaced(HttpSessionBindingEvent)
javax.servlet.http.
HttpSessionActivationListener
จะเกี่ยวพันถึงการ migrate session ข้าม jvm (สำหรับบางกรณี เช่นการทำ load-balancing)sessionDidActivate(HttpSessionEvent)
sessionWillPassivate(HttpSessionEvent)
javax.servlet.http.
HttpSessionBindingListener
คล้ายกับ HttpSessionAttributeListener แต่ต่างกันที่เป็น listener ที่จะ implement โดย attribute class คือมันจะ notify ที่ attribute ที่ implement มัน เมื่อ attribute นั้นๆ ถูกผูกเข้ากับ session หรือโยนออกจาก sessionvalueBound(HttpSessionBindingEvent)
valueUnbound(HttpSessionBindingEvent)

Servlet: Cookie Example1

ตัวอย่างนี้เป็นตัวอย่างโปรแกรม cookie ที่เพียงต้องการแสดงให้รู้จักการใช้ cookie เท่านั้น อาจจะไม่ใช่โปรแกรมที่สมเหตุสมผลเท่าไรนะค่ะ

เอาละ มาดูกัน

CookieAdd.java

package com.amadmonster.scwcd.cookies; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class CookieAdd */ public class CookieAdd extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); // add any name to test cookie Cookie cookie = new Cookie("username", "amadmonster"); cookie.setMaxAge(30 * 60); response.addCookie(cookie); RequestDispatcher view = request .getRequestDispatcher("cookies/cookieresult.jsp"); view.forward(request, response); } }


cookie/cookieresult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="testcookie.do">click</a> </body> </html>

CookieAdd เป็น servlet ที่ใส่ cookie username ไว้ และ forward ต่อให้ cookieresult.jsp แสดงลิงค์ ไปยัง CookieTester (testcookie.do map กับ CookieTester.java) เพื่อแสดงผลค่าของ cookie username ที่เก็บไว้

CookieTester.java

package com.amadmonster.scwcd.cookies; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class CookieTester */ public class CookieTester extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; if (cookie.getName().equals("username")) { String userName = cookie.getValue(); out.println("Hello " + userName); break; } } } }


Cookie จะเหมือน attribute ใน session scope ฮับ คือใน session เดียวกันจะเป็นตัวเดียวกัน ในขณะที่อีก session หนึ่งจะไม่เห็นตัวแปรนั้น ลองทดสอบได้ฮับ ถ้าคุณใช้ IE อยู่ หลังจากที่ run CookieAdd แล้ว ให้ลองเปิดอีก tab หนึ่ง (แต่ยังอยู่ใน windows เดียวกันนะ) ให้ run testcookie.do ซึ่งจะแสองผลเหมือนกับยังอยู่ใน tab เดิมอยู่ แต่ถ้าเปิด IE ขึ้นมาอีก 1 ตัว และลอง run testcookie.do (โดยไม่ run CookieAdd ก่อน) จะได้เป็นหน้าว่างๆ ฮับ เนื่องจากไม่มี cookie ที่ชื่อ username ที่จะแสดงผลนั่นเอง

ลองดูนะฮับ ขอให้โชคดี

Servlet: Class Diagram



สำหรับ parameter ที่ได้รับมาจากแต่ละ reqest method ที่ใช้ก็จะเป็น method ที่อยู่ใน ServletRequest ทั้งหมด ซึ่งมีดังนี้

getParameter(String)
getParameterNames()
getParameterValue(String) - คล้ายกับ getParameter(String) แต่สามารถดึงค่าตัวแปรที่เป็น array ของ String ได้

จะเห็นว่า parameter มีแต่ get method เท่านั้น เราไม่สามารถ set ค่า ให้กับ parameter ได้


Initial parameter

สำหรับ initial parameter ที่กำหนดไว้ใน deployment descriptor ซึ่งมีด้วยกัน 2 ส่วนคือ
  1. ส่วนที่กำหนดไว้ที่ context-param ซึ่งเป็นค่าทุก servlet สามารถนำไปใช้ได้ โดยใช้ method จาก ServletContext getInitParameter(String) หรือ getInitParameterNames()
  2. ส่วนที่กำหนดไว้ที่ init-param ใน servlet จะต้องใช้ ServletConfig getInitParameter(String) method

Attribute

ก่อนหน้านี้เคยสงสัยเหมือนกันว่า parameter มันต่างกับ attribute ตรงไหน ส่วนที่ต่างกันนอกจากเราไม่สามารถ set ค่าให้กับ parameter ได้แล้ว นอกนั้นหลักๆ เลยก็คือ parameter มันเก็บได้เฉพาะค่าที่เป็น String เท่านั้น แต่ attribute สามารถเก็บค่าที่เป็น object ใดๆ ก็ได้

จาก Class Diagram ก็จะเห็นว่า มี method ที่เกี่ยวกับ attribute (setAttribute(String, Object), getAttribute(String), removeAttribute(String), getAttributeName()) อยู่ใน 3 object ซึ่งก็คือ
  1. ServletContext
  2. HttpSession
  3. ServletRequest
นั่นก็หมายความว่า attribute จะอยู่ใน 3 scope คือ application, session และ request ซึ่งก็หมายถึง การเข้าถึง attribute ทั้ง 3 scope จะแตกต่างกันด้วย (นั่นหมายถึงการ ป้องกัน attribute เพื่อให้เป็น thread-safe ก็จะต้องแตกต่างกันด้วย)
  1. application scope - ทุก session ทุก servlet สามารถเข้าถึง attribute นี้ได้ทั้งหมด ดังนั้นถ้าต้องการจะทำให้เป็น thread-safe จะต้อง synchronize ที่ ServletContext เพื่อป้องกัน servlet ตัวอื่นๆ ที่จะเข้าถึงattribute ตัวนี้ได้
  2. session scope - attribute นี้ เข้าถึงได้จาก session เดียวกันเท่านั้น ดังนั้นการทำ thread-safe ก็จะต้อง synchonize ที่ HttpSession เพื่อให้เรียกใช้ตัวแปรใน session นั้นๆ ได้ทีละครั้งเท่านั้น
  3. request scope - ใช้ได้ภายใน request หนึ่งๆ เท่านั้น ตัวนี้เป็น thread-safe อยู่แล้ว ไม่ต้องทำไร สำหรับ servlet ที่ถูกเรียกใช้โดย forward หรือ include จะมี default attribute ซึ่ง container สร้างไว้เลยดังนี้

    ForwardInclude
    javax.servlet.forward.request_urijavax.servlet.include.request_uri
    javax.servlet.forward.context_pathjavax.servlet.include.context_path
    javax.servlet.forward.servlet_pathjavax.servlet.include.servlet_path
    javax.servlet.forward.path_infojavax.servlet.include.path_info
    javax.servlet.forward.query_stringjavax.servlet.include.query_string
    NB. ทั้งนี้เหมือนกับ method ของ HttpServletRequest คือ getRequestURI(), getContextPath(), getServletPath(), getPathInfo(), getQueryString()


Session

สำหรับการจัดการ session Object ที่เราต้องใช้หนักๆ เลยก็คือ HttpSession ซึ่งใน diagram จะ list ไว้เฉพาะ method ที่เราใช้กันบ่อยๆ ไว้แล้ว ส่วน Object อื่นๆ ที่เกี่ยวข้องกับการจัดการ session ก็คือ HttpServletRequest getSession() method ซึ่งที่เกี่ยวกับ session จริงๆ จะมีแค่นี้ค่ะ

โดยปกติแล้ว session จะใช้หลักการส่ง-รับ session id ระหว่าง server กับ client ซึ่งจะต้องใช้ cookie เป็นหลัก ดังนั้นถ้า client disable การับ cookie ไว้ การจัดการ session โดยวิธีนี้ก็จะใช้ไม่ได้ทันที ดังนั้นจะต้องมีวิธีอื่นเพื่อรองรับกรณี นั้นก็คือการ แปะ session id ไปกับ URL ซึ่งเราก็จะใช้ HttpServletResponse encodeURL(String) หรือ encodeRedirectURL(String) ในกรณีที่เป็น redirect URL เพื่อให้ container แปะ session id ให้เราโดยอัตโนมัติ


Cookies

Cookie เป็นส่วนหนึ่งที่ช่วยในการจัดการ session Object ที่เราใช้ก็คือ Cookie ซึ่งใน diagram ก็ list method ที่จะต้องใช้ไว้ให้แล้ว นอกจากนี้ ที่เราจะต้องใช้สำหรับ เพิ่ม cookie และ ดึงค่า cookie มาใช้ก็คือ HttpServletResponse addCookie(Cookie) และ HttpServletRequest getCookies() (ไม่มี method สำหรับการดึง cookie ตัวใดตัวหนึ่งออกมา เราจะต้องใช้การวนค่า array Cookie[] เพื่อดึงค่าที่ต้องการออกมาเอง)

สุดท้ายแถม Servlet Life Cycle ให้ฮับ



สำหัรบ HttpServlet service() method จะเรียก doGet(), doPost, etc. แ้ล้วแต่ request ที่ำได้รับยกเว้น CONNECT method ซึ่ง HttpServlet ไม่ support

Reference:
Web Application FAQ

Web: Content Type

Content type คือค่าที่บอกให้ browser รู้ว่าเนื้อหาที่ server ส่งกลับมาเป็นประเภทไหน เราอาจจะเคยเห็นว่าเืมื่อการคลิ๊ก pdf ไฟล์ browser บางตัว จะทำการเปิดไฟล์ pdf ในหน้า browser ให้เลย นั้นก็เพราะ browser รู้ว่าไฟล์เนื้อหานี้จะต้องจัดการอย่างไร เพื่อแสดงผลได้อย่างถูกต้อง โดย browser จะดูจาก content type (หรือบางครั้งก็ดูจาก นามสกุลของไฟล์) สำหรับข้อมูลบางประเภทที่ browser รู้จักและสามารถแสดงผลได้ มันก็จะแสดงผลให้ แต่สำหรับข้อมูลที่มันไม่สามารถจัดการได้ มันก็จะต้อง pop-up ให้เรา download ลงมาไว้ที่เครื่อง เพื่อเราจะได้นำไปใช้ต่อไป

โดย Content type ก็คือ MIME type นะเอง MIME หรือ Multipurpose Internet Mail Extensions ดูจากชื่อ ก็คงพอเดาได้นะค่ะ ว่า MIME ที่นำมาใช้ครั้งแรก เพื่อใช้ักับ e-mail สำหรับบอกว่าเนื้อหาของ e-mail เป็นรูปแบบไหน เพื่อให้ e-mail client สามารถแสดงผลได้ แต่มันก็ถูกขยายมาให้ใ้ช้เพื่อจุดประสงค์อื่นๆ ต่อมา เช่นการใช้เป็น Content type บน internet เพื่อระุบุ response ที่ server ตอบกลับมาเป็นต้น

ค่าของ MIME type หรือ Content type โดยทั่วไป เช่น

text/plain
text/html
multipart/mixed - text ผสมกับไฟล์แนบ ใช้สำหรับการ download หรือ upload ไฟล์ พร้อมกับแสดงผล HTML หรือ plain text
image/jpeg
image/jpg
audio/mp3
video/mp4
video/quicktime
application/pdf
application/java
application/jar
application/octet-stream
application/x-zip
application/msword


Reference:
MIME - Wikipedia

Servlet: Deployment Descriptor (DD)

DD ก็คือ XML ไฟล์ที่กำหนดการ deploy Servlet สำหรับ Web Container หรือ DD ก็คือ web.xml นะเอง

ตัวอย่างของ DD อย่างง่ายๆ
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <context-param>
    <param-name>param</param-name>
    <param-value>parameter value</param-value>
  </context-param>
  [ <context-param> ...parameter name-value pair as above... </context-param> ]

  <listener>
    <listener-class>package.class</listener-class>
  </listener>

  <session-config>
    <session-timeout>10</session-timeout>
  </session-config>

  <servlet>
    <servlet-name>Internal Name</servlet-name>
    <servlet-class>package.ServletClass</servlet-class> | <jsp-file>path/file.jsp</jsp-file>
    <load-on-startup>1<load-on-startup/>

    <init-param>
      <param-name>param</param-name>
      <param-value>parameter value</param-value>
    </init-param>
    [ <init-param> ...parameter name-value pair... <init-param> ]...

    <security-role-ref>
      <role-name>Manager</role-name>
      <role-link>Admin</role-line>
    </security-role-ref>
  </servlet>

  <servlet-mapping>
    <servlet-name>Internal Name</servlet-name>
    <url-pattern>/Public.do</url-pattern>
  </servlet-mapping>

  <jsp-config>
    <jsp-property-group>
      <url-pattern>*.jsp</url-pattern>
      <el-ignored>[ true | false ]</el-ignored>
      <scripting-invalid>[ true | false ]</scripting-invalid>
    </jsp-property-group>

    <taglib>
      <taglib-uri>randomThing</taglib-uri>
      <taglib-location>/WEB-INF/myFunctions.tld</taglib-location>
    </taglib>
  </jsp-config>

  <!-- filter config -->
  <filter>
    <filter-name>LogRequest</filter-name>
    <filter-class>package.Filter</filter-class>

    <init-param>
      <param-name>param</param-name>
      <param-value>parameter value</param-value>
    </init-param>
    [ <init-param> ...parameter name-value pair... <init-param> ]...
  </filter>

  <filter-mapping>
    <filter-name>LogRequest</filter-name>
    <url-pattern>/path/*</url-pattern> | <servlet-name>AnyRequest</servlet-name>
    <dispatcher> REQUEST | INCLUDE | FORWARD | ERROR </dispatcher>
    [ <dispatcher> REQUEST | INCLUDE | FORWARD | ERROR </dispatcher> ]...
  </filter-mapping>

  <!-- declare welcome file -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    [ <welcome-file>index.html</welcome-file> ]...
  </welcome-file-list>

  <!-- declare to catch all error, but you can change to catch only some exceptions -->
  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/ErrorPage.jsp</location>
  </error-page>

  <!-- This is another way to catch error by status code -->
  <error-page>
    <error-code>404</error-code>
    <location>/ErrorNotFound.jsp</location>
  </error-page>

  <!-- external resource related -->
  <resource-env-ref>
    <resource-env-ref-name>jms/StockQueue</resource-env-ref-name><resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
</resource-env-ref>
  <resource-ref>
    <res-ref-name>ECC</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth> APPLICATION | CONTAINER </res-auth>
    <res-sharing-scope> Shareable | Unshareable </res-sharing-scope>
  </resource-ref>

  <!-- EJB related -->
  <ejb-local-ref>
    <ejb-ref-name>JNDI lookup name (such as ejb/Customer)</ejb-ref-name>
    <ejb-ref-type> Entity | Session </ejb-ref-type>
    <local-home>package.Class</local-home>
    <local>package.Class</local>
  </ejb-local-ref>

  <ejb-ref>
    <ejb-ref-name>JNDI lookup name (such as ejb/Customer)</ejb-ref-name>
    <ejb-ref-type> Entity | Session </ejb-ref-type>
    <home>package.Class</home>
    <remote>package.Class</remote>
  </ejb-ref>

  <env-entity>
    <env-entry-name>JNDI lookup name (such as rates/discountRate)</env-entry-name>
    <env-entry-type>java.lang.Integer</env-entry-type>
    <env-entry-value>10<env-entry-value>
  </env-entity>

  <!-- mine-type mapping -->
  <mime-mapping>
    <extension>mgp</extension>
    <mime-type>video/mpeg</mime-type>
  </mime-mapping>

  <!-- constraint resource -->
  <security-constraint>

    <web-resource-collection>
      <web-resource-name>some name</web-resource-name>
      <description>explain about tht resource</description>
      <url-pattern>/Public.do</url-pattern>
      [ <url-pattern>/Path/resource</url-pattern> ]...

      <http-method>GET | POST | PUT | TRACE | DELETE | HEAD | OPTION</http-method>
      [ <http-method>GET | POST | PUT | TRACE | DELETE | HEAD | OPTION</http-method> ]...
    </web-resource-collection>

    <auth-constraint>
      <role-name>Admin</role-name>
      [ <role-name>Others</role-name> ]...
    </auth-constraint>

    <user-data-constraint>
      <transport-guarantee> NONE | INTEGRAL | CONFIDENTIAL </transport-guarantee>
    </user-data-constraint>
  </security-constraint>

  <!-- authorization path to define role -->
  <security-role><role-name>Admin</role-name></security-role>
  [ <security-role><role-name>Admin</role-name></security-role> ]...

  <login-config>
    <auth-method>BASIC | DIGEST | CLIENT-CERT | FORM</auth-method>
    <form-login-config>
    <form-login-page>/loginPage.html</form-login-page>
    <form-error-page>/loginPage.html</form-error-page>
    </form-login-config>
  </login-config>

</web-app>

context-param เป็นค่าที่กำหนดไว้สำหรับทั้ง application
listener เป็นตัวกำหนดว่าใน application ของเรามี listener อะไรบ้าง


Servlet Configuration

session-timeout กำหนดระยะเวลาที่ session inactive กี่นาที ก่อนจะหลุด session จากตัวอย่างข้างบน คือ ถ้า session inactive 10 นาที ก็จะหลุด ถ้าใส่ 0 หมายถึงให้ time out ทันมี (เสมือนเรียก HttpSession invalidate())
servlet-name ใน servlet เป็นชื่อที่ใช้ใน DD เพื่อเชื่อกับ servlet-name ใน servlet-mappping
servlet-class เป็น Servlet class ที่เราเขียนขึ้นมาเพื่อให้มัน process อะไรสักอย่างสำหรับเวปเรา
jsp-file เป็นชื่อไฟล์ jsp ที่เราต้องการใส่แทน servlet class โดยปกติ jsp สามารถแสดงผลได้โดยไม่ต้องใ่ส่ใน deployment descriptor ก็ได้ แต่เราจะใส่ในกรณีที่เราต้องการ config เพิ่มเติม เช่นต้องการกำหนดค่า init-param แต่ในกรณีที่เราเขียน jsp-file tag แล้ว จะต้องไ่ม่มี servlet-class tag อีก
load-on-startup เป็นการบอกว่าจะให้ servlet นั้นๆ ทำการ load ตั้งแต่ตอน deploy หรือไม่ (เพื่อเป็นการย่นระยะเวลาในการเรียกใช้ของผู้ใช้ในครั้งแรก)

init-param เป็นค่าที่กำหนดไว้สำหรับ servlet นั้นๆ ซึ่งสามารถมี init-param tag ได้มากกว่า 1 ตัวสำหรับหลายๆ parameter

servlet-mapping กำหนดค่ารูปแบบ url ที่จะใช้เรียก servlet ซึ่งลำดับในการ map จะใช้เป็น exact match (คือจะต้องถูกต้องตรงกับ url-pattern ทั้งหมด), directory match (เช่น url-pattern เป็น /test/*) สุดท้ายคือ extension match (เช่น *.do)
url-pattern เป็น URL pattern สำหรับ คนภายนอกที่จะเรียกใช้ ทั้งนี้เราสามารถเขียนเป็น pattern ซึ่งทุก URL ที่ตรงกับ pattern ที่กำหนดจะใช้ Servlet class ตัวเดียวกัน

JSP Configuration

el-ignored กำหนดให้ EL ทำงานหรือไม่ ถ้าเป็น true คือไ่ม่ให้ทำงาน
scripting-invalid กำหนดให้ JSP สามารถใส่ scriptlet ได้หรือไม่

taglib เป็นการกำหนด location ของ Tag Library Descriptor ซึ่งใช้สำหรับก่อน JSP 2.0 ซึ่งจำเป็นต้องบอก location ที่ให้กับ web container แต่ตั้งแต่ JSP 2.0 เป็นต้นไป ไม่จำเป็นต้องมากำหนดใน DD แล้ว web container สามารถหาได้จากการ map ไฟล์ .tld ทุกไฟล์ที่อยู่ใน WEB-INF รวมถึง META-INF ใน jar ไฟล์ แต่ถ้ามีการกำหนดค่าไว้ใน DD และถึงแม้จะเป็น JSP 2.0 web container ก็จะใช้ตัวที่กำหนดไว้ใน DD เท่านั้น

Filter Configuration

Web container จะเรียง filter ตามลำดับที่ปรากฎใน Deployment descriptor โดยจะเลือกที่ map โดย url-pattern ก่อน servlet-name

Error Configuration
exception-type เป็น Class ที่ต้องการจะดักเพื่อให้ redirect ไปยัง error page
error-code นอกจากจะดักเป็น Exception class แล้ว ก็สามารถดักเป็น status code ได้
location เป็น relative location ของ error page

EJB Configuration

env-entry-type จะต้องเป็น Class เท่านั้น เป็น primitive type ไม่ได้

Security Configuration

ส่วนนี้เป็นแยกเป็นส่วนที่เกี่ยวกับ Authorization และ Authentication ซึ่งจะต้องใช้ร่วมกับ web container แต่ละตัว ซึ่งแต่ละียี่ห้อก็จะแตกต่างกัน เช่น Tomcat ใช้การ config ไว้ที่ไฟล์ conf/tomcat-users.xml

ส่วนที่เกี่ยวกับ Authorization จะเป็นการกำหนดว่า resource ไหน จะถูกจำกัดด้วย role ใด โดยวีธีใดบ้าง

security-constraint เป็นส่วนที่กำหนดว่า resources หรือไฟล์ไหนและ method ไหนบ้างที่จะต้องมี constraint กำหนดไว้ เช่น
url-pattern เป็น resource ที่ถูกกำหนดว่าจะต้องมี constraint ซึ่ง กำหนดเป็นไฟล์ใดไฟล์หนึ่ง หรือว่ากำหนดเป็น path ก็ได้ (ในกรณีนี้จะเป็น /path/*) หรือกำหนดเป็น pattern เช่น /path/*.do ก้ได้ แต่อย่างไรก็ตามจะต้องกำหนดอย่างน้อย 1 resouce
auth-contraint เป็นตัวกำหนดว่า resource เหล่านี้จะมี constraint ที่ method ไหนบ้าง ซึ่งจะใช้ได้กับทั้ง resource ใน web-resource-collection

ส่วนถัดมาเป็น Authentication เป็นส่วนกำหนดว่าจะมี role ในบ้าน โดยวีธีการ authentication แบบใด
security-role และ role-name เป็นตัวกำหนดว่าจะมี role อะไรบ้าง

สำหรับโครงสร้างในการ deploy web application จะเป็นดังนี้


Reference:

COBOL: structure

สำหรับ COBOL ใน Mainframe จะต้องมีโครงสร้าง column เข้ามาร่วมด้วย ดังนี้

  1. column 1-6 เป็น sequence number
  2. column 7 ไว้ใส่ตัวอักษรที่มีความหมายพิเศษ
    • * แสดงว่าบรรทัดนั้นเป็น comment
    • - แสดงว่าบรรทัดนี้ต่อมาจากบรรทัดข้างบน
  3. column 8-11 เป็น area A ซึ่งไว้ใส่ division ในโปรแกรม
  4. column 12-72 เป็น area B ไว้ใส่ code อื่นๆ นอกจาก division
  5. column 73-80 เป็น optional ที่แสดง program identification or comments
ซึ่งโครงสร้างด้านล่าง จะละ column 1-7 ไว้ (เนื่องจากไม่ได้ใส่ comment) code จะเริ่มที่ column 8 เป็นต้นไป


IDENTIFICATION DIVISION.
PROGRAM-ID
ProgName.
[AUTHOR
Desc.]
[INSTALLATION
Desc.]
[DATE-WRITTEN
Desc.]
[DATE-COMPILED
Desc.]
[SECURITY
Desc.]

[
ENVIRONMENT DIVISION.

[INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT
FileName
[ASSIGN [TO] DISK|PRINTER.]
[ORGANIZATION IS SEQUENTIAL|LINE SEQUENTIAL|RELATIVE|INDEXED.]
[ACCESS MODE IS SEQUENTIAL|RANDOM|DYNAMIC.]]]

DATA DIVISION.
[FILE SECTION.
FD
FileName [RECORD MODE [IS] BINARY|DECIMAL LOW|HIGH|HYPER DENSITY]
LABEL RECORD|RECORDS IS|ARE STANDARD|OMITTED
[VALUE OF FILE-ID IS [
DataName |Literal ]
[BLOCK CONTAINS
Integer CHARACTERS|RECORDS]
[RECORD CONTAINS
Integer CHARACTERS]
[DATA RECORD IS|RECORDS ARE
DataName1[, DataName2, ...]]

[
LevelNo DataName |FILLER
[REDEFINES
DataName ]
[PIC|PICTURE [IS]
Pattern ]
[OCCURS [
Interger TO] Integer TIMES
[DEPEND ON
DataName1 ]
[ASCENDING|DESCENDING [KEY] [IS]
DataName2 [, DataName3, ...]]
[INDEXED [BY]
IndexName1 [, IndexName2, ...]]
[RENAMES
DataName [THRU DataName2 ]]
[VALUE [IS|ARE]
Literal1 [THRU Literal2 ] [Literal3 [THRU Literal4]] ...
[JUST|JUSTIFIED RIGHT]
[SIZE [IS]
Integer CHARACTERS|DIGITS]
[CLASS [IS] NUMERIC|ALPHABETIC|ALPHANUMERIC]
[USAGE [IS] COMP|COMPUTATIONAL 1|COMP-1|COMPUTATION-1|DISPLAY|INDEX]
[BLANK WHEN ZERO]]

WORKING-STORAGE SECTION.
[77
DataName PIC|PICTURE [IS] Pattern.]
...
[
LevelNo DataName |FILLER
[REDEFINES
DataName ]
[PIC|PICTURE [IS]
Pattern ]
[OCCURS [
Interger TO] Integer TIMES
[DEPEND ON
DataName1 ]
[ASCENDING|DESCENDING [KEY] [IS]
DataName2 [, DataName3, ...]]
[INDEXED [BY]
IndexName1 [, IndexName2, ...]]
[RENAMES
DataName [THRU DataName2 ]]
[VALUE [IS|ARE]
Literal1 [THRU Literal2 ] [Literal3 [THRU Literal4]] ...
[JUST|JUSTIFIED RIGHT]
[SIZE [IS]
Integer CHARACTERS|DIGITS]
[CLASS [IS] NUMERIC|ALPHABETIC|ALPHANUMERIC]
[USAGE [IS] COMP|COMPUTATIONAL 1|COMP-1|COMPUTATION-1|DISPLAY|INDEX]
[BLANK WHEN ZERO]]
...

[LINKAGE SECTION.
[77
DataName PIC|PICTURE [IS] Pattern.]
...
[
LevelNo DataName |FILLER
[REDEFINES
DataName ]
[PIC|PICTURE [IS]
Pattern ]
[OCCURS [
Interger TO] Integer TIMES
[DEPEND ON
DataName1 ]
[ASCENDING|DESCENDING [KEY] [IS]
DataName2 [, DataName3, ...]]
[INDEXED [BY]
IndexName1 [, IndexName2, ...]]
[RENAMES
DataName [THRU DataName2 ]]
[VALUE [IS|ARE]
Literal1 [THRU Literal2 ] [Literal3 [THRU Literal4]] ...
[JUST|JUSTIFIED RIGHT]
[SIZE [IS]
Integer CHARACTERS|DIGITS]
[CLASS [IS] NUMERIC|ALPHABETIC|ALPHANUMERIC]
[USAGE [IS] COMP|COMPUTATIONAL 1|COMP-1|COMPUTATION-1|DISPLAY|INDEX]
[BLANK WHEN ZERO]]
...]

[SCREEN SECTION.
LevelNo [ScreenName] [BLANK-SCREEN]
[LINE [NUMBER] [IS] [PLUS]
Integer]
[LINE [NUMBER] [IS] [PLUS] Integer]
[BLANK LINE]
[BELL] [HIGHLIGHT|BLINK]
[VALUE [IS] Literal | PIC|PICTURE [IS]
Pattern FROM Literal2 | Identifier1 |TO Identifier2 |USING Identifier3
[BLANK WHEN ZERO]
[JUST|JUSTIFIED RIGHT]
[AUTO]
[SECURE]]

PROCEDURE DIVISION.

ParagraphName1.
Statement.
....

JCL Overview

JCL (Job Control Language) เป็น programming language ที่ใ้ช้ในการควบคุมการทำงานบน Mainfram JCL จะถูก interpret และำ execute โดย JES (Job Entry Subsystem) ฮับ ซึ่งเป็น subsystem ของ MVS อีกที ดังนั้นก่อนจะรู้จัก JCL เรามาทำความรู้จักกับ MVS กันคร่าวๆ กันก่อน

โครงสร้าง JCL จะประกอบไปด้วย
  1. // ทุกบรรทัีดของ JCL จะเริ่มต้นด้วย // ซึ่งบรรทัดไหนที่ไม่มี // ขึ้นต้น อาจจะเป็นส่วนของ data หรือว่าคำสั่งพิเศษ ที่ใช้กับ software อื่นๆ
  2. job name เริ่มต้นที่ column 3 JCL name สามารถยาวได้ 8 ตัวอักษร และสามารถประกอบด้วยตัวอักษร และตัวเลข และอักขระพิเศษอื่นๆ เช่น @, $, # แต่ไม่สามารถใช้ - หรือขึ้นต้นด้วยตัวเลขได้
  3. JCL operator เริ่มต้นได้ตั้งแต่ column 4 ซึ่งมีด้วยกัน 3 ตัว คือ JOB, EXEC และ DD
    • JOB จะถูกใช้เป็น statement แรก ที่ใช้ระบุข้อมูลของ job นั้นๆ
    • EXEC เป็น operator ที่ใช้ใันแต่ละ step ของแต่ละ job เป็นตัวบอกว่า ในแต่ละ step จะต้อง execute อะไร
    • DD (Data Definition) เป็น operator ที่ระบุที่อยู่ของข้อมูล และลักษณะของข้อมูล ที่จะใช้ในการ process ของ step นั้นๆ
  4. JCL parameter ซึ่งแล้วแต่ JCL Operator ที่ใช้ สำหรับในกรณีที่ parameter เยอะ สามารถขึ้นบรรทัดใหม่ได้ แต่ปิดบรรทัดด้วย , และจะต้องเริ่มต้นที่ column 4-16 เท่านั้น (โดยที่ column แรกยังคงต้องเป็น //) parameter ที่ใส่ใน JCL สามารถใช้แบบตามตำแหน่ง คือจะต้องใส่ให้เีรียงกันไปตามตำแหน่งให้ถูกต้อง หรือว่าจะใส่โดยใช้ parameter name เป็นตัวบอกและใส่ = ต่อท้ายก็ได้ ซึ่งโดยปกติก็จะนิยมแบบหลังมากกว่า เพราะว่า parameter ค่อยข้างเยอะ จำได้ยากว่าจะต้องตัวไหนมาก่อนมาหลัง
  5. อาจจะปิดท้ายด้วย sequence number 8 ตัว ซึ่งอาจจะมีหรือไม่มีก็ได้ เป็น optional ดังนั้น JCL name, operator และ parameter จะอยู่ใน column 3 - 71 เท่านั้น

สำหรับคนที่ีไม่ชินกับ Mainframe อาจจะไม่เข้าใจว่า column ที่ว่าคืออะไร มันก็คือ text ตัวที่เท่าไรในบรรทัดนั้นๆ นะเอง ใน editor บางตัวเราจะเห็นได้จาก status bar ที่โชว์ว่า ณ.ขณะนี้ cursor เราอยู่ที่ บรรทัดอะไร column อะไร ซึ่ง programming language ใน Mainframe ส่วนใหญ่จะต้องอิงตาม column และจะ้ต้องใช้ให้ถูกด้วย ม่ะงั้นมันจะ compile ไม่ผ่าน

ตัวอย่าง JCL ฮับ Job นี้ชื่อว่า IS198CPY มี step เดียวชื่อ COPY01 และก็มี parameter มากมายโดยใช้คู่กับ parameter name

//IS198CPY JOB (IS198T30500),'COPY JOB',CLASS=L,MSGCLASS=X
//COPY01 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=OLDFILE,DISP=SHR
//SYSUT2 DD DSN=NEWFILE,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(40,5),RLSE),
// DCB=(LRECL=115,BLKSIZE=1150)
//SYSIN DD DUMMY

Comment ใน JCL จะใช้ มี 2 แบบ
  1. all line comment จะใช้ //* ขึ้นต้น และ มันจะ ignore ข้อความหลังจากนั้นทั้งบรรทัด
  2. หรือ ถ้าเราเว้น space ด้านหลังของ parameter ก็จะถือเป็น comment เหมือนกัน ซึ่งนั้นก็หมายความว่า parameter ด้านหลังทั้งหมดจะต้องติดกัน ห้ามเว้น space เลยฮับ มิฉะนั้น parameter นั่นจะหายไปเลย... แง๊ว
แต่ถ้าเราใส่ // โดยไม่มี * จะหมายถึง หยุดการ process ทั้งหมดแค่นี้

JCL จะถูกอ่านโดย JES2 (subsystem หนึ่งของ MVS) เพื่อเช็ค syntax และเปลี่ยนให้เป็นงานที่อยู่ในคิว โดยงานแต่ละคิว จะถูกแบ่งตาม Class และ initiator จะเป็นตัวจัดการกับงานที่อยุ่ในคิวต่างๆ อีกที โดยเลือกงานตามลำดับความสำคัญ และ กำหนด I/O ตามที่งานนั้นต้องการ โดยใช้ MVS Service ช่วยอีกที

Reference:
Job Control Language - Wikipedia
JCL Study Material

Computer history ฉบับย่อ

ทุกวันนี้คนใ้ช้คอมพิวเตอร์กันเป็นเรื่องปกติ แต่จริงๆ แล้วก่อนหน้านี้คอมพิวเตอร์ไม่ได้หน้าตาแบบนี้ หุ่นเพียวบางแบบนี้ และคอมพิวเตอร์เครื่องหนาๆ เป็นตู้เสื้อผ้า ก็ยังคงมีใช้กันอยู่ในบางที่ กับบางงาน และเมื่อเราต้องเผชิญหน้ากับชื่อและคำศัพท์พวกนี้ เราก็มักจะงงว่าอะไรมันเป็นอะไรกันแน่ สรุปมาให้เห็นแบบสั้นๆ ง่ายๆ (เพราะว่า ยากๆ ก็ไม่รู้เหมือนกัน) แบบนี้



MainframeMinicomputerWorkstation (RISC)
1964-IBM System/360
1970-IBM System/370
1978-
IBM System/34
1980-
IBM System/38
1983-
IBM System/36
1986-

Sun SPARC
1988-
AS/400
late 1980s-

RISC System/6000 หรือ RS System/6000
1990-IBM System/390
mid 1990s-

DEC Alpha
2000-IBM eServer zSeriesIBM eServer iSeriesIBM eServer pSeries
2006-IBM System z (z Series)IBM System i
2008-

IBM System p

*ตัวที่ใส่ตัวหนาไว้ จะเป็นรุ่นที่ได้รับความนิยมอย่างมาก และมีการใช้กันแพร่หลาย ซึ่ง เป็นชื่อที่ให้เรียกกันมาจนถึงทุกวันนี้ อย่างเช่น AS/400 ข้อสังเกตุอีกอย่างหนึ่งก็คือ SUN ได้รับความนิยมจากเครื่อง workstation มากกว่า IBM

AS/400 มักจะมีคนสับสนกับเครื่อง mainframe แต่จริงๆ แล้วมันเป็นเครื่อง minicomputer ที่ IBM ผลิตขึ้นมา เมื่อกระแสความต้องการคอมพิวเตอร์ที่มีราคาถูกลง เครื่องเล็กลง ประสิทธิภาพอาจจะไม่เท่า Mainframe แต่ก็เพียงพอต่อความต้องการ จนกระทั่งมาถึง PC ซึ่งเป็น architecture แบบ CISC ซึ่งเกิดขึ้นมาพร้อมๆ กับ RISC บน workstation แต่ CISC สามารถผลิตได้ถูกกว่า เครื่อง CISC แรกๆ ก็คือ chip ตระกูล x86 เช่น 386, 486 เดิม ของ Intel

แม้ว่าเครื่อง mainframe และ minicomputer จะถูก IBM ครองตลาด แต่สำหรับเครื่อง workstation ซึ่งเป็น RISC กลับมีผู้ผลิตหลายรายที่ผลิตชิพของตัวเองและ design workstation ขึ้นมาขายแข่งกับ IBM ด้วย อย่างเช่น Sparc ของ Sun Microsystem ซึ่งค่อยข้างดัง และยังมี Alpha ของ DEC (Digital Equipment Corporation) ด้วย

นอกจากคำศัพท์ประเภทเครื่อง และรุ่น ของคอมพิวเตอร์แล้ว OS ก็อีกเป็นปัจจัยหลักที่มาคู่กับเครื่องคอมพิวเตอร์ ซึ่งบางครั้งเราก็จะได้ยิน คนเรียกชื่อ OS แทนชื่อเครื่อง แล้วก็ทำให้เราสับสนไปกันใหญ่ (ไม่รู้คนอื่นจะสับสนเหมือนกันหรือเปล่า) ว่ามันเป็นเครื่องรุ่นใหม่ แบบใหม่ หรืออย่างไร

MVS เกิดขึ้นไปปี 1974 ใชักับเครื่อง IBM System/370 และ System/390
OS/390 เกิดขึ้นมาปี 1995 นำมาใช้บน IBM System/390 แทน MVS
z/OS เป็นการ re-brand OS/390 เดิม ตามเครื่อง IBM System z

อย่างไรก็ตาม OS/390, z/OS หรือ OS อื่นๆ ที่ใช้กับเครื่อง mainframe ก็ยังมี core เป็น MVS จึงเป็นคำเรียกติดปากของคนทั่วไป เหมือนกับที่เราเรียก Redhat เป็น Linux

OS/400 เกิดขึ้นปี 1988 พร้อมกับ AS/400 ที่ใช้ร่วมกัน ซึ่งภายหลังได้ rename เป็น i5/OS และ IBM i ตาม IBM System i

AIX เป็น OS ที่ใช้บน IBM Workstation หรือเริ่มต้นใช้กับ System/6000 ซึ่งพัฒนามาจาก UNIX System V และ 4.3 BSD-compatible
OpenVMS เป็น OS สำหรับเครื่อง Alpha

นอกจากชื่อ computer ประเภทและรุ่นต่างๆ แล้ว ยังมีระบบคอมพิวเตอร์ที่เคยโด่งดังในสมัยหนึ่ง ของบริษัท Tandem Computers, Inc. ซึ่งใช้ชื่อบริษัทเป็นชื่อของระบบคอมพิวเตอร์ที่ออกแบบขึ้นโดยใช้แนวคิดแบบ fault-tolerant ซึ่งเป็นระบบที่สามารถรองรับงานได้ 24 ชม. ตลอดทั้งปี โดยออกแบบมาให้มีการรองรับ failure ที่จะเกิดขึ้นทั้งใน software และ hardward (ในขณะที่ mainframe จำเป็นจะต้องมีความเวลาในการ maintenence ซึ่งจะต้องหยุดระบบงานที่มีอยู่ทั้งหมด อย่างน้อย 1 ครั้งต่อปี และเป็นที่มาของวันหยุดธนาคารกลางปีนะเอง) ระบบของ Tandem ที่ออกมาตัวแรก ในปี 1975 ชื่อ Tandem-16 หรือ T/16 (ต่อมาเปลี่ยนชื่อเป็น NonStop I) ซึ่งออกเพื่อรองรับการทำงาน OLTP (On-Line Transaction Processing) ของธนาคาร ระบบ Tandem จะใช้ custom OS (เนื่องจากต้องมีการจัดการเรื่อง failure) โดย OS ตัวแรกชื่อ T/TOS และหลังจากนั้นระบบของ Tandem ก็แพร่หลายออกไป จนในปี 1997 บริษัท Compaq ก็ได้มาซื้อบริษัท Tamdem ไป

Reference:
Wikipedia
Tamdem - Wikipedia
Computer History Museum


TCP: default port

port number ก็คือเลข 16-bit (0 - 65535) ที่ใช้บอก application ที่จะใช้

เนื่องจากในการส่งข้อมูลภายใน internet (หรือเครือข่ายที่ใช้ TCP protocol) นั้นสามารถนำไปใช้กับ application ได้หลากหลาย ซึ่งแต่ละ application ก็สามารถใช้ protocol ที่แตกต่างกันออกไปในการตีความข้อมูลที่ส่งไป-มาใน network เช่น เราส่ง HTML โดยใช้ protocol HTTP หรือการส่งไฟล์โดยใช้ protocol FTP เป็นต้น ดังนั้นเพื่อจะบอก server ได้ว่าข้อมูลที่ส่งมานั้นเป็น application อะไร จะต้องใช้ protocol ตัวไหน จึงต้องมีการกำหนดหมายเลข port ขึ้นมา

ทั้งนี้ทั้งนั้น ตอนที่เรา config application เราสามารถกำหนดได้เองว่า จะใช้ application นั้นๆ ใช้ port หมายเลขอะไร แต่โดยทั่วไปแล้ว application ซึ่งเป็นที่รู้จักกันโดยทั่วไปจะมี ค่า default ของ application นั้นๆ อยู่ เช่น

port 21 เป็น FTP
port 22 เป็น SSH
port 23 เป็น Telnet
port 25 เป็น SMTP
port 80 เป็น HTTP
port 110 เป็น POP3
port 443 เป็น HTTPS

นอกจากนี้ยังมี applicatoin อื่นๆ อีก ซึ่ง port 0 - 1023 จะถูกสำรองไว้สำหรับ application ที่เป็นที่รู้จักเหล่านี้ ดังนั้นถ้าเรามีการสร้าง application ของเราเองที่ใช้อยู่บน TCP ก็ควรจะหลีกเลี่ยงการใช้ port เหล่านี้

HTTP and HTML introduction and architecture

อย่างที่เรารู้กันว่า เราส่ง HTML ไปด้วย protocol HTTP โดย HTML นั้นจะถูกหุ้มด้วย HTTP header อีกทีหนึ่ง ซึ่งตัว header ที่ว่านี้ก็อาจจะแตกต่างกันไปเล็กน้อยแล้วแต่ HTTP method

เช่น Get request method


GET /select/selectBeerTaste.jsp?color=dark&taste=malty
HTTP/1.1 Host: www.wickedlysmart.com
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/ 20030624 Netscape/7.1
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/ plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-aliv
e



หรือ Post request method

POST /advisor/selectBeerTaste.do HTTP/1.1
Host: www.wickedlysmart.com
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4) Gecko/ 20030624 Netscape/7.1
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/ plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive


color=dark&taste=malty

ข้อแตกต่างของ get กับ post ที่เห็นได้ชัดๆ ก็คือ post จะสามารถมี body ได้ (บรรทัดสุดท้าย color=dark... คือส่วนของ body) โดย get method จะส่ง parameter ตามหลัง URL เลยทำให้ไม่สามารถส่งค่าที่มีความยาวมากๆ ได้ แต่ว่า post จะส่งโดยผ่าน body ทำให้มีความยาวได้ไม่จำกัด

นอกจาก post และ get แล้ว ยังมี HTTP method อื่นๆ อีก ดังนี้ HEAD, TRACE, OPTIONS, PUT,
DELETE และ CONNECT

ดูในส่วนของ request ไปแล้ว ทีนี้มาดูตัวอย่างของ response ที่ server ตอบกลับไปที่ client กันบ้าง


HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=0AAB6C8DE415E2E5F307CF334BFCA0C1; Path=/testEL
Content-Type: text/html
Content-Length: 397 Date: Wed, 19 Nov 2003 03:25:40 GMT Server: Apache-Coyote/1.1 Connection: close
<html>
...
</html>



ด้านล่างก็เป็นส่วน body ของ respond ซึ่งโดยส่วนใหญ่ก็จะเป็น HTML ที่นำมาแสดงในหน้า browser กันนะเอง โดย browser จะอ่าน message ในส่วนของ body และตีความและแสดงให้เราเห็น ดังนั้นเราจึงมี HTML standard ที่กำหนดว่า tag อะไรจะต้องแสดงผลแบบไหน ซึ่ง browser แต่ละ version ก็จะมีการบอกไว้ว่าตัวนี้ comply กับ HTML version อะไร ก็คือเป็น standard version นะเอง