September 8, 2020

Number to Myanmar Digit

ကျွန်တော် Blogger ကို ဝင်မကြည့်ဖြစ်ခဲ့တာ အတော်လေးကြာခဲ့ပါပြီ။ တစ်ချို့အသိတွေက ပြောကြပါတယ်။ Menu တွေ မပေါ်တော့ဘူးတို့၊ Image တွေ ပျောက်ကုန်ပြီတို့။ ဘာကြောင့်လဲ ဆိုတာကိုတော့ ရိပ်မိိပါတယ်။ ဒါပေမဲ့ ပြင်ရမှာ အလုပ်ရှုပ်တာနဲ့ ဒီအတိုင်းပဲ ပစ်ထားခဲ့ပါတယ်။ အားမှအေးဆေးပြင်မယ်ပေါ့။ ဒါပေမဲ့ ပြန်ပြီး မကြည့်ဖြစ်ခဲ့ပါဘူး။

ဒါပေမဲ့ အခု ကိုဗစ် 19 ကြောင့် ကျွန်တေော်တို့ သင်တန်းတွေ တကယ်ပိတ်ထားရတဲ့ အခါ ကျွန်တော် အားသွားခဲ့ပါတယ်။ ဒီအချိန်ဘာလုပ်ရင်ကောင်မလဲ တွေးမိတဲ့ အခါ မြန်မာဂျာဗားယူဇာလေးမှာ စာပြန်ရေးမယ် ဖြစ်လာပါတယ်။ အရင်ဆုံး Site Menu လေးကို ပြန်ပြီး အလုပ်လုပ်အောင်ပြင်ပါတယ်။ Post အသစ်လေးတွေ အားရင်အားသလိုရေးပါတယ်။ ပြီးတော့မှာ Comment တွေကို ပြန်ကြည့်ပါတယ်။ တစ်ချို့ Span Comment တွေလဲရှိကြသလို ကြားထဲမှာလဲ စာမေးထားတဲ့ Comment လဲရှိပါတယ်။ ဒီနေရာမှာတော့ Formatting Number Post မှာ မေးထားတဲ့ မေးခွန်းလေးကို ပြန်ပြီး ဖြေသွားမှာ ဖြစ်ပါတယ်။

မေးထားတာကတော့ Number တွေကို မြန်မာကိန်းဂဏန်း အနေနဲ့ ဘယ်လိုဖေါ်ပြမလဲ ဆိုတာပါ။


My First Idea is Unicode

Java Programming Language ဟာ Character တွေနဲ့ String တွေမှာ Unicode ကို အသုံးပြုထားပါတယ်။ Unicode ဆိုတာကတော့ Encoding System တစ်ခုဖြစ်ပြီး၊ Computer System ပေါ်မှာ ဘာသာစကားအားလုံးကို အသုံးပြုနိုင်အောင် စီစဉ်ထားတဲ့ Encoding System တစ်ခုဖြစ်ပါတယ်။ စာလုံးတွေကို Comflit မဖြစ်အောင် Code Point တွေနဲ့သတ်မှတ်ထားပြီး Hexa Decimal Format နဲ့ ဖေါ်ပြလေ့ရှိပါတယ်။ Ascii Code ဆိိုရင် Code Point ဘယ်လောက်ကနေ ဘယ်လောက်၊ မြန်မာစာ ဆိုရင် Code Point ဘယ်လောက်ကနေ ဘယ်လောက်၊ ဂျပန်စာဆိုရင် Code Point ဘယ်လောက်ကနေ ဘယ်လောက် ဆိုပြီး သတ်မှတ်ထားပါတယ်။

ဘာဘာသာစကားနဲ့ပဲ ရေးရေး Number တွေကိုတော့ 0 ကနေ 9 အထိ အစဉ်လိုက်ထားရှိမှာ ဖြစ်ပါတယ်။ အဲ့ဒီတော့ ကျွန်တော်တို့ စမ်းသပ်ရမှာက Number 0 နဲ့ မြန်မာ သုည ဟာ Code Point ဘယ်လောက်ကွာလဲ ဆိုတာပဲဲ ဖြစ်ပါတယ်။ '0' ကနေ '9' အထိ Unicode Character တွေကို Code Point ကွာခြားချက်နဲ့ ပေါင်းလိုက်ရင် သက်ဆိုင်ရာ ဘာသာစကားရဲ့ ကိန်းဂဏန်း Character တွေကို ရလိမ့်မယ်လို့ တွေးမိပါတယ်။

JShell လေးကို ဖွင့်ပြီး စမ်းကြည့်မိပါတယ်။

အရင်ဆုံးစမ်းမိတာကတော့ မြန်မာ သုညနဲ့ Ascii Zero ဟာ Code Point ဘယ်လောက်ကွာလဲ ဆိုတာပါပဲ။ မြန်မာ သုည char ထဲဲကနေ Ascii Zero char ကို နှုတ်ကြည့်တဲ့အခါ 4112 ကို ရတာကို တွေ့ရပါတယ်။ ဆိုလိုတာက Number Zero ကို 4112 ပေါင်းလိုက်ရင် မြန်မာဂဏန်း သုည ရပါမယ်။ အိုကေ ဆက်ပြီး Number One ကို 4112 နဲ့ ပေါင်းကြည့်တဲ့ အခါမှာ မြန်မာဂဏန်း ၁ ကို ရရှိတာကို တွေ့ရပါတယ်။


Writing Convert Method

Number Character တွေကို တစ်လုံးချင်းပြောင်းပေးနိုင်တာတော့ ဟုတ်ပါပြီ။ တကယ်တမ်း Number တွေလာရင် အပြည့်ကိန်း အနေနဲ့ လာလိမ့်မယ်။ သူမေးထားတဲ့ မေးခွန်းထဲမှာတောင် 13 ဆိုရင် ၁၃ လို့ပြရမယ်လို့ ပါတယ်။ ဒါဆိုရင်တော့ Number တွေကို Charactor တစ်လုံးဆီဖြစ်အောင်လုပ်ပြီး၊ ကွာနေတဲ့ ကုဒ်ပွိုင့်ကို ပေါင်းပေးရုံပဲလို့ တွေးမိပါတယ်။ အဲ့ဒီအတွက် Method တစ်ခုကို ရေးကြည့်ပါတယ်။

String convert(int number) {

	// conver to string       	
	String str = String.valueOf(number);

	// get char array from String
	char [] array = str.toCharArray();
	
	StringBuilder sb = new StringBuilder();
	
	// Loop array
	for(char c : array) {
              
		// change to Myanmar digit uinicode code point
		int i = c + 4112;
              
		// cast to uinicode char
		char mmDigit = (char)i;

		// append to StringBuilder
		sb.append(mmDigit);
	}
	
	// return result as string
	return sb.toString();
}

Integer ကနေ char တစ်လုံးချင်းစီကို ထုတ်ယူဖို့ အတွက် String အဖြစ်ပြောင်းပြီးမှ char array အဖြစ် ပြောင်းယူပါတယ်။ ပြီးတော့မှ char တစ်လုံးချင်းစီကို Myanmar Digit အဖြစ်ပြောင်းပြီး StringBuilder အဖြစ်ပြန်ပြောင်းယူပါတယ်။

ရေးထားတဲ့ Method ကို စမ်းကြည့်တဲ့ အခါ အထက်ပါအတိုင်း မှန်မှန်ကန်ကန် အလုပ်လုပ်နေတာကို တွေ့ရပါတယ်။ တစ်ခြားနည်းလဲ ရှိမယ်ဆိုရင် ရှိနိုင်ပါတယ်။ ကျွန်တော် ဆိုရင်တော့ ဒီအတိုင်း ရေးသားသွားမှာ ဖြစ်ပါတယ်။

သိချင်တာရှိရင်လဲ Comment တွေမှာ မေးပေးကြပါခင်ဗျာ။
ကျွန်တော် သိသလောက်တော့ ဖြေကြားသွားမှာ ဖြစ်ပါတယ်။
မင်းလွင်

Getting Start Module

ကျွန်တော်တို့ Module ကို လေ့လာတဲ့ နေရာမှာ What, Why & How နဲ့ လေ့လာသွားကြရအောင်။

What is a Module?

“A Module is a group of closely related packages and resources along with a new module descriptor file.”

အနီးကပ်ဆုံးအသုံးပြုမည့် Java Packages တွေ၊ XML, Properties, Json, Images အစရှိတဲ့ Resources File တွေနဲ့ အတူ Module Descriptor File တစ်ခုနဲ့ စုစည်းထားတဲ့ Group တစ်ခုကို Module လို့ ခေါ်တယ်လို့ ဆိုပါတယ်။

သေချာပြန်စဉ်းစားကြည့်မယ်ဆိုရင် Package တွေနဲ့ Resources တွေကို စုစည်းထားတာဆိုတော့ Jar File ဟာလဲ ဒီလိုပဲ မဟုတ်ဘူးလားဆိုပြီး မေးစရာရှိလာပါမယ်။ နောက်ပြီး Module Project ကို Package လုပ်တဲ့နေရာမှာလဲ Jar ကိုပဲ​အသုံးပြုကြတဲ့ အတွက် Module နဲ့ Jar ဘာကွာလဲ မေးစရာရှိလာပါမယ်။


Module Vs Jar

Module နဲ့ Jar ဘာကွာလဲဆိုရင် မိမိကိုယ်ကိုယ်ပြန်ပြီး သတ်မှတ်နိုင်တဲ့ အချက်ဖြစ်ပါတယ်။ Module ထဲမှာ Module Descriptor File ကို ရေးသားနိုင်ပြီး လက်ရှိ Module ဟာ ဘယ်လို ဖြစ်တယ်ဆိုတာကို သတ်မှတ် ရေးသားနိုင်ပါတယ်။ Jar File တစ်ခုမှာ ဒါတွေကို သတ်မှတ်ရေးသားလို့ မရနိုင်ပါဘူး။

