December 15, 2016

To Be Enable CDI in Your Project

CDI တွေကို ဘယ်လို Project တွေမှာ အသုံးပြုနိုင်သလဲ။ ပြီးတော့ မိမိရေးသားနေတဲ့ Java Project တွေထဲမှာ CDI ကို အသုံးပြုနိုင်အောင် ဘယ်လိုလုပ်မလဲ။ ဒါတွေကို လေ့လာသွားကြပါမယ်။

အရင်ဆုံး CDI ကို ဘယ်လို Project တွေမှာ အသုံးပြုနိုင်သလဲ။ ဒါကို မစဉ်စားခင် ဘယ်လို Project မျိုးတွေရှိမလဲ ဆိုတာကို စဉ်းစားပါမယ်။ Java ရဲ့ Edition တွေအရကြည့်မယ်ဆိုင် Java SE ဆိုတဲ့ Standard Edition ရှိမယ်။ ပြီးတော့ Java EE ဆိုတဲ့ Enterprise Edition တွေရှိမယ်။ နောက် Java ME ဆိုတဲ့ Micro Edition တွေရှိပါမယ်။ Java ME ကတော့ ကျွန်တော်တို့ မြန်မာနိုင်ငံမှာ အလွယ်တကူရေးလေ့မရှိတဲ့ အတွက် ဖယ်ထားလိုက်ရအောင်။


Java SE Environments


Java SE ပတ်ဝန်းကျင်မှာတော့ အရေးများတာက Desktop Application တွေရှိတယ်ဗျာ။ အဲဒီ Desktop Application တွေမှာ CDI ကို သုံးလို့ရလားဆိုတော့ ရပါတယ်။ ဒါပေမဲ့ CDI Container လို့ခေါ်တဲ့ Library လိုအပ်ပါလိမ့်မယ်။ CDI Container အနေနဲ့ အသုံးများတာကတော့ JBoss Community က ရေးသားတဲ့ WELD ကို အသုံးပြုနိုင်ပါတယ်။ WELD တစ်ခုထဲနဲ့ ဆိုရင် CDI ရဲ့ Feature တွေ အကုန်ကို အသုံးပြုနိုင်မှာ မဟုတ်ပါဘူး။
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.jdc</groupId>
  <artifactId>cdi1</artifactId>
  <version>1.0</version>
  <properties>
      <maven.compiler.version>1.8</maven.compiler.version>
      <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <dependencies>
      <dependency>
          <groupId>org.jboss.weld.se</groupId>
          <artifactId>weld-se</artifactId>
          <version>2.2.15.Final</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
</project>

ဆိုလိုတာက Transaction Handling တို့လို Feature တွေကို သုံးလို့ရမှာ မဟုတ်ဘူး။

Maven Dependency ကတော့ အောက်ပါ အတိုင်းဖြစ်ပါတယ်။
CDI Container အနေနဲ့ weld-se ကို ဖြည့်စွက်ထားဖို့လိုအပ်ပါတယ်။ ဒါမှသာ Java SE ပတ်ဝန်းကျင်မှာ CDI ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ တဖန် Java SE Project တွေဟာ Default အတိုင်း ဆိုရင် CDI ရဲ့ Feature တွေကို ရမှာ မဟုတ်ဘူး။ အဲ့ဒီအတွက် resources/META-INF/ အောက်မှာ CDI ရဲ့ Deployment Descriptor File ဖြစ်တဲ့ beans.xml file ကို ရေးသားထားရပါမယ်။ Eclipse IDE ရဲ့ create > New > beans.xml ကို သုံးပြီး အလွယ်တကူ Create လုပ်နိုင်မှာ ဖြစ်ပါတယ်။

beans.xml မပါပဲနဲ့တော့ Java SE Project တစ်ခုကို CDI Project အဖြစ် အသိမှတ်ပြုမှာ မဟုတ်ဘူး။


ကျွန်တော်တို့ ဒီတစ်ခေါက်ကတော့ CDI အကြောင်းကို ရှင်းသွားမှာ မဟုတ်ပါဘူး။ ပတ်ဝန်းကျင် တိုင်းအတွက် CDI ကို အသုံးပြုနိုင်အောင် ဘယ်လို လုပ်ရမယ်ဆိုတာကိုပဲ အဓိထားပြီး လေ့လာသွားပါမယ်။ အထက်ပါ အတိုင်း Maven Dependency ကို ထည့်ပြီးနောက် beans.xml ကို ထည့်လိုက်တာနဲ့ ကျွန်တော်တို့ Java SE Project လေးဟာ CDI ကို သုံးလို့ရတဲ့ Project တစ်ခုဖြစ်လာပါပြီ။

