October 15, 2013

Injection

Injection သည် ပုံမှန်အားဖြင့် ဆေးထိုးခြင်းဟု အဓိပ္ပါယ်ရပြီး၊ Java EE ဘာသာရပ်တွင်မှု Object တစ်ခု အတွင်း ပြင်ပမှ လိုအပ်ချက်များအား ထိုးသွင်းပေးခြင်းဟု အဓိပ္ပါယ်ဖြင့် အသုံးပြုပါသည်။ Java EE 7 တွင် Injection လုပ်ပေးနိုင်သော Injection Mechanism နှစ်မျိုးရှိကြပါသည်။ ၎င်းတို့မှာ Resource Injection နှင့် Dependency Injection တို့ဖြစ်ကြ၏။

Java EE ၏ Injection Mechanism အား အသုံးပြုခြင်းအားဖြင့် အသုံးပြုနေသော Object အတွင်းရှိ Resource များ၊ Dependency များအား instantiate လုပ်စရာမလိုပဲ အသုံးပြုနိုင်မည် ဖြစ်သည်။ အသုံးပြုလိုသည့် Dependency များနှင့် Resource များအား Class အတွင်းတွင် Declare လုပ်ထားပြီး၊ Inject လုပ်လိုသည့် Injection Point (Fields သို့မဟုတ် Methods) တွင် Annotation အား ရေးသားရန် လိုအပ်ပါသည်။ Injection အား အသုံးပြုလိုသည့် Class အား အလုပ်လုပ်စေသည့် အချိန် (Runtime) တွင် Container မှ လိုအပ်သည့် Object များအား Create လုပ်ကာ ဖြည့်စွက်ပေးမည် ဖြစ်သည်။ Injection အား အသုံးပြုခြင်းအားဖြင့် သင်၏ Code များအား ရိုးရှင်းစွာ ရေးသားနိုင်မည် ဖြစ်ပြီး၊ Resources များနှင့် Dependencies များအား instantiate လုပ်စရာမလိုအပ်တော့သောကြောင့် ၎င်းတို့နှင့် ချုပ်နှောင်မှု့ကို နည်းပါးစေမည် ဖြစ်ပါသည်။

Context Dependency Injection အခန်းတွင် အသေးစိတ် ဖော်ပြသွားမည် ဖြစ်သော်လည်း ယခု တစ်ခေါက်တွင်မှု အခြေခံ သဘောတရားများအား မိတ်ဆက်သွားပါမည်။


Resource Injection

Resource Injection အား အသုံးပြုခြင်းအားဖြင့် Container Manage Object များဖြစ်ကြသော၊ Servlets များ၊ Enterprise Java Bean များနှင့် Manage Bean များအတွင်းသို့၊ JNDI Namespace အတွင်းရှိ အသုံးပြုနိုင်သော Resource များအား Inject လုပ်ပေးနိုင်မည် ဖြစ်သည်။ ဥပမာအားဖြင့် JNDI Namespace အတွင်းရှိ Datasource များ၊ Connections များနှင့် အခြားသော Custom Resource များအား Resource Injection အားအသုံးပြု၍ Inject လုပ်နိုင်မည် ဖြစ်သည်။

Inject လုပ်မည့် Resource Object အား Reference လုပ်မည့် Type အဖြစ် Interface အား အသုံးပြုမည် ဖြစ်ပါသဖြင့်၊ Resource Class များအား ကိုယ်တိုင်ရေးသားစရာမလိုအပ်ပဲ Business Logic Code များနှင့် Resource Class ၏ Code များအတွင်းရှိ ချုပ်နှောင်မှု့ကို နည်းပါးစေမည်ဖြစ်ပါသည်။

နမှုနာအနေဖြင့် ပြီးခဲ့သော တစ်ခေါက်က ရေးသားခဲ့သော Resource အား Inject လုပ်၍ အသုံးပြုကြည့်ပါမည်။

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 version="3.1">
 <display-name>Test</display-name>
 <resource-env-ref>
  <resource-env-ref-name>jdbc/ygndb</resource-env-ref-name>
  <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
 </resource-env-ref>
</web-app>