Title Description
Name လက်ရှိရေးသားနေတဲ့ Module Name
Dependencies လက်ရှိ Module ထဲမှာ အသုံးပြုလိုတဲ့ အခြား Module တွေ
Public Packages အခြား Module တွေကို ပေးသုံးလိုတဲ့ လက်ရှိ Module ရဲ့ Package တွေ
Services Offer အခြား Module တွေကို ပေးသုံးစေလိုတဲ့ Service တွေ
Services Consume လက်ရှိ Module မှာ အသုံးပြုမည့် အခြား Module က Service တွေ
Reflection Permissions အခြား ဘယ် Module တွေကို Reflection ပေးသုံးမလဲ ဆိုတဲ့ Permission သတ်မှတ်ချက်တွေ


Why Java need Module?

Java Platform က ဘာဖြစ်လို့ Modular ဖြစ်ဖို့လိုရတာလဲ။ တနည်းပြောရမယ်ဆိုရင် ဘာတွေလုပ်မယ် ဆိုတာတွေကို Module Descriptor File မှာ ရေးသားထားဖို့လိုအပ်ရတာလဲ။ အဲ့ဒါကတော့ Class Path နဲ့ Jar Problem တွေကြောင့် ဖြစ်ပါတယ်။


Jar Dependencies

အတန်ကြီးတဲ့ System တစ်ခုကို ရေးသားကြပြီဆိုပါစို့။ အစအဆုံးကို တစ်နေရာထဲမှာ ရေးသားကြတယ် ဆိုတာ မရှိသလောက်ရှားပါတယ်။ Open Source Framework တွေ၊ Open Source Library တွေကို အသုံးပြု ရေးသားနေကြတာ များပါတယ်။ ဒီလိုပဲ အသုံးပြုနေတဲ့ Open Source Library တွေကလဲ အခြားသော Open Source Library တွေကို အသုံးပြုရေးသားနေကြပါတယ်။

ဒီလိုနဲ့ Runtime မှာ Load လုပ်ရမည့် Jar တွေက တဖြည်းဖြည်းနဲ့ တိုးပွါးလာခဲ့ရပါတယ်။ ပြီးတော့ Jar File တွေမှာလဲ မိမိ အသုံးပြုနေတဲ့ Library တွေကိုလဲ သတ်မှတ်နိုင်ခြင်းမရှိတဲ့ အတွက် အသုံးပြုနေတဲ့ Library တွေ အားလုံးကို Class Path ထဲကို ကောက်ထည့်ဖို့ပဲ ရှိပါတော့တယ်။

Jar File တွေအရမ်းများလာတဲ့ အခါမှာ Version မှန်ကန်မှုတွေကို ထိမ်းမရသိမ်းမရဖြစ်လာပါတော့တယ်။ Version ကို Update လုပ်လိုက်တိုင်း၊ Dependency တွေကို မှန်အောင် ရှာပြီးထည့်ရတဲ့ အလုပ်ဟာ ပြဿနာ တစ်ခုဖြစ်လာသလို၊ မှန်မှန်ကန်ကန် မထည့်နိုင်ပြန်ရင်လဲ၊ Class ကို မတွေ့ဘူးဆိုတဲ့ ပြဿနာဟာ မကြာမကြာ တွေ့ရလေ့ရှိပါတယ်။

ပြီးတော့ မိမိပရိုဂျက်က အသုံးပြုနေတဲ့ Open Source Library တွေကနေ Version မတူတဲ့ အခြား Open Source Library ကို သွားပြီး သုံးမိနေတာတွေလဲ ရှိနိုင်ပါတယ်။ ဒီလိုမျိုး Class Path ထဲမှာရှိတဲ့ Jar File တွေ ကြောင့် ဖြတ်တတ်တဲ့ ပြဿနာတွေကို JAR HELL လို့ လဲ ခေါ်ဆိုလေ့ရှိပါတယ်။

ဒီလို ပြဿနာတွေကို ဖြေရှင်းဖို့ ကြိုးစားခဲ့ကြတာကတော့၊ Maven တို့ Gradle တို့လို Build Tools တို့ဖြစ်ကြပါတယ်။ Maven Project တွေမှာ pom.xml ထဲမှာ အသုံးပြုလိုတဲ့ Dependency ရဲ့ Version တွေကို သတ်မှတ်ခြင်းအားဖြင့် Compile Time မှာ Jar File တွေရဲ့ Version ပြဿနာကို ဖြေရှင်းဖို့ ကြိုးစားခဲ့ကြပါတယ်။

Java Modular System မှာလဲ Module Description File မှာ အသုံးပြုမည့် Dependency တွေကို သတ်မှတ် ရေးသားစေခြင်းအားဖြင့် Compile Time မှာကော Run Time မှာပါ Jar ကြောင့် ဖြစ်တဲ့ ပြဿနာကို ဖြေရှင်းနိုင်ဖို့ ကြိုးစားလာခဲ့ကြတာဖြစ်ပါတယ်။


Public is too public

ဒါဟာ Library ထဲမှာပဲ သုံးသင့်တဲ့ Class တွေနဲ့ Library ပြင်ပကို ပေးသုံးစေချင်တဲ့ Class တွေကို ခွဲခြားပြီး မသတ်မှတ်နိုင်လို့ ဖြစ်ပါတယ်။ ဒီလို သတ်မှတ်နိုင်ခြင်း မရှိတဲ့ အတွက် Library အတွင်းမှာသာ သုံးသင့်တဲ့ Class တွေကို အပြင်ကနေ သွားသုံးနေမိတတ်ပါတယ်။ ဒါ့ကြောင့် အတွင်းပိုင်း ပြောင်းလဲမှုကို လုပ်လိုက်တဲ့ အခါမှာ အဲ့ဒီ Class ကို အပြင်က သုံးမိနေတဲ့ အတွက် ဖြစ်ရတဲ့ ပြဿနာက ပိုပြီးများမှာ ဖြစ်ပါတယ်။

ဒါဟာ Java Programming Language မှာ Library ထဲမှာသာ သုံးလို့ရမည့် အရာဆိုပြီး သတ်မှတ်နိုင်တဲ့ Accss Modifier မရှိတဲ့ အတွက် ဖြစ်ပါတယ်။

Encapsulation ဆိုတာက အပြင်ကို ထုတ်ပြသင့်တာ တွေကိုသာ ထုတ်ပြပြီး၊ အတွင်းပိုင်းမှာ သိမ်းထားသင့်တာတွေကို အပြင်က မမြင်အောင် လုပ်ထားနိုင်ခြင်း ဖြစ်ပါတယ်။ ဒီလို အပြင်က မမြင်သင့်တာတွေကို မမြင်အောင် လုပ်ထားနိုင်ခြင်းအားဖြင့် အတွင်းပိုင်း ပြောင်းလဲမှု အတွက် ပြင်ပကနေ သုံးနေတဲ့ နေရာတွေမှာ ထိခိုက်မှုမရှိအောင် ဆောင်ရွက်ထားနိုင်မှာပဲ ဖြစ်ပါတယ်။

Java Programming မှာတော့ Encapsulation ကို ဆောင်ရွက်နိုင်ဖို့ Access Modifier တွေကိုပြင်ဆင် ပေးထားပါတယ်။ Modifier တွေအနေနဲ့ private, default (package), protected နဲ့ public Modifier တွေကို အသုံးပြုပြီး လိုအပ်သလို အသုံးပြုခွင့်ကို သတ်မှတ်နိုင်အောင် ပြင်ဆင်ပေးထားပါတယ်။

Package တစ်ခုထဲမှာသာ အသုံးပြုစေလိုတယ်ဆိုရင် Default Modifier ကို အသုံးပြုနိုင်ပြီး၊ Package အပြင်ကပါ ပေးသုံးစေချင်တယ်ဆိုရင်တော့ Protected နဲ့ Public Modifier တွေကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။ ဒါပေမဲ့ Public လို့ သတ်မှတ်လိုက်ပြီဆိုတာနဲ့ ဘယ်နေရာကမဆို အသုံးပြုသွားနိုင်မှာ ဖြစ်ပါတယ်။

ဒါ့ကြောင့် Library တစ်ခုထဲမှာရှိပြီး Package တွေအကြားမှာ အသုံးပြုစေလိုတဲ့ Class တွေ Interface တွေဆိုရင် ကျွန်တော်တို့ Public Modifier ကို အသုံးပြုရုံကလွဲပြီး တစ်ခြားနည်းလမ်းမရှိတော့ပါဘူး။ ဒါပေမဲ့ Public Modifier ကို သုံးမိပြီဆိုရင်လဲ Library အတွင်းမှာ ထားသုံးသင့်တဲ့ Class တွေကို ဘယ်နေရာက မဆို မြင်နေပြီး အသုံးပြုသွားနိုင်ပါတယ်။

ဒါ့ကြောင့် Library အတွင်းမှာသာ အသုံးပြုသင့်တဲ့ အရာတွေကို Library အတွင်းမှာသာ အသုံးပြုနိုင်အောင် သတ်မှတ်ထားနိုင်ခြင်းမရှိတဲ့ အတွက်၊ ပြောရမယ်ဆိုရင် Encapsulation ကို ကောင်းမွန်အောင် ဆောင်ရွက် ထားနိုင်ခြင်းမရှိတဲ့ အတွက် အတွင်းပိုင်းပြုပြင်ပြောင်းလဲမှုတွေဟာ အသုံးပြုနေတဲ့ဘက်ကို အကျိုးသက်ရောက်စေတာဖြစ်ပါတယ်။

ဒီပြဿနာတွေကို ဖြေရှင်းဖို့ အတွက် Project Jigsaw ဟာ Module Description File ထဲမှာ Public Packages တွေ၊ Consume လုပ်မည့် Service တွေ၊ Provide လုပ်မည့် Service တွေနဲ့ Reflaction ကို ခွင့်ပြုမည့် Permission တွေကို ရေးသား သတ်မှတ်နိုင်အောင် ပြင်ဆင်လာခဲ့တာဖြစ်ပါတယ်။


Because of Module