DI အကြောင်းလေ့လာတဲ့အခါမှပဲ Java SE ပတ်ဝန်းကျင်ပေါ်မှာ CDI ကို သုံးပြီးလေ့လာသွားပါမယ်။


Java EE Environments


Java EE ပတ်ဝန်းကျင်နဲ့ ပတ်သက်ပြီး Container အကြောင်းကို အရင် သဘောပေါက်ဖို့လိုတယ်။ Java EE ရဲ့ Application Server တွေမှာ Web Container နဲ့ EJB Container ဆိုပြီးရှိပါတယ်။ Java EE Full Version ကို ရေးချင်ရင် ဒါမှမဟုတ် EJB Lite ကို သုံးချင်ရင် EJB Container ပါတဲ့ Server မျိုးနဲ့မှ ရေးလို့ရတယ်။ ဥပမာ Glassfish တို့လို JBoss Application Server တို့လို IBM ရဲ့ Web Sphere Server တွေဟာ EJB Container ပါတဲ့ Application Server တွေဖြစ်တယ်။ EJB Container ပါတဲ့ Server တွေမှာ CDI ကို သုံးချင်ရင် ဒီအတိုင်းရေးလို့ရပါတယ်။ အထွေအထူး CDI Container တွေ ရေးစရာ မလိုအပ်ပါဘူး။

Web Container သာပါတဲ့ Tomcat တို့လို Server တွေကတော့ CDI ကို ဒီအတိုင်း သုံးလို့မရပါဘူး။ Java SE ပတ်ဝန်းကျင်မှာလိုပဲ CDI Container ကို Library အနေနဲ့ ထည့်ထားမှသာ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ ဒါပေမဲ့ Apache Foundation က ရေးသားထားတဲ့ CDI Extension Library တစ်ခု ဖြစ်တဲ့ Deltaspike နဲ့ တွဲသုံးမယ်ဆိုရင်တော့ Java EE ပတ်ဝန်းကျင် မဟုတ်တဲ့ နေရာတွေမှာလဲ Java EE လို CDI ရဲ့ Feature တွေကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။


Web Application on Application Server


Application Server တွေပေါ်မှာ Web Application ကို ရေးသားမယ်ဆိုရင် war ပုံစံနဲ့ ရေးသားရမှာ ဖြစ်ပါတယ်။ Java EE 6 ကနေစပြီး Application Server တွေက CDI ကို Support လုပ်ပါတယ်။ ဒါ့ကြောင့် Application Server တွေပေါ်က Web Application တွေမှာ CDI ကို ရေးသားချင်ရင် အထွေအထူး Maven Dependency တွေကို ရေးသားစရာ မလိုအပ်ပါဘူး။

တဖန် Java EE 7 ကနေစပြီး CDI ရဲ့ Deployment Descriptor ဟာ Optional ဖြစ်လာပြီး CDI ရဲ့ Default Feature အတိုင်းသုံးနေမယ်ဆိုလို့ကတော့ beans.xml တောင် မလိုအပ်ပါဘူး။ ဒါပေမဲ့ Default Feature တွေကို ပြုပြင်ချင်တယ်ဆိုမှ beans.xml file ကို WEB-INF အောက်မှာ ရေးသားပြီး Customise လုပ်ရမှာ ဖြစ်ပါတယ်။


အထက်ပါအတိုင်း Eclipse ရဲ့ Beans XML Editor ကို သုံးပြီး မိမိ လိုအပ်သလို CDI ရဲ့ Feature တွေကို Customise လုပ်နိုင်မှာ ဖြစ်ပါတယ်။

CDI ရဲ့ Scope တွေကို လေ့လာသွားတဲ့အခါမှာ အထက်ပါ ရေးသားပုံကို အသုံးပြုသွားမှာ ဖြစ်ပါတယ်။


Enterprise Applications