ShopServlet.java
package com.dtc.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet("/ShopServlet")
public class ShopServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Resource(name="jdbc/ygndb")
    private DataSource ds;
    
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        
        try(Connection conn = ds.getConnection(); 
                PrintWriter writer = response.getWriter()) {
            System.out.println("Servlet is called;");
            Statement stmt = conn.createStatement();
            ResultSet result = stmt.executeQuery("select * from shop limit 10");
            writer.write("<h2>Shop List</h2>");
            writer.write("<ul>");
            while(result.next()) {
                writer.write("<li>");
                writer.write(result.getString("name"));
                writer.write("</li>");
            }
            writer.write("</ul>");
            writer.flush();
            writer.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

အထက်ပါအတိုင်း web.xml တွင် Server ပေါ်တွင် Config လုပ်ထားသော Resource အား Declare လုပ်၍  Servlet အတွင်းမှ @Resource Anotation အား အသုံးပြု၍ ရေးသားနိုင်မည် ဖြစ်သည်။



Dependency Injection

Object A အတွင်း အခြားသော Object B အား ခေါ်ယူအသုံးပြုနေသည် ဆိုပါက Object A သည် Object B အား မှီခိုနေသည်ဟု ဆိုနိုင်ပါသည်။ တနည်းအားဖြင့်ဆိုသော် Object B သည် Object ၏ Dependency ဖြစ်၏။ Java EE ပတ်ဝင်းကျင်တွင် Dependency Injection အား အသုံးပြုခြင်းအားဖြင့်၊ ပုံမှန် Java Class တစ်ခုအား ပတ်ဝင်းကျင်ပေါ်တွင် Manage လုပ်ထားသော Object အဖြစ်ပြောင်းလည်းပြီး၊ လိုအပ်သည့်အခြားသော Managed Object တစ်ခုအတွင်းတွင် Inject လုပ်ပေးနိုင်ပါသည်။ ဤကဲ့သို့ Dependency Injection အား အသုံးပြုခြင်းအားဖြင့် Managed Class တစ်ခုအတွင်းရှိ Dependency များအား Declare လုပ်ရုံဖြင့် အသုံးပြုနိုင်မည် ဖြစ်ပါသည်။ Java EE Container သည် အဆိုပါ Dependency များအား Run Time အချိန်တွင် အလိုအလျှောက် ဖြည့်စွက်ပေးမည်ဖြစ်ပြီး၊ ၎င်းတို့၏ Life Cycle ကိုလည်း Developer များကိုယ်စား ထိမ်းသိမ်း ပေးနိုင်မည် ဖြစ်ပါသည်။

Java EE ၏ Dependency Injection အားအသုံးပြုရာတွင် Scope များအား သတ်မှတ်ရန်လိုအပ်ပြီး၊ ၎င်းသည် Inject လုပ်မည့် Object ၏ Life Cycle အား Manage လုပ်ရာတွင်အသုံးပြုပြီး၊ Container မှ အဆိုပါ Object အား Instantiate လုပ်မည့် အချိန်အား ဆုံးဖြတ်ရာတွင် အသုံးပြုပါသည်။ ဥပမာအားဖြင့် Client များဆီမှ Request တစ်ခုတည်းကိုသာ အလုပ်လုပ်ရန်လိုသော Manage Object သည် Scope များစွာတွင် အလုပ်လုပ်နိုင်ပြီး၊ Client တစ်ခုတည်းနှင့် Session ထဲတွင် အလုပ်လုပ်ရန် လိုအပ်သော Object သည် Section Scope တစ်ခုအတွင်းမှာသာ အလုပ်လုပ်နိုင်မည် ဖြစ်ပါသည်။ အဆိုပါ Session Scope အထဲတွင် အလုပ်လုပ်မည့် Object အား အခြားသော Client အတွက် အလုပ်လုပ်ရန် လိုအပ်ပါက အခြားသော Object တစ်ခုအား Instantiate လုပ်ပေးရန် လိုအပ်မည်ဖြစ်ပါသည်။

လက်တွေ့ Inject လုပ်မည့် နမှုနာတစ်ခုအား ရေးသားကြည့်ပါမည်။ ဤနမှုနာတွင် Kg မှ Pound အားပြောင်းပေးနိုင်သော Manage Object တစ်ခုအား ရေးသား၍ ၎င်းအား JSF ၏ Backing Bean အတွင်းမှခေါ်ယူ အသုံးပြုကြည့်ပါမည်။

ဦးစွာ Injection လုပ်မည့် Object အတွက် Class အား အောက်ပါအတိုင်း ရေးသားပါမည်။

PoundConverter.java
package com.dtc.di;

import javax.enterprise.context.RequestScoped;


@RequestScoped
public class PoundConverter {

    public Double getPound(Double kg) {
        return 2.20462262 * kg;
    }
}

အဓိကသတိပြုရန်မှာ ၎င်း Class ၏ ရှေ့တွင် @RequestScope ဟု အသုံးပြုမည့် Scope အား သတ်မှတ်ရေးသားနေပါသည်။ ဤသို့ရေးသားခြင်းအားဖြင့် ၎င်း၏ Object အား Request Scope အတွင်းတွင် Inject လုပ်၍ အသုံးပြုနိုင်မည် ဖြစ်ပါသည်။

ပြီးပါက ၎င်းအား အသုံးပြုမည့် JSF ၏ Backing Bean အားရေးသားပါမည်။

ViewBean.java
package com.dtc.di;

import javax.faces.bean.ManagedBean;
import javax.inject.Inject;

@ManagedBean
public class ViewBean {
    
    @Inject
    private PoundConverter cv;
    
    private String out;
    private Double in;
    
    public void convert() {
        out = cv.getPound(in).toString() + " Pound";
    }

    // getter and setter
}
အထက်တွင် ရေးသားထားသော PoundConverter ၏ Object အား အသုံးပြုရန်မှာ အသုံးပြုမည့် Class အတွင်းတွင် @Injection ဟု Declare လုပ်ရုံသာလိုအပ်ပါသည်။ Instantiate လုပ်ရန် လုံးဝမလိုအပ်ပါ။ Container မှ အလိုအလျှောက် Instantiate လုပ်၍ ပေးမည်ဖြစ်ပါသည်။

နောက်ဆုံးတွင် View ဖြစ်သော index.xhtml အား ရေးသားကြည့်ပါမည်။

index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core">

 <h:head>
  <title>DI sample</title>
 </h:head>
 
 <h:body>
  <h2>Kg to Pound Converter</h2>
  
  <h:form>
   <h:panelGrid columns="3" cellspacing="10">
    <h:outputLabel value="Kg" />    
    <h:inputText value="#{viewBean.in}" >
     <f:ajax render="out" event="blur" execute="@this" listener="#{viewBean.convert}" ></f:ajax>
    </h:inputText>
    <h:outputText id="out" value="#{viewBean.out}" />
   </h:panelGrid>
  </h:form>
 </h:body>

</html>

ဤအထဲတွင် h:inputText အထဲမှ တန်ဖိုးအား viewBean ၏ in ဖြင့် ရယူကာ event="blur" ဟု ရေးသားထားသောကြောင့် ၎င်းအတွင်း တန်ဖိုးဖြည့်ပြီး Cursor မှာ အခြားတစ်နေရာသို့ပြောင်းသွားပါက၊ Ajax ဖြင့် viewBean ၏ convert method အား သွားခေါ်စေမည် ဖြစ်သည်။ Ajax လုပ်ဆောင်ချက်ပြီးဆုံးပါက randler="out" ဟု ရေးသားထားသောကြောင့် id out နေရာသို့ သွား၍ update လုပ်မည် ဖြစ်ပါသည်။

ဤနမှုနာအား စမ်းသပ်ကြည့်ပါဦးမည်။ အောက်ပါအတိုင်း တန်ဖိုးအား ပြောင်းလည်းပေးနိုင်သည်ကို တွေ့ရပါသည်။


ဤကဲ့သို့ Dependency Injection အား အသုံးပြုခြင်းအားဖြင့် အသုံးပြုလိုသည့် Object အား  အသုံးပြုမည့် Class အတွင်းတွင် Instantiate လုပ်ရန် မလိုအပ်တော့ပဲ၊ Object တစ်ခုနှင့် တစ်ခုအကြားရှိ မှီခိုမှု့အား လျှော့ချပေးနိုင်မည် ဖြစ်ပါသည်။


Resource Injection နှင့် Dependency Injection


Resource Injection သည် JNDI Namespaceအတွင်းရှိ Resource များအားအသုံးပြုလိုသည့် Managed Objectအတွင်းသို့ တိုက်ရိုက် Inject လုပ်နိုင်မည် ဖြစ်သည်။ ဤကဲ့သို့ Inject လုပ်ရာတွင် Resource Name ဖြင့် လိုအပ်သည့် Object အား ခေါ်ယူအသုံးချမည် ဖြစ်သည်။ ထို့ကြောင့် Type Safe ဖြစ်သည်ဟု ပြောနိုင်မည် မဟုတ်ပေ။ Type Safe ဆိုသည်မှာ အသုံးပြုမည့် Object ၏ Type မတူညီမှု့ကြောင့် ဖြစ်ပေါ်မည့် Error များအား တားဆီးပေးနိုင်ခြင်းကို ဆိုလိုပါသည်။ Resource Injection မှာမှု Declare လုပ်ထားသော Object အား ၎င်း၏ Name ဖြင့်ခေါ်ယူမည်ဖြစ်သောကြောင့်၊ JNDI အတွင်းတွင် ၎င်းအမည်ဖြင့် အခြားသော Class အား သတ်မှတ်ရေးသားထားပါက Type မတူညီသော ပြဿနာ ဖြစ်ပေါ်လာမည်ဖြစ်ပါသည်။ ထို့ကြောင့် Name ဖြင့်ခေါ်ယူသောကြောင့် Type Safe မဖြစ်ဟု ဖော်ပြခြင်း ဖြစ်ပါသည်။

Dependency Injection မှာမှု့ ပုံမှန် Class တစ်ခုအား အသုံးပြုလိုသည့် Managed Object အတွင်းသို့ Inject လုပ်နိုင်မည် ဖြစ်သည်။ ခေါ်ယူရာတွင်လည်း အမည်အား အသုံးမပြုပဲ Type အား တိုက်ရိုက် ခေါ်ယူမည် ဖြစ်သောကြောင့် Type Safe ဖြစ်မည် ဖြစ်ပါသည်။


ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်
မင်းလွင်

2 comments:

  1. ဟုတ္ အကို ၾကီး ေရးထားတဲ့ Lesson ေတြက ေကာင္းပါတယ္
    ညီေလး တစ္ခု ေမးခ်င္ပါတယ္။ ခု website ေတာ္ေတာ္ မ်ားမ်ား က PHP နဲ႔ C# နဲ႔ ေရးထားတဲ့ website ေတြ ပဲ ေတြ႔ရတယ္ အကို ။ java နဲ႔ ေရးထားတဲ့ website ေတြကို မျမင္းဖူးလို႔ ပါ။ အဲဒါ သိခ်င္ပါတယ္ ။ျပီးေတာ့ အဲလို website ျဖစ္ေအာင္ ဘယ္လိုေလ့လာ လုပ္ေဆာင္၇မလဲ သိခ်င္ပါတယ္ အကို ။ ေက်းဇူးပါ။

    ReplyDelete
  2. Java မှာ Enterprise Edition ဆိုတာရှိပါတယ်။ အဲ့ဒီ အဲဒီးရှင်းဟာ Web ကို အခြေခံပြီး Enterprise အပလီကေးရှင်းတွေကို ရေးသားဖို့အတွက်ပြင်ဆင်ထားတဲ့ နည်းပညာဖြစ်ပါတယ်။
    Java မှာ Web ကို ရေးဖို့အတွက်
    Servlet
    JSP
    JSF
    Web Service
    အစရှိတဲ့ နည်းပညာများအပြင် Open Source Framework များဖြစ်တဲ့
    Spring MVC
    JBosss Seam
    Play Framework (Java)
    တွေနဲ့လည်း Web ကို ရေးနိုင်ပါတယ်။

    Java Web Site တွေကို သိပ်မတွေ့ရတဲ့ အကြောင်းကတော့
    Java Application Server တွေကို Hosting တွေ သိပ်မရှိတဲ့အတွက်တစ်ကြောင်း
    Java EE Technology ဟာ ကြီးမားတဲ့ Enterprise တွေအတွက်ဦးတည်ပြီးရေးသားထားတာဖြစ်တဲ့အတွက်တစ်ကြောင်း
    အမှန်အတိုင်းပြောရရင် PHP လောက် View အပိုင်းမှာ ရေးရမလွယ်တဲ့အတွက် တစ်ကြောင်း
    တော်ရုံ Web Site တွေမှာ မတွေ့ရတာဖြစ်ပါတယ်။

    ReplyDelete