ဒီနေရာမှှာ Module ဆိုတာဘာလဲ ဆိုတာကို ပြန်ပြီး လေ့လာကြည့်ကြရအောင်။ Module တစ်ခုမှာ အသုံးပြုမည့် Package တွေနဲ့ Resources File တွေပါဝင်ကြပါမယ်။ ပြီးတော့ လက်ရှိအသုံးပြုနေတဲ့ Module ဟာ အခြားဘယ်လို Dependency တွေကို အသုံးပြုနေတာလဲ၊ ပြီးတော့ လက်ရှိ ရေးသားနေတဲ့ Module ရဲ့ Package တွေထဲက ဘယ် Package တွေကို Public အနေနဲ့ ထားမှာလဲ၊ ပြီးတော့ ဘယ်လို Service တွေကို အသုံးပြုချင်တာလဲဆိုတာနဲ့ လက်ရှိ Module ထဲက ဘယ် Class တွေကို Service အနေနဲ့ Privide လုပ်မလဲ ဆိုတာကို သတ်မှတ်လာနိုင်မှာ ဖြစ်ပါတယ်။

Modular Java ဖြစ်သွားခဲ့ရတဲ့ အတွက်ဘာတွေကောင်းသွားမှာလဲ။ ဒါကတော့ Modular System အကြောင်းကို လေ့လာသွားရင်းပဲ မြင်အောင် ကြည့်ကြရအောင်။


How to Module?

ကျွန်တော်တို့ Module ဆိုတာဘာလဲ၊ ပြီးတော့ Java Platform မှာ Module ဆိုတာကို ထည့်သွင်း အသုံးပြုဖို့ လိုအပ်ခဲ့ရတာလဲ ဆိုတာကို သိရှိပြီးတဲ့ နောက်မှာ Module တစ်ခုကို ဘယ်လို ရေးသား အသုံးပြုမလဲ ဆိုတာကို လေ့လာသွားကြပါမယ်။


Writing Module as a Library

ကျွန်တော်တို့ Eclipse IDE နဲ့ Java 11 ကို အသုံးပြုပြီး Java Project တစ်ခုကို တည်ဆောက်လိုက်ရင် module-info.java file ကို Create လုပ်မလား ဆိုတာကို မေးပါမယ်။

အထက်ပါအတိုင်း Create module-info.java ကို Check လုပ်ပြီးလဲ Module ကို အသုံးပြုတဲ့ Java Project တစ်ခုကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ ဒီနေရာမှာတော့ အသုံးပြုလိုတဲ့ Module Name ကို ဖြည့်စွက်ပေးရ ပါမယ်။ Module Name ဟာလဲ Package Name တွေလိုပဲ Reverse Domain Name ကို ရေးသားပေးရပါမယ်။ ဒီနမူနာမှာတော့ com.jdc.hello.library ကို Module Name အဖြစ် အသုံးပြုပါမယ်။

တည်ဆောက်ပြီးတဲ့ Project ရဲ့ src folder အောက်မှာ module-info.java file ကို တည်ဆောက်ပေးသွားတာကို တွေ့ရမှာ ဖြစ်ပါတယ်။

module [Module Name] {
    // module body
}

Module တစ်ခုကို ရေးသားတဲ့ နေရာမှာ module keyword ကို အသုံးပြုပြီး Module Name နဲ့ Module Body တို့ကို ရေးသားရမှာ ဖြစ်ပါတယ်။ Module Body ထဲမှာတော့ Dependency, Public Packages, Services တွေနဲ့ Reflection Permission တွေကို သတ်မှတ်ရေးသားရမှာ ဖြစ်ပါတယ်။

package com.jdc.hello;

public interface Hello {

    String sayHello(String name);
}

Hello Interface ကတော့ ဒီ Library ကို အသုံးပြုလိုသူတွေကို ထုတ်ပေးမဲ့ API တစ်ခုဖြစ်ပြီး com.jdc.hello Package အောက်မှာ ရေးသားထားပါတယ်။

package com.jdc.hello.impl;

import com.jdc.hello.Hello;

public class HelloImpl implements Hello{

    @Override
    public String sayHello(String name) {
        return String.format("Hi! %s, this is from Module.", name);
    }
}

HelloImpl Class ကတော့ Hello Interface ရဲ့ Implementation Class ဖြစ်ပြီး Library ထဲမှာပဲ ထားသုံးမည့် Class ဖြစ်ပါတယ်။ Library ပြင်ပကနေ ဒီ Class ကို တိုက်ရိုက်ပေးမသုံးစေချင်တဲ့ အတွက် com.jdc.hello.impl Package အောက်မှာ ရေးသားထားပါတယ်။

package com.jdc.hello;

import com.jdc.hello.impl.HelloImpl;

public class HelloFactory {

    public static Hello getHello() {
        return new HelloImpl();
    }
}

HelloFactory Class ကတော့ Hello Interface အတွက် Factory Class တစ်ခုဖြစ်ပါတယ်။ Hello Object ကို Library ပြင်ပကနေ အသုံးပြုလိုတဲ့ အခါမှာ HelloFactory ရဲ့ getHello() Method ကို ခေါ်ယူအသုံးပြု ရမှာ ဖြစ်ပါတယ်။ အထဲမှာတော့ HelloImpl Class ကို new Operator နဲ့ Object ဆောက်ပြီး Hello Interface အနေနဲ့ Return ပြန်ထားပါတယ်။

ပြီးတော့ HelloFactory Class ကိုလဲ Module ပြင်ပကနေ ပေးသုံးစေလိုတဲ့ အတွက် com.jdc.hello Package ထဲမှာ ရေးသားထားပါတယ်။

module com.jdc.hello.library {
    exports com.jdc.hello;
}

Module Descriptor ထဲမှာတော့ Module ပြင်ပကေန ပေးသုံးစေလိုတဲ့ com.jdc.hello Package ကို Export လုပ်မယ်လို့ ရေးသားထားပါတယ်။ ဤနည်းအားဖြင့် com.jdc.hello Package အောက်မှာရှိတဲ့ Hello နဲ့ HelloFactory ကိုသာ Module ပြင်ပကနေ အသုံးပြုနိုင်မှာ ဖြစ်ပြီး၊ Module အတွင်းမှာသာ အသုံးပြုစေလိုတဲ့ HelloImpl Class ကို Module ပြင်ပကနေ အသုံးပြုလို့ ရမှာ မဟုတ်တော့ပါဘူး။

အကြောင်းတစ်မျိုးမျိုးကြောင့် HelloImpl Class အတွင်းပိုင်းမှာ ပြုပြင်ပြောင်းလဲမှုတွေ ရေးသားဖို့လိုလာခဲ့ရင် တောင်မှ Module ပြင်ပကနေ သုံးမထားတဲ့ အတွက် အသုံးပြုသူတွေဘက်ကို ထိခိုက်မှုတွေ ရှိလာစရာ အကြောင်း ရှိတော့မှာ မဟုတ်ပါဘူး။

အခုရေးသားထားတဲ့ Project ကို Jar File အဖြစ် Export လုပ်ပြီး အခြား Project တစ်ခုမှာ ပြန်ပြီး အသုံးပြုကြည့်ပါမယ်။


Using Module Library

ရှေ့မှာ ရေးသားထားတဲ့ hello-lib.jar File ကို အသုံးပြုဖို့ အတွက် Eclipse IDE နဲ့ hello-app ဆိုတဲ့ Java Project တစ်ခုကို တည်ဆောက်ပါတယ်။ Project Root Folder အောက်မှာ hello-lib.jar file ကို ထည့်ထား လိုက်ပါတယ်။

Module ကို Project ထဲကနေ အသုံးပြုဖို့ဆိုရင် Module Path ထဲမှာ သွားပြီး သတ်မှတ်ပေးရမှာ ဖြစ်ပါတယ်။

အထက်ပါအတိုင်း Module Path ထဲကို hello-lib.jar File ကို ဖြည့်စွက်ထားမှသာ Module Dependency အနေနဲ့ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

module com.jdc.hello.app {    
    requires com.jdc.hello.library;
}

Hello App project ရဲ့ Module Descriptor File ထဲမှာတော့ com.jdc.hello.library Module ကို အသုံးပြုမယ် ဆိုပြီး requires statement နဲ့ ရေးသားရပါမယ်။

တစ်ခုသတိထားဖို့လိုအပ်တာက Module Path ထဲမှာ Module Library File ကို ထည့်ထားတာနဲ့ အသုံးပြုလို့ရတာမဟုတ်ပါဘူး။ သုံးချင်တယ်ဆိုရင် အသုံးပြုမည့် Module တွေကို requires statement နဲ့ သတ်မှတ်ထားမှသာ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

public class UsingModuleDemo {

    public static void main(String[] args) {
        
        Hello hello = HelloFactory.getHello();
        String message = hello.sayHello("Jigsaw");
        System.out.println(message);
    }
}

Module Dependency တွေကို သတ်မှတ်ရေးသားပြီးပြီဆိုရင်တော့ Library ထဲက Export လုပ်ထားတဲ့ Class တွေကို အသုံးပြုရေးသားနိုင်မှာ ဖြစ်ပါတယ်။ HelloImpl Class မျိုးလို Library Module ကနေ Export မလုပ်ထားတဲ့ Class တွေကို သုံးမိရင်တော့ Compile Time မှာတင် Error ဖြစ်စေမှာ ဖြစ်ပါတယ်။

Backward Compatibility

Module Project တွေကို ရေးသားတဲ့ နေရာမှာ Module Library တွေကိုကော၊ Legacy Jar Library တွေကို ရေးသားအသုံးပြုနိုင်ဖို့လိုအပ်ပါတယ်။ အဲ့ဒီအတွက် Java Platform Module System က Automatic Module နဲ့ Unnamed Module တို့ကို ပြင်ဆင်ပေးထားပါတယ်။


Automatic Module