Enterprise Application တစ်ခုမှာ Module တွေ တစ်ခုမက ပါဝင်နေနိုင်ပါတယ်။ ပြီးတော့လည်း Module တွေကလဲ တစ်ခုနဲ့ တစ်ခု Dependent လုပ်နေနိုင်ပါတယ်။ ဥပမာအားဖြင့် Enterprise Application တစ်ခုမှာ Business Logic တွေကို Wrap လုပ်ပေးနိုင်တဲ့ EJB Module တွေလဲ​တစ်ခုမကပါနိုင်ပါတယ်။ လုပ်ငန်းအလိုက် Web Module တွေကိုလဲ ခွဲခြားထားနိုင်ပါတယ်။ တဖန် JMS တို့ Web Service တို့အတွက် Module တွေကို ရေးသားထားနိုင်ပါတယ်။ အဲ့ဒီ Module တွေကို စုစည်းပြီး EAR အဖြစ် Archive လုပ်ရမှာ ဖြစ်ပါတယ်။


အထက်ပါ Project Structure ကတော့ Java EE ရဲ့ Full Feature ကို အသုံးပြုနိုင်တဲ့ Enterprise Application တစ်ခုကို Maven နဲ့ တည်ဆောက်ထားတာဖြစ်ပါတယ်။

ဦးစွာ ejb1 အမည်နဲ့ Maven POM Project တစ်ခုကို တည်ဆောက်ပါတယ်။ ပြီးတော့မှ EJB Module အနေနဲ့ ejb1-ejb ဆိုတဲ့ Project ကို ejb ပုံစံနဲ့တည်ဆောက်ပါတယ်။ ထို့နောက် ejb1-war အမည်နဲ့ war ပုံစံနဲ့ တည်ဆောက်ပါမယ်။

အဲ့ဒီ Module တိုင်းမှာ CDI ကို Default အတိုင်း သုံးမယ်ဆိုရင်တော့ ဘာမှ အထွေအထူး ရေးသားစရာမလိုအပ်ပါဘူး။ customize လုပ်လိုမှသာ beans.xml ကို ဖြည့်စွက်ရမှာ ဖြစ်ပါတယ်။ CDI ကို သုံးမည့် project ဟာ jar ဖြစ်ရင် META-INF အောက်မှာ ရေးသားရပြီး war project ဆိုရင်တော့ WEB-INF အောက်မှာ beans.xml ကို ရေးသားရပါမယ်။

ejb1-war ထဲကနေ ejb1-ejb ကို Reference လုပ်နေမှာ ဖြစ်ပါတယ်။ ejb1-ejb project ထဲမှာ Business Logic တွေကို Encapsulate လုပ်ထားတဲ့ EJB တွေနဲ့ Persistence Layer အတွက် JPA Entity တွေကို ရေးသားထားမှာ ဖြစ်ပါတယ်။ အဲ့ဒီ EJB တွေကို ejb1-war ထဲကနေ ယူသုံးနေမှာ ဖြစ်ပါတယ်။ ejb1-ejb ထဲက Beans တွေမှာ CDI ကို သုံးပြီး Inject လုပ်ချင်တယ်ဆိုရင်တော့ မဖြစ်မနေ ejb1-ejb project ထဲမှာ beans.xml ကို ရေးသားထားရပါမယ်။

Project ထဲမှာ beans.xml ပါမှသာ အခြား Project ကနေကြည့်ရင် CDI Beans အနေနဲ့ တွေ့ရှိမှာ ဖြစ်ပါတယ်။ ဒါ့ကြောင့် အခြား Project ထဲကနေ Reference လုပ်မည့် Project တွေဆိုရင် beans.xml ကို ရေးသားထားရမှာ ဖြစ်ပါတယ်။

ဒီလို ပုံစံတွေကိုတော့ ကျွန်တော်တို့ EJB ကို လေ့လာတဲ့ နေရာမှာ ရေးသားအသုံးပြုရမှာ ဖြစ်ပါတယ်။


Web Container's Applications


Tomcat လို Web Container တွေပေါ်မှာရေးသားတဲ့ Dynamic Web Application တွေမှာ CDI ကို သုံးချင်တယ်ဆိုရင် ဒီအတိုင်းဆိုရင် သုံးလို့ရမှာ မဟုတ်ပါဘူး။ CDI container ကို Library အဖြစ်ဖြည့်စွက်ပြီးမှသာ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ WELD Container ကိုသုံးပြီး Tomcat လို Web Container တွေမှာလဲ CDI ရဲ့ Feature တွေကို အသုံးပြုနိုင်မှာ ဖြစ်တယ်။ တဖန် Deltaspike လို CDI Extension လို Library တွေနဲ့ တွဲသုံးရင် Java EE Application တွေလိုပဲ Transaction တွေကို Handle လုပ်ပေးနိုင်မှာ ဖြစ်ပါတယ်။