ရေးသားနေတဲ့ Project ရဲ့ Module Path ထဲကို Jar File တွေကို Unofficial Module အနေနဲ့ ထည့်သွင်း အသုံးပြုနိုင်ပါတယ်။ Module Name ကတော့ Jar File Name ဖြစ်လာမှာ ဖြစ်ပြီး၊ Automatic Module လို့ ခေါ်ဆိုပါတယ်။ Module Path ထဲကနေ Load လုပ်ထားတဲ့ Module တွေအားလုံးကို Automatic Modules အတွက် Full Read Access ကို ရရှိစေမှာ ဖြစ်ပါတယ်။


Unnamed Module

Class တွေ Jar Library တွေကို Module Path မဟုတ်ပဲ Class Path ထဲကို ထည့်ထားမယ်ဆိုရင် အဲ့ဒီ Class တွေအားလုံးကို Unnamed Module ထဲက Class တွေ အဖြစ် သတ်မှတ်သွားပါမယ်။ Module သုံးလို့မရတဲ့ Java Version နဲ့ ရေးသားထားတာတွေကို လက်ရှိ Module Project ထဲကို ထည့်သွင်း အသုံးပြုနိုင်အောင် စီစဉ်ထားတာလဲ ဖြစ်ပါတယ်။

ဤနည်းအားဖြင့် Module မပေါ်ခင်တုန်းက ရေးသားထားတဲ့ Library တွေကို Module Project တွေမှ အသုံးပြုနိုင်အောင် ပြင်ဆင်ပေးထားပါတယ်။

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

September 7, 2020

Custom Converters

ရှေ့အခန်းမှာ ဖေါ်ပြခဲ့သလို JSF Framework ဟာ Primitive Data Type နဲ့ သူတို့ရဲ့ Wrapper Type တွေ၊ Date တွေ၊ Enum တွေ နဲ့ Number တွေဆိုရင်တော့ Standard Converter တွေကို အသုံးပြုပြီး၊ Convert လုပ်တာတွေ Format လုပ်တာတွေကို လုပ်ဆောင်နိုင်ပါတယ်။ မိမိရေးသားထားတဲ့ Custom Object တွေကို Format လုပ်ချင်တဲ့ အခါ၊ ဒါမှမဟုတ် Request Parameter တွေကနေ ပြန်ပြီး Convert လုပ်ချင်တဲ့ အခါမျိုးတွေမှာ Custom Converter တွေကို ရေးသားအသုံးပြုနိုင်အောင်လဲ ပြင်ဆင်ထားပါတယ်။

Converter Interface

Custom Converter ကို ရေးသားတဲ့ နေရာမှာ JSF ရဲ့ အရင်ရေးသားပုံနဲ့လဲ​ ရေးသားနိုင်သလို၊ CDI Beans အနေနဲ့လဲ ရေးသားအသုံးပြုနိုင်ပါတယ်။ ဘယ်လိုပဲ ရေးရေး Converter အနေနဲ့ ရေးသားလိုတဲ့ Class ဟာ javax.faces.convert.Converter Interface ကို Implement လုပ်ပြီး ရေးသားရမှာ ဖြစ်ပါတယ်။

public interface Converter<T> {

	public T getAsObject(FacesContext context,
   	 	UIComponent component, String value);

	public String getAsString(FacesContext context,
   	 	UIComponent component, T value);   

}

Converter Interface ဟာ Generics Type Interface ဖြစ်တဲ့ အတွက်၊ Implement လုပ်တဲ့ အခါမှာ ဘယ် Type ကို Convert လုပ်ချင်လဲ ဆိုတာကို Type Parameter အနေနဲ့ သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်။ Converter Interface ထဲမှာ Abstract Method အနေနဲ့ ၂ ခုပါဝင်ပါတယ်။ အဲ့ဒီ Method တွေကတော့ getAsObject() Method နဲ့ getAsString() Method တို့ပဲဖြစ်ပါတယ်။


Parsing in Process Validations Phase

JSF View တစ်ခုကနေ Form ကို Submit လုပ်လိုက်တဲ့အခါမှာ Input Parameter တွေဟာ Request Parameter တွေအနေနဲ့ JSF Framework ထဲကို ရောက်ရှိလာမှာ ဖြစ်ပါတယ်။ JSF Life-cycle ရဲ့ Process Validation Phase ကို ရောက်တဲ့ အခါမှာ Request Parameter ထဲက String တန်ဖိုးတွေကနေ Component Value ရဲ့ Type အဖြစ်ပြောင်းဖို့ အတွက် Component တွေမှာ သတ်မှတ်ရေးသားထားတဲ့ Converter ရဲ့ getAsObject() Method ကို Invoke လုပ်ပြီး Spring ကနေ Component Value ဖြစ်အောင် Convert လုပ်ယူမှာ ဖြစ်ပါတယ်။

Converter ရဲ့ getAsObject() Method မှာ Argument ၃ ခုပါဝင်ပါတယ်။ ပထမ Argument ကတော့ FacesContext Object ဖြစ်ပြီး၊ Request Liife-cycle တစ်ခုလုံးမှာ သုံးဖို့လိုအပ်တဲ့ အရာအားလုံးကကို FacesContext Object ကနေ ရယူနိုင်ပါတယ်။ ဒုတိယ Argument ကတော့ UIComponent Object ဖြစ်ပြီး၊ လက်ရှိ Converter ကို အသုံးပြုနေတဲ့ UI Component Object ကို ကိုယ်စားပြုပါတယ်။ တတိယ Argument ကတော့ String Type ဖြစ်ပြီး Servlet Request Parameter ကို ကိုယ်စားပြုပါတယ်။

Return Type ကတော့ Generic Type ဖြစ်ပြီး Component Value ရဲ့ Type ဖြစ်လာပါမယ်။ ဒါ့ကြောင့် getAsObject() Method ထဲမှာတော့ Request Parameter ကို အသုံးပြုပြီး Component Value နေရာမှာ အသုံးပြုလိုတဲ့ Type အဖြစ် ဘယ်လို ပြောင်းမလဲ ဆိုတာကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။


Formatting in Render Response Phase

Converter ရဲ့ getAsString() Method ကိုတော့ JSF Runtime ဟာ Render Response Phase မှာ အသုံးပြုပါမယ်။ UI Component တွေရဲ့ Value တွေကနေ String အဖြစ် ပြောင်းတဲ့ အခါမှာလဲ Converter ကို အသုံးပြုပါတယ်။

Converter ရဲ့ getAsString() Method မှာ Argument ၃ ခုပါဝင်ပါတယ်။ ရှေ့မှာပါတဲ့ Argument ၂ ခုကတော့ FacesContext နဲ့ UiComponent Object တွေဖြစ်ကြပြီး getAsObject() Method မှာ ပါဝင်ခဲ့တာနဲ့ အတူတူပဲ​ဖြစ်ပါတယ်။ တတိယ Argument ကတော့ Type Parameter မှာ သတ်မှတ် ထားခဲ့တဲ့ Type ဖြစ်ပြီး၊ Component Value ကို ကိုယ်စားပြုပါတယ်။ ဒီ Method ထဲမှာတော့ Component Value ကနေ String အဖြစ်ပြောင်းတာကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။

ဒါ့ကြောင့် UI Output Component တွေမှာ Component Value တွေကို Format လုပ်ပြီး ပြချင်တယ် ဆိုရင်လဲ Converter တွေကိုအသုံးပြုရမှာ ဖြစ်ပါတယ်။ ပြီးရင် getAsString() Method ကို Override လုပ်ပြီး Component Value ကနေ String အဖြစ် ဘယ်လို Format ချမယ် ဆိုတာကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။

Custom Converter in Action

ရှေ့မှာ ဖေါ်ပြခဲ့သလို့ Converter တွေကို Input တန်ဖိုးတွေကို Parse လုပ်တဲ့ နေရာမှာလဲ အသုံးပြုနိုင်သလို Output တွေကို Format လုပ်တဲ့ နေရာတွေမှာလဲ အသုံးပြုနိုင်ပါတယ်။ ကဲ ကျွန်တော်တို့ Custom Converter တွေကို ဘယ်လို အခါတွေမှာ ရေးပြီး ဘယ်လို သုံးသွားကြမလဲ ဆိုတာကို ဒီနေရာမှာ လေ့လာသွား ကြပါမယ်။


Formatting Output Value

အရင်ဆုံး Formatter အနေနဲ့ အသုံးပြုသွားတဲ့ ပုံစံကနေ စပြီး ကြည့်သွားကြရအောင်။ ဘယ်လို နေရာမျိုး တွေမှာ Output အတွက် Format ချပေးချင်တာလဲ။ ဆိုကြပါစို့၊ မှတ်ပုံတင်နံပတ် ဒါမျိုးတွေကို ဖေါ်ပြတဲ့ နေရာတွေမှာ Input တုန်းက ယူတဲ့ ပုံစံက တစ်ခုချင်း ယူတာရှိချင်ရှိပါမယ်။ ဒါပေမဲ ပြန်ပြီး ဖေါ်ပြတဲ့ အခါမှာ ပုံစံတစ်မျိုးထဲဖေါ်ပြပေးရမှာ မျိုးတွေ ရှိလာတတ်ပါတယ်။ ဒီလို အခါမျိုးတွေမှာလဲ Converter တွေကို အသုံးပြုချင်လာမှာ ဖြစ်ပါတယ်။

ကျွန်တော်တို့ မှတ်ပုံတင် နံပါတ်ကို နမူနာထားပြီးကြည့်ကြရအောင်။

	12/YKN(N)006789

12 ဟာ တိုင်းဒေသကြီးကုဒ် ဖြစ်ပြီး၊ YKN ဟာ မြို့နယ်ကုဒ်ဖြစ်ပါတယ်။ တဖန် (N) ကတော့ နိုင်ငံသားကို ကိုယ်စားပြုတဲ့ ကုဒ်ဖြစ်ပြီး နောက်က ဂဏန်း ၆ လုံးကတော့ ID Number ဖြစ်ပါမယ်။

ဒါ့ကြောင့် Database ထဲမှာ သိမ်းမယ်ဆိုရင် STATE_CD, CITY_CD, TYPE, REGIST_NUMBER ဆိုပြီး Column လေးခုနဲ့ သိမ်းတာက SELECT လုပ်တဲ့ အခါမှာ ပိုပြီး လွယ်ကူစေမှာ ဖြစ်ပါတယ်။

public class NrcNumber {
    
    private String stateCode;
    private String cityCode;
    private String type;
    private int registNumber;

    // getter and setter
}

Java Class နဲ့ရေးမယ်ဆိုရင်လဲ အထက်ပါအတိုင်း Field တစ်ခုချင်းစီကို ကိုယ်စားပြုတဲ့ ပုံစံနဲ့ ရေးကြပါလိမ့်မယ်။ Program ထဲမှာတော့ အသုံးပြုရလွယ်တဲ့ ပုံစံနဲ့ ရေးကြမှာ ဖြစ်ပေမဲ့ တကယ်တမ်း UI မှာ ပြန်ပြတဲ့ အခါမှာ User က နားလည်လွယ်တဲ့ ပုံစံနဲ့ ပြန်ပြပေးဖို့လိုအပ်ပါတယ်။

@FacesConverter("com.jdc.NrcNumber")
public class NrcNumberFormatter implements Converter<NrcNumber>{

}

NrcNumberFormatter Class ကို Converter တစ်ခုအနေနဲ့ အသုံးပြုနိုင်ဖို့ အတွက် Converter Interface ကို Implement လုပ်ပြီး ရေးသားရမှာ ဖြစ်ပါတယ်။ Type Parameter အနေနဲ့ကတော့ Convert လုပ်လိုတဲ့ NrcNumber Class ကို အသုံးပြုပါတယ်။ နောက်တစ်ခုကတော့ @FacesConverter Annotation ကို တတ်ဆင်ရေးသားရပါမယ်။ “com.jdc.NrcNumber” ကတော့ Converter ID ဖြစ်လာပါမယ်။ ဒါကတော့ JSF ရဲ့ Converter ရေးသားပုံရေးသားနည်းဖြစ်ပါတယ်။

@Named
@Dependent
public class NrcNumberFormatter implements Converter<NrcNumber>{

}

အထက်ပါအတိုင်း CDI Scope တစ်ခုဖြစ်တဲ့ @Dependent Annotation နဲ့ @Named Annotation ကို တတ်ဆင်ရေးသားမယ်ဆိုရင်လဲ ရပါတယ်။ ဒါကတော့ CDI Bean တစ်ခုကို Converter အနေနဲ့ အသုံးပြု သွားတဲ့ ပုံစံဖြစ်ပါတယ်။ CDI ကို အသုံးပြုမယ်ဆိုရင် Dependency Injection ကို အသုံးပြုနိုင်မှာ ဖြစ်တဲ့အတွက် Converter ထဲမှာ Database ကို ချိတ်ဆက် အသုံးပြုလိုတဲ့ အခါမျိုးတွေမှာ CDI ပုံစံနဲ့ ရေးသားသင့်ပါတယ်။

NrcNumberFormatter Class ဟာ Converter Interface ကို Implement လုပ်လိုက်ပြီဆိုတာနဲ့ Converter ထဲမှာပါတဲ့ Abstract Method နှစ်ခုကို Override လုပ်ပြီး ရေးသားပေးရတော့မှာ ဖြစ်ပါတယ်။ လက်ရှိရေးသားနေတဲ့ Class ဟာ Output တွေကို Format လုပ်ဖို့သာ ရည်ရွယ်ရေးသားတဲ့ Class ဖြစ်တဲ့ အတွက် getAsObject() Method ထဲမှာ ဘာမှမရေးထားရင်လဲ ရပါတယ်။

ဒါပေမဲ့ getAsString() Method ထဲမှာတော့ Format လုပ်မည့် Logic တွေကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။ ဒီနေရာမှာတော့ NrcNumber Object ရဲ့ Fields တွေကို အသုံးပြုပြီး၊ မှတ်ပုံတင်နံပတ် တစ်ခုကို ဘယ်လို Format လုပ်မယ် ဆိုတာကို ရေးသားရပါမယ်။

@Override
public String getAsString(FacesContext context,
    UIComponent component, NrcNumber value) {
    
    if(null != value) {
   	 return String.format("%s / %s (%s) %06d",
   			 value.getStateCode(), value.getCityCode(),
   			 value.getType(), value.getRegistNumber());
    }
    
    return null;
}

Converter Class ကို ရေးသားပြီးပြီဆိုတာနဲ့ Output ပြမည့် Component တွေနေရာမှာ Converter ကို အသုံးပြုလို့ရပါပြီ။ Converter ကို ရေးသားထားတဲ့ ပုံစံအပေါ်မှာ မူတည်ပြီး မှာ သတ်မှတ်ရေးသားပုံဟာလဲ ကွဲပြားမှာ ဖြစ်ပါတယ်။ JSF ရဲ့ နဂိုပုံစံအတိုင်းရေးသားထားတယ်ဆိုရင် UI Converter ရဲ့ converter Attribute တန်ဖိုး၊ ဒါမှမဟုတ် Converter Tag ရဲ့ converterId Attribute တန်ဖိုးတွေမှာ converter id ကို String အနေနဲ့ သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်။


အထက်နမူနာကတော့ UIOutputText Component မှာ converter id ဖြစ်တဲ့ “com.jdc.NrcNumber” ကို converter attribute မှာ ရေးသားထားတာ ဖြစ်ပါတယ်။


    

အထက်ပါနမူနာကတော့ Converter Tag ရဲ့ converId Attribute ကို အသုံးပြုပြီးရေးသားထားတာ ဖြစ်ပါတယ်။


    

တကယ်လို့ Converter Class ကို CDI ပုံစံနဲ့ ရေးသားထားတယ်ဆိုရင်တော့ Binding Attribute ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။


Converting Input Values

UI Input Component တွေမှာလဲ Custom Converter တွေကို အသုံးပြုနိုင်ပါတယ်။ Select One Menu Component တွေမှာ Category တွေကို ရွေးချယ်ပြီး နောက်ကွယ်မှာ Category Object နဲ့ Bind ထားချင်တယ် ဆိုရင် Custom Converter တွေကို ရေးသားရတော့မှာ ဖြစ်ပါတယ်။

@Entity
public class Category implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    // getters, setters and serial version uid 

	// Override hashCode and equals method
}

အထက်ပါ Category Class ကတော့ Select One Menu မှာ အသုံးပြုမည့် Entity Class ဖြစ်ပါတယ်။


    

Select One Menu ကို အသုံးပြုမယ်ဆိုရင် Component Value တွေနဲ့လဲ Backing Bean မှာရှိတဲ့ Category Object နဲ့ Bind ဖို့လိုအပ်သလို Select Item မှာ ဖေါ်ပြဖို့လဲ Category List နဲ့ Bind ထားဖို့လိုအပ်ပါတယ်။

@Named
@Dependent
public class CategoryConverter implements Converter<Category>{
    
    @EJB
    private CategoryService service;

    // converter methods

}

Category Converter ကို ရေးသားတဲ့ နေရာမှာလဲ Request ထဲကနေရောက်လာတဲ့ Category ID ကို အသုံးပြုပြီး Database ထဲကနေ Category ကို ရှာဖွေပြီးပြန်ပေးဖို့လိုတဲ့ အတွက် CDI ပုံစံနဲ့ ရေးသား ရပါမယ်။ ဒါမှသာ EJB ဖြစ်တဲ့ CategoryService ကို Inject လုပ်လို့ရမှာ ဖြစ်ပါတယ်။

Product Edit View ကို ပထမဆုံးစပြီးဖေါ်ပြတဲ့ First Request မှာ Model ထဲကတန်ဖိုးတွေနဲ့ HTML ကို Create လုပ်တဲ့ အခါမှာ CategoryConverter ရဲ့ getAsString() Method ကို အသုံးပြုပြီး Select Items ထဲက Category တွေအားလုံးကိုကော Select One Menu ရဲ့ Value ကိုပါ Convert လုပ်ပါမယ်။

@Override
public String getAsString(FacesContext context,
   	 	UIComponent component, Category value) {
    
    if(null != value) {
   	 	return String.valueOf(value.getId());
    }
    
    return null;
}

ဒီနေရာမှာတော့ Category Object ရဲ့ ID ကို String အဖြစ်ပြောင်းပြီး Return ပြန်ပေးလိုက်ပါတယ်။ ဒါ့ကြောင့် HTML Select Tag ထဲမှာရှိတဲ့ Option Values တွေနေရာမှာ Category ID တွေကို String တွေ အနေနဲ့ ဖေါ်ပြပေးနိုင်မှာ ဖြစ်ပါတယ်။ ဒီလိုပဲ Select One Menu ရဲ့ Value ဖြစ်တဲ့ Category ရဲ့ ID နဲ့ တူတဲ့ Option ကိုလဲ Selected လို့ ဖေါ်ပြပေးနိုင်မှာ ဖြစ်ပါတယ်။

Product Edit Form ကို Submit လုပ်တဲ့ အခါမှာ Select မှာ ရွေးထားတဲ့ Option Value တစ်ခုက Requst Parameter အနေနဲ့ JSF Framework ထဲကို ရောက်ရှိလာမှာ ဖြစ်တယ်။ Option Value ဟာ Category ID ဖြစ်တဲ့ အတွက် Category ID ကနေ Category Object ဖြစ်အောင် Convert လုပ်ပေးရပါမယ်။

@Override
public Category getAsObject(FacesContext context,
   	 	UIComponent component, String value) {
   	 
    if(null != value && !value.isEmpty()) {
   	 int id = Integer.parseInt(value);
   	 return service.findById(id);
    }
    
    return null;
}

Request Parameter ကနေ Category Object ကို Convert လုပ်ဖို့အတွက်ကတော့ getAsObject() Method ကို အသုံးပြုပါမယ်။ ဒီနေရာမှာတော့ EJB ဖြစ်တဲ့ service Object ကို အသုံးပြုပြီး Category Object ကို Database ထဲကနေ သွားရှာပေးပါတယ်။