Tomcat 7 အထက်ကို သုံးမယ်ဆိုရင် CDI ကို Servlet, Filter တွေနဲ့ Listener တွေမှာ Injection ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

လုပ်ရမှာကတော့ Maven Dependency ထဲမှာ Weld Servlet ကို Container အနေနဲ့ ဖြည့်စွက်ပါမယ်။
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.jdc</groupId>
    <artifactId>web-cdi</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.weld.servlet</groupId>
            <artifactId>weld-servlet</artifactId>
            <version>2.2.15.Final</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>

ပြီးရင် WEB-INF အောက်မှာ CDI ရဲ့ Deployment Descriptor ဖြစ်တဲ့ beans.xml ကို ရေးသားထားရုံပါပဲ။ ဒါဆိုရင် Tomcat ရဲ့ Dynamic Web Application တွေမှာ CDI ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

Project Structure ကတော့ အောက်ပါ အတိုင်းဖြစ်ပါတယ်။


ပြီးရင် စမ်းသပ်ဖို့အတွက် CDI Beans တစ်ခုကို @RequestScoped သုံးပြီးရေးသားပါမယ်။
package com.jdc.cdi;

import javax.enterprise.context.RequestScoped;

@RequestScoped
public class HelloBean {

    public String getMessage() {
        return "Hello CDI";
    }
}

ပြီးပါက အထက်ပါ HelloBean ကို Servlet ထဲမှာ Inject လုပ်ပြီး သုံးကြည့်ပါမယ်။
package com.jdc.cdi;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloCDIServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Inject
    private HelloBean hello;
       
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().append(hello.getMessage());
    }
}

အထက်ပါ အတိုင်း Servlet ထဲမှာ CDI ကို သုံးပြီး Inject လုပ်လာနိုင်ပါမယ်။ Servlet ပေါ်မှာ CDI ကို သုံးလာနိုင်တာ ဝမ်းသာစရာ သိပ်ပြီး မကောင်းပါဘူး။ ဒါပေမဲ့ CDI Feature နဲ့ Deltaspike ကို သုံးပြီး Struts လို Framework တွေနဲ့ တွဲပြီး သုံးနိုင်မယ်ဆိုရင် Java EE ပတ်ဝန်းကျင် မဟုတ်ပေမဲ့ Java EE Feature တွေကို သုံးလာနိုင်တာဟာ စိတ်ဝင်စားစရာကောင်းပါတယ်။

ဘာလို့လဲဆိုတော့ Cloud ပတ်ဝန်းကျင်တွေမှာ Java EE Server ကို သုံးနိုင်တဲ့ Cloud တွေကို Comercial အနေနဲ့ သုံးမယ်ဆိုရင် ဈေးကြီးပါတယ်။ ဒါပေမဲ့ Tomcat လောက်ဆိုရင် သိပ်ပြီး ဈေးမကြီးတော့ပါဘူး။ ဒါ့ကြောင့် Tomcat လို Server မျိုးနဲ့ Java EE Feature တွေသုံးနိုင်တာဟာ ဝမ်းသာစရာ အချက်တစ်ခုဖြစ်ပါတယ်။


Conclusion


ကျွန်တော်တို့ ဒီတစ်ခေါက် ဘယ်လို Project တွေမှာ CDI ကို သုံးနိုင်အောင် ဘယ်လိုလုပ်မလဲ ဆိုတာကို အဓိကထားလေ့လာခဲ့ပါတယ်။ CDI ကိုဘယ်လို ရေးမလဲ​ဆိုတာ မဟုတ်သေးပါဘူး။ မိမိရေးသားနေတဲ့ Project က ဘယ်ပုံစံ အဲ့ဒီမှာ CDI ကို သုံးချင်ရင် ဘာတွေလုပ်ရမယ်ဆိုတာကို လေ့လာနိုင်မယ်လို့ ထင်ပါတယ်။

နောက် အခန်းတွေကဆက်ပြီး Dependency Injection, Scopes of CDI Beans, Interceptors, Decorators, Events အစရှိတဲ့ CDI Feature တွေကို ဆက်လက်ပြီး လေ့လာသွားပါမယ်။

ဆက်ပါဦးမယ်။
မင်းလွင်

No comments:

Post a Comment