Database ထဲကနေရှာလာတဲ့ Category Object နဲ့ အရင်ပြထားတဲ့ Category List ထဲက Object တွေဟာ Create လုပ်တဲ့ အချိန်မတူပါဘူး။ အဓိပ္ပါယ်အရတူညီပေမဲ့ Object တွေမတူဘူးဆိုတာဖြစ်လာနိုင်တဲ့ အတွက် Category Class မှာ hashCode() နဲ့ equals() Method တွေကို Override လုပ်ထားဖို့လိုအပ်ရတာ ဖြစ်ပါတယ်။

ရေးသားထားတဲ့ CategoryConverter ဟာ CDI Bean ဖြစ်တဲ့ အတွက် UI Component မှာ Converter အနေနဲ့ ပြန်သုံးတဲ့ အခါ Converter Tag ရဲ့ binding attribute မှာ Binding Expression နဲ့ ရေးသားပေးရမှာ ဖြစ်ပါတယ်။


    
    

အထက်ပါအတိုင်း Select One Menu Component ထဲမှာ Nested Tag အနေနဲ့ Converter Tag ကို ရေးသားအသုံးပြုနိုင်ပါတယ်။

Input Component Value နဲ့ Backing Beans ထဲမှာ Bind ထားတဲ့ Type တွေ မတူညီခဲ့ရင်၊ ဒါမှဟုတ် Output မှာ Format လုပ်ပြီးပြသလိုတဲ့ အခါမျိုးမှာ Converter တွေကို ရေးသားအသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

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

September 5, 2020

Conversions

JSF Framework ကို အသုံးပြုနေတယ်ဆိုပေမဲ့ နောက်ကွယ်မှာတော့ Servlet ကိုသာ အသုံးပြုနေတာ ဖြစ်ပါတယ်။ JSF Framework ဖြစ်တဲ့ FacesServlet ဟာ Servlet တစ်ခုဖြစ်ပြီး Type 2 MVC ရဲ့ Front End Controller ကို ကိုယ်စားပြုပြီးရေးသားထားတာ ဖြစ်ပါတယ်။

Request တွေမှန်သမျှဟာ Front End Controller ဖြစ်တဲ့ FacesServlet ထဲကို ရောက်ရှိလာကြမှာ ဖြစ်ပါတယ်။ HTTP Servlet Request ရဲ့ Request Parameter တွေအားလုံးဟာ String Type အနေနဲ့ ရောက်ရှိလာမှာ ဖြစ်တဲ့ အတွက် JSF Framework ထဲရောက်လာတဲ့ အခါမှာ Model ထဲမှာ သတ်မှတ်ရေးသားထားတဲ့ Java Data Type တွေအဖြစ်ပြန်ပြီးပြောင်းလဲဖို့ လိုအပ်ပါတယ်။

တဖန် JSF Framework ကနေ Response ပြန်တော့မယ်ဆိုရင်လဲ View Object တွေကနေ HTML အဖြစ်ပြောင်းပြီး HTTP Servlet Response အဖြစ်ပြောင်းပေးဖို့လိုအပ်ပါတယ်။ ဒီနေရရာမှာလဲ HTML မှာ String တွေကိုသာ ဖေါ်ပြနိုင်တာ ဖြစ်တဲ့ အတွက် Model ထဲမှာရှိတဲ့ Java Data Type Value တွေကို String အဖြစ်ပြောင်းဖို့လိုအပ်ပါတယ်။

Request ရောက်လာတဲ့အခါ Request Parameter တွေကို String ကနေ သက်ဆိုင်ရာ Java Data Type တွေအဖြစ်ပြောင်းဖို့၊ တဖန် Response ကို Create လုပ်တဲ့ နေရာမှာလဲ Component Value တွေကို Java Data Type တွေကနေ String အဖြစ်ပြောင်းဖို့ Conversion တွေကို လုပ်ဆောင်စေတာဖြစ်ပါတယ်။

JSF Framework မှာ Conversion ကို လုပ်ဆောင်ဖို့အတွက် Build In Converters တွေကို ပြင်ဆင်ပေးထားသလို လိုအပ်လာရင် Custom ရေးသားနိုင်ဖို့ အတွက် Custom Converter တွေကိုလဲ ရေးသားနိုင်အောင် ပြင်ဆင်ပေးထားပါတယ်။

Build In Converters

JSF Framework တွေမှာရှိတဲ့ Component တွေဟာ View မှာရှိတဲ့ တန်ဖိုးတွေနဲ့ Model ထဲမှာရှိတဲ့ တန်ဖိုးတွေကို အလို်အလျောက် ပြောင်းပေးနိုင်အောင် ပြင်ပေးထားပါတယ်။ ဥပမာအားဖြင့် UISelectBoolean Component ရဲ့ value မှာ Model ထဲမှာရှိတဲ့ Boolean Type Variale နဲ့ Bind လုပ်ထားတယ်ဆိုရင် Request Parameter ထဲမှာရှိတဲ့ String တန်ဖိုးကနေ Boolean အဖြစ် ပြောင်းပေးနိုင်သလို၊ Model ထဲက Boolean တန်ဖိုးအလိုက် HTML မှာပြမည့် တန်ဖိုးကို ပြသပေးနိုင်ပါတယ်။

ဒီလိုဖေါ်ပြပေးနိုင်အောင် JSF Implementation တွေမှာ Standard Converter တွေကို ရေးသားပေး ထားကြပါတယ်။ JSF Standard Converter တွေကို javax.faces.convert Package အောက်မှာ ထားရှိပါတယ်။

Converter Converter ID
BigDecimalConverter javax.faces.BigDecimal
BIgIntegerConverter javax.faces.BigInteger
BooleanConverter javax.faces.Boolean
ByteConverter javax.faces.Byte
CharacterConverter javax.faces.Character
DateTimeConverter javax.faces.DateTime
DoubleConverter javax.faces.Double
EnumConverter javax.faces.Enum
FloatConverter javax.faces.Float
IntegerConverter javax.faces.Integer
LongConverter javax.faces.Long
NumberConverter javax.faces.Number
ShortConverter javax.faces.Short

အထက်ပါ Standard Converter ထဲမှာ DateTimeConverter နဲ့ NumberConverter တွေမှာ သူတို့ရဲ့ ကိုယ်ပိုင် Tags တွေကိုပိုင်ဆိုင်ကြပါတယ်။ သတ်မှတ်ထားတဲ့ Attribute တွေကို အသုံးပြုပြီး လိုအပ်သလို Format လုပ်တာတွေကို လုပ်ဆောင်နိုင်မှာ ဖြစ်ပါတယ်။ <f:convertDateTime /> နဲ့ <f:convertNumber /> Tags တွေကို အသုံးပြုပြီးရေးသားကြရမှာ ဖြစ်ပါတယ်။ တဖန် မိမိကိုယ်ပိုင် Custom Converter တွေကို ရေးသားအသုံးပြုချင်ရင်တော့ <f:converter /> ကို အသုံးပြုပြီး ရေးသားနိုင်ပါတယ်။


Using Standard Converter

မိမိရေးသားထားတဲ့ Component တွေမှာ Converter တွေကို အသုံးပြုလိုတယ်ဆိုရင် UI Component ရဲ့ converter attribute မှာလဲ အသုံးပြုလိုတဲ့ Converter ID ကို သတ်မှတ်ရေးသားနိုင်သလို၊ Nested Converter Tag ကို အသုံးပြုပြီးလဲ ရေးသားနိုင်ပါတယ်။

private BigInteger data;

public BigInteger getData() {
    return data;
}

public void setData(BigInteger data) {
    this.data = data;
}

UI Component ရဲ့ Value နဲ့ Bind လုပ်ဖို့အတွက် Backing Bean ရဲ့ Instance Variable မှာ Getter Setter တွေ ရေးသားထားဖို့လိုအပ်ပါတယ်။


အထက်ပါအတိုင်း <h:inputText /> Component ရဲ့ converter attribute မှာ Backing Beans ထဲမှာ Bind လုပ်မည့် Data Type ရဲ့ Converter ID ကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။


    

တဖန် <f:converter /> Tag ကို Input Text Component ရဲ့ Nested Tag အနေနဲ့ သတ်မှတ်ရေးသား အသုံးပြုနိုင်ပါတယ်။


    

Conversion Error ဖြစ်လာတဲ့ အခါမှာ Error Message ကို Custom ရေးသားလိုပါက Input Text Component ရဲ့ converterMessage Attribute မှာ သတ်မှတ်ရေးသားနိုင်မှာ ဖြစ်ပါတယ်။


Using Date Time Converter

Date, Calendar, Date Time တွေကို Component Data တွေမှာ အသုံးပြုလိုတယ်ဆိုရင် <f:convertDateTime /> Tag ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။

private LocalDate localDate = LocalDate.now();

public LocalDate getLocalDate() {
    return localDate;
}

public void setLocalDate(LocalDate localDate) {
    this.localDate = localDate;
}

အထက်ပါနမူနာမှာတော့ Java 8 ရဲ့ Date Time API ထဲက LocalDate ကို Model Data Type အနေနဲ့ အသုံးပြုထားပါတယ်။


    

LocalDate ကို အသုံးပြုထားတယ်ဆိုရင် type Attribute မှာ localDate လို့ ရေးသားဖေါ်ပြရန်လိုအပ်ပြီး၊ pattern attribute မှာတော့ မိမိဖေါ်ပြလိုတဲ့ Date Pattern ကို ရေးသားရမှာ ဖြစ်ပါတယ်။ Render Response Phase ရောက်ပြီး Component Value ကနေ HTML အဖြစ် ပြောင်းတဲ့ အခါမှာ သတ်မှတ်ထားတဲ့ Pattern အတိုင်း String အဖြစ် Format ချပြီး ပြန်ပေးမှာ ဖြစ်ပါတယ်။


    

အထက်ပါအတိုင်း Date Time Converter ကို UI Input Component ဖြစ်တဲ့ Tag မှာ တွဲဖက် ရေးသားထားတယ်ဆိုရင် Process Validation Phase မှာ Request Parameter ထဲကနေ ပါလာတဲ့ String တန်ဖိုးကနေ LocalDate အဖြစ် သတ်မှတ်ထားတဲ့ Pattern နဲ့ Parse လုပ်ပေးနိုင်မှာ ဖြစ်သလို၊ Render Response Phase မှာလဲ LocalDate ကနေ String အဖြစ် သတ်မှတ်ထားတဲ့ Pattern နဲ့ Formmat လုပ်ပေးနိင်မှာ ဖြစ်ပါတယ်။

Conversion မှာ Error ဖြစ်တဲ့ အခါ Custom Error Message ကို ရေးသားလိုတယ်ဆိုရင် အသုံးပြုမည့် UI Component ရဲ့ converterMessage attribute မှာ သတ်မှတ်ရေးသားနိုင်ပါတယ်။


Attribute of Date Time Converter

Date Time Converter တွေဟာ type, pattern တို့လို ကိုယ်ပိုင် Attribute တွေပါဝင်ပြီး Developer တွေကနေ Convert လုပ်တဲ့ အခါ Format လုပ်တဲ့အခါ ဘယ်လို လုပ်ရမယ်ဆိုတာကို သတ်မှတ်နိုင်အောင် ပြင်ဆင်ပေးထားပါတယ်။ Date Time Converter မှာ ပါဝင်တဲ့ Attribute တွေကတော့ အောက်ပါ အတိုင်း ဖြစ်ပါတယ်။

Attribute Type Description
binding DateTimeConverter Backing Bean Property နဲ့ Bind လုပ်လိုတဲ့ အခါ Unified EL Expression နဲ့ ရေးသားရပါမယ်။
dateStyle String Date Format ကို သတ်မှတ်လိုတဲ့ အခါမှာ ရေးသားရပါမယ်။
“default”, “short”, “medium”, “long”, “full” တို့ကို သတ်မှတ် ရေးသားနိုင်ပါတယ်။ ဘာမှ မရေးထားရင် “default” ကို အသုံးပြုပါမယ်။
for String Composite Component တွေမှာ Converter ကို အသုံးပြုလိုတဲ့ အခါ အသုံးပြုလိုတဲ့ Composite Component ထဲက Tag ကို သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်
locale String or Locale အသုံးပြုလိုတဲ့ Locale ကို သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်။ ဘာမှ မရေးထားရင်တော့ FacesContext ရဲ့ getLocale() Method ကနေရတဲ့ Locale ကို အသုံးပြုသွားမှာ ဖြစ်ပါတယ်
pattern String Custom Date Format ကို ရေးသားလိုတဲ့ အခါမှာ Pattern ကို ရေးသားနိုင်ပါတယ်။ Pattern ကို ရေးသားထားမယ်ဆိုရင် dateStyle, timeStyle မှာ ရေးသားထားတာတွေကို Ignore လုပ်သွားပါမယ်
timeStyle String Date Format ကို သတ်မှတ်လိုတဲ့ အခါမှာ ရေးသားရပါမယ်။
“default”, “short”, “medium”, “long”, “full” တို့ကို သတ်မှတ် ရေးသားနိုင်ပါတယ်။ ဘာမှ မရေးထားရင် “default” ကို အသုံးပြုပါမယ်။
timeZone String or TimeZone အသုံးပြုလိုတဲ့ Time Zone ကို သတ်မှတ်ရေးသား နိုင်ပါတယ်။
type String Parse ဒါမှမဟုတ် Format လုပ်တဲ့ အခါမှာ အသုံးပြု မည့် Type ကို ရေးသားပေးရပါမယ်။
both, date, time, localDate, localDateTime, localTime, offsetTime, offsetDateTime, or zonedDateTime ကို အသုံးပြုနိုင်ပါတယ်။

Using Number Converter

Component Value တွေနဲ့ java.lang.Number Type ကို Convert လုပ်ပြီး အသုံးပြုလိုတဲ့ အခါမှာ <f:convertNumber /> Tag ကို အသုံးပြုနိုင်ပါတယ်။

private long number = 10000;

public long getNumber() {
    return number;
}

public void setNumber(long number) {
    this.number = number;
}

အထက်နမူနာမှာတော့ Backing Bean ထဲမှာ long type Variable တစ်ခုကို ရေးသားထားပြီး Number Converter ကို နဲ့ Conversion ကို ပြုလုပ်သွားမှာ ဖြစ်ပါတယ်။ UI Output Component အတွက်ဆိုရင်တော့ Getter တစ်ခုသာလိုအပ်ပေမဲ့၊ UI Input Component တွေနဲ့ Bind လုပ်မယ် ဆိုရင်တော့ Getter ကော Setter ပါ ရေးသားထားဖို့လိုအပ်ပါတယ်။


    

အထက်ပါအတိုင်း <f:convertNumber /> Tag ရဲ့ pattern နေရာမှာ “$ #,##0” လို့ ရေးသားထားတဲ့ အတွက် Output ပြတဲ့ အခါမှာ အောက်ပါအတိုင်း ဖေါ်ပြသွားမှာ ဖြစ်ပါတယ်။

	$ 10,000

တဖန် Number တွေကို Currency Type အနေနဲ့ သတ်မှတ်ရေးသားလိုတဲ့ အခါမျိုးတွေမှာလဲ အောက်ပါ အတိုင်း ရေးသားနိုင်ပါတယ်။


    

Type Attribute မှာ “currency” လို့ ရေးသားပြီး currencyCode ဒါမှမဟုတ် currencySymbol နေရာမှာ မိမိအသုံးပြုလိုတဲ့ Currency ကို သတ်မှတ်ရေးသားနိုင်ပါတယ်။


Attributes of Nummber Converter

Number Converter မှာလဲ ကိုယ်ပိုင် Attribute တွေပိုင်ဆိုင်ပြီး နှစ်သက်ရာ Format နဲ့ Convert လုပ်မည့် Type ကို သတ်မှတ်နိုင်မှာ ဖြစ်ပါတယ်။

Attribute String Descriptions
binding NumberConverter Backing Bean Property နဲ့ Bind လုပ်လိုတဲ့ အခါ Unified EL Expression နဲ့ ရေးသားရပါမယ်။
currencyCode String Currency တွေကို Format လုပ်တဲ့ အခါမှာ အသုံးပြုမည့် ISO 4217 Currency Code ကို ရေးသားပေးရပါမယ်
currencySymbol String Currency တွေကို Format လုပ်တဲ့ အခါမှာ အသုံးပြုမည့် Currency Symbol ကို ရေးသားပေးရပါမယ်
for String Composite Component တွေမှာ Converter ကို အသုံးပြုလိုတဲ့ အခါ အသုံးပြုလိုတဲ့ Composite Component ထဲက Tag ကို သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်
groupingUsed Boolean Format လုပ်တဲ့ အခါမှာ Grouping separators ပါမပါ သတ်မှတ်ပေးနိုင်ပါတယ်
integerOnly Boolean Parse လုပ်တဲ့ အခါမှာ Integer အပိုင်းကို သာအသုံး ပြုမယ် ဆိုတာကို သတ်မှတ်ပေးနိုင်ပါတယ်
locale String or Locale အသုံးပြုလိုတဲ့ Locale ကို သတ်မှတ်ရေးသားပေးရမှာ ဖြစ်ပါတယ်။ ဘာမှ မရေးထားရင်တော့ FacesContext ရဲ့ getLocale() Method ကနေရတဲ့ Locale ကို အသုံးပြုသွားမှာ ဖြစ်ပါတယ်
maxFractionalDigits int အပြည့်ကိန်းနဲ့ ဒဿမကိန်းရဲ့ အများဆုံးနဲ့ အနဲဆုံး Digit ကို သတ်မှတ်လိုတဲ့ အခါမှာ ရေးသား အသုံးပြုနိုင်ပါတယ်
maxIntegerDigits int
minFractionalDigits int
minIntegerDigits int
pattern String Parse ဒါမှမဟုတ် Format လုပ်မည့် Pattern ကို ရေးသားပေးရပါတယ်
type String Parse ဒါမှမဟုတ် Format လုပ်မည့် ပုံစံကို ရေးပေးရပါတယ်။ number, currency ဒါမှမဟုတ် percentage တို့ကို အသုံးပြုနိုင်ပါတယ်။

Custom Object အတွက်လဲ Custom Converter တွေကို ရေးသားအသုံးပြုနိုင်အောင် ပြင်ဆင်ပေးထားပါသေးတယ်။ Custom Converter များအကြောင်းကိုတော့ နောက်တစ်ခေါက်မှာ ဖေါ်ပြသွားပါမယ်။

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

September 4, 2020

About Project Jigsaw

Java 8 ကို Release လုပ်ပြီးတဲ့နောက် Java Programming Language ကို ကြည့်မယ်ဆိုရင် နှစ်လွှာကွဲနေမယ်လို့ ခံစားရပါတယ်။ ဒါကတော့ ကျွန်တော်တစ်ယောက်ထဲရဲ့ ခံစားချက်ဖြစ်ပါတယ်။ Android ကို ရေးနေပြီး Java ကို အသုံးပြုနေသူတွေက Java 8 မတိုင်ခင်က Java ကို အသုံးပြုနေကြပြီး၊ Java ကိုယ်တိုင်ကတော့ Version တွေ အမျိုးမျိုးပြောင်းလဲ လာခဲ့ပါပြီ။

Android ကို ရေးသားသူတွေက Java 8 နောက်ပိုင်း New Feature တွေကို Kotlin Language ကို ပြောင်းသုံးပြီး ရေးလာနိုင်ခဲ့ပါတယ်။ ဒါပေမဲ့ Java ရဲ့ အဓိကပြောင်းလဲမှုဟာ Project Lambda တစ်ခုထဲမဟုတ် ပါဘူး။ Java သမိုင်းမှာ အကြီးမားဆုံးပြောင်းလဲမှုလို့ ပြောလို့ရတဲ့ ပြောင်းလဲမှုတစ်ခုဟာ Java 9 မှာလဲ ဖြစ်ပေါ်ခဲ့ပါတယ်။ အဲ့ဒါကတော့ Modular Java ပဲ ဖြစ်ပါတယ်။

Raise of Modular Java

Java 9 မှာ စတင် Release လုပ်ခဲ့တာကာ Java Platform Module System ဖြစ်ပါတယ်။ Java 9 ရောက်မှ Release လုပ်နိုင်ခဲ့တာဖြစ်ပေမဲ့ တကယ်တမ်း Java Platform မှာ Module System ကို အသုံးပြု နိုင်ရေး အတွက် ကြိုးစားလာခဲ့သည်မှာ ကြာခဲ့ပြီဖြစ်ပါတယ်။ ဘယ်လောက်ကြာသလဲ ဆိုတော့ လက်ရှိအနေအထားအရ Java သမိုင်းမှာ အချိန်အကြာဆုံး ကြိုးပမ်းမှုလို့တောင် ပြောလို့ရပါတယ်။

Java Platform မှာ Modular System ကို ထည့်သွင်းဖို့ကြိုးစားခဲ့သည့်မှာ Java 7 ကထဲက ဖြစ်ပါသည်။ ပြောရမည်ဆိုရင် ၂၀၀၉ ခုနှစ်ကထဲက ဒီကြိုးစားမှုကြီးစတင်ခဲ့ပါသည်။ ဒါဟာလဲ Project Jigsaw ရဲ့ အစ မူလဘူတ လို့ ပြောရမည်ဖြစ်ပါသည်။

တကယ်တော့ Java SE 5 Release လုပ်ခဲ့တဲ့ ၂၀၀၅ ခု မှာကျင်းပခဲ့တဲ့ Java One မှာ စခဲ့တယ်လို့ ပြောရင်လဲ ရနိုင်ပါသည်။ Java SE 5 ကို Release လုပ်တဲ့ Java One Session တစ်ခုမှာ C++ ရဲ့ friend Feature လိုဟာမျိုး Java မှာ ရှိသင့်တယ်မဟုတ်ဘူးလားလို့ မေးခွန်းတစ်ခုတက်လာခဲ့ပါသည်။ အဲ့ဒီအချိန်ကထဲက Java ပတ်ဝန်းကျင်မှာ Modular System ကို ရေးသားနိုင်ဖို့ လိုအပ်တယ်ဆိုတဲ့ အတွေးဟာ သန္ဓေတည်ခဲ့တယ်လို့ ပြောလို့ ရမှာ ဖြစ်ပါတယ်။ ပြောရမယ်ဆိုရင် အဲဒီအချိန်တုန်းက Java 9 မပြောနဲ့ Java 6 တွေ Java 7 တွေမှာ ဘာတွေပါမယ်ဆိုတာကို ဘယ်သူမှ မသိသေးတဲ့ အချိန်ဖြစ်ပါတယ်။


JSR 277 And JSR 294

Java One နောက်ပိုင်းဖြစ်တည်လာခဲ့တာကတော့ Modular System နဲ့ ပတ်သက်ပြီး JSR ၂ ခု ပေါ်ထွက် လာခဲ့ရပါတယ်။

  • JSR 227
    Java Module System
  • JSR 249
    Improved Modularity Support in the Java Programming Language

JSR 277 ရဲ့ Speac Lead ကတော့ Stanley Ho ဖြစ်ပြီး၊ jar file အစား အခြား Packaging System တစ်ခုကို အစားထိုးဖို့ ကြိုးစားခဲ့ကြတာ ဖြစ်ပါတယ်။ JAva Module File ဆိုပြီး jam ကို အသုံးပြုမလားဆိုပြီး ကြိုးစားခဲ့ကြတာဖြစ်ပါတယ်။ ဒါပေမဲ့ ကန့်ကွက်သူ အများရှိခဲ့တာကြောင့် အကောင်အထည်ဖေါ်လို့ မရခဲ့ပါဘူး။ ဒါ့ကြောင့် JSR 277 ကို 2008 ခု အရာက်မှာ Cancel လုပ်တော့မယ်လို့ သတ်မှတ်ခဲ့ကြပါတယ်။ တကယ်တမ်း တရားဝင် Cancel ဖြစ်ခဲ့တာကတော့ ၂၀၁၆ ခုကျမှ ဖြစ်ပါတယ်။

JSR 249 ကတော့ Alex Buckley က ဦီးဆောင်ခဲ့တာဖြစ်ပြီး package အထက်မှာရှိတဲ့ namespace ကို အသုံးပြုကြရအောင် ဆိုပြီး အဆိုပြုခဲ့ကြတာဖြစ်ပါတယ်။ အစကတော့ Super Package ဆိုတာကို အသုံးပြု ကြရအောင် ဆိုပြီးနောက်ပိုင်းမှာ Module အဖြစ် ပြောင်းလဲ လာခဲ့ကြတာ ဖြစ်ပါတယ်။

နောက်ဆုံး JSR 249 တစ်ခုသာ ကျန်ခဲ့ပြီး Packaging ကိုပါ ဘယ်လိုလုပ်မယ်ဆိုတာကို ထည့်သွင်း စဉ်းစားပြီး Project Jigsaw ကို စတင်ဖြစ်ခဲ့ကြတာဖြစ်ပါတယ်။


Project Jigsaw

Open JDK မှာ Project Jigsaw စပြီး ပါဝင်ခဲ့တာကတော့ ၂၀၀၉ ခုကျမှ ဖြစ်ပါတယ်။ JSR 277 နဲ့ JSR 294 က တော်ရုံနဲ့ သတ်မှတ်နိုင်ခြင်း မရှိတဲ့ အတွက် Java SE ရဲ့ Chief Architect ဖြစ်တဲ့ Mark Reihold က Specification သတ်မှတ်နိုင်ရေးနဲ့ Implementation ရေးသားနိုင်ရေးအတွက် Project Jigsaw ကို စတင် ဖွဲ့စည်းခဲ့ရတာ ဖြစ်ပါတယ်။

ဒါပေမဲ့ Project Jigsaw ဟာ ထင်ထားတဲ့ အတိုင်း ဖြစ်မလာခဲ့ပါဘူး။ Java SE 7 ထွက်လာတဲ့ အခါမှာလဲ Project Jigsaw ဟာ Sleep ဖြစ်ခဲ့သလို့ Java SE 8 ထွက်တဲ့ အခါမှာလဲ ပါမလာခဲ့ပါဘူး။ အဓိက အကြောင်းလို့ ပြောကြတာက ဘယ်အတိုင်းအတာအထိ Module System ကို သတ်မှတ်ကြမလဲ ဆိုတာကို ဆုံးဖြတ်လို့ မရနိုင်ခဲ့တဲ့ အတွက်လို့ ဆိုကြပါတယ်။

ဒီလိုနဲ့ JSR 249 ဟာလဲ Cancel ဖြစ်ခဲ့ပြီး JSR 376 Java Platform Modular System အဖြစ် Specification တွေကို အသစ်ပြန်လည် သတ်မှတ်ခဲ့ကြပါတယ်။ တော်ရုံနဲ့ Project Jigsaw ကို Release မလုပ်နိုင်တဲ့ အကြောင်းအရင်းအနေနဲ့ အပြောများကြတာကတော့ ဘယ်အတိုင်းအတာအထိ Modular System အဖြစ်ပြောင်းကြမှာလဲ ဆိုတာကို သတ်မှတ်လို့ မရနိုင်ခဲ့ကြလို့ဆိုပြီး အပြောများကြပါတယ်။

လက်ရှိအသုံးပြုနေတဲ့ Component Framework တစ်ခုဖြစ်တဲ့ OSGi နဲ့ ပတ်သက်ပြီး ဘယ်လို လုပ်ကြမလဲ၊ Module Repository နဲ့ Version Management ကိုကောဘယ်လိုလုပ်ကြမလဲ၊ ပြီတော့ လုပ်ကြပြီဆိုရင်တောင် ဘယ်အတိုင်းအတာအထိလုပ်ကြမလဲ ဆိုတာကို ဆုံးဖြတ်လို့ မရခဲ့လို့ဖြစ်ပါတယ်။

၂၀၁၄ ခု Java SE 8 ကို Release လုပ်တဲ့ အခါ Project Jigsaw ဟာ Sleep ဖြစ်ခဲ့ရပြန်တဲ့ အတွက် Project Jigsaw နဲ့ပတ်သက်ပြီး တောင်းဆိုမှုတွေဟာ ပိုပြီးများပျားလာပြီး Project Jigsaw ရဲ့ Draft Plan ကို သတ်မှတ်ခဲ့ကြပါတယ်။ ဒါ့ကြောင့်လဲ Project Jigsaw မှာလုပ်မယ်လို့ ရည်မှန်းထားတဲ့ Function တွေထဲက အနဲဆုံးအနေအထားကိုပဲ Release လုပ်တော့မယ်လို့ သတ်မှတ်ခဲ့ကြပုံရပါတယ်။ ဒီလိုနဲ့ Project Jigsaw ဟာ Java 9 နှင့်အတူ ၂၀၁၇ ခု စက်တင်ဘာလ ၂၁ ရက်နေ့မှာ Release လုပ်လာခဲ့ပါတော့တယ်။


Goals for Project Jigsaw

Project Jigsaw ကို စတင်ခဲ့တဲ့ အဓိက ရည်ရွယ်ချက်တွေကတော့ အောက်ပါအတိုင်းဖြစ်ပါတယ်။

  • Make it easier for developers to construct and maintain libraries and large applications
  • Improve the security and maintainability of Java SE Platform Implementations in general, and the JDK in particular
  • Enable improved application performance;
  • Enable the Java SE Platform, and the JDK, to scale down for use in small computing devices and dense cloud deployments
  • Project Jigsaw ရဲ့ Official Page မှာလဲ အသေးစိတ်လေ့လာနိုင်ပါတယ်။
    Open JDK Project Jigsaw Project

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