Saturday, December 21, 2013

ProtoBuf & Thrift



Protocol Buffer არის გუგლის ენა  - მექანიზმი დასასერიალიზირებადი მონაემებისათვის. სხვა სიტყვებით რომ ვთქვათ, საშუალებას გვაძლევს მარტივად და სწრაფად ვიმუშაოთ სტრუქტურიზირებულ მონაცემებთან.  წარმოიდგინეთ XML დოკუმენტი. XML ზე უფრო პატარა გვაქვს  JSON. უფრო პატარას, უფრო სწრაფს და უფრო მარტივს კი გუგლის გვთავაზობს(binary არის ოღონდ).  ერთხელ ვწერთ, თუ როგორი სტრუქტურა გვინდა, შემდეგ კი შესაძლებლობა გვაქვს მონაცემები ჩავწეროთ ან წავიკითხოთ.  ამასთან გვაქვს საშუალება,  სხვადასხვა ენებში მუშაობისა - Java, C++,  Python.

ტესტირებისთვის ჯავას ობიექტი დავასერიალიზე, დაახლოებით 500 byte ზომის გამომივიდა, ProtoBuf ით კი ბაინარი დატა 50 byte.

ამ მექანიზმს, ვისაც ნანახი გაქვთ, Google App Engineც იყენებს, და სხვა გუგლის სერვისები. საკმაოდ ფართოდ გამოყენებადია.

ალტერნატივებიც არსებობს, მაგალითად  Apache Thrift, რომელიც FB-მ შექმნა. ორივე რაღაცით არის კარგი. მაგალითად Thrift ისგან განსხვავებით, პროტოკოლ ბუფერით დასერიალიზირებული მონაცემები 30% ით უფრო მცირე არის. სამაგიეროდ, Thrift-ს სტრუქტურა მეტად დახვეწილი აქვს, მაგალითად შესაძლებელია Map ის აღწერა. კიდე ერთი განსხვავება ის არის რომ Thrift ში პირდაპირ არის ინტეგრირებული RPC , პროტოკოლ ბუფერში კი ცალკე არის გატანილი. ენების მხრიბ Thrift-ს შემდეგ ენებთან აქვს მუშაობის შესაძლებლოვა: Thrift: Java, C++, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, OCaml, ხოლო რაც შეეხება protobuf-ს მხოლოდ Java, C++, Python. და ბოლოს, რაც მთავარია Protobuf ვრცელდება BSD ლიცენზიით, Thrift-ს კი Apache License ადევს.


Sunday, December 8, 2013

Mapping Persistent Objects

Mapping Persistent Objects

ამ სტატიაში ვისაუბრებთ თუ როგორ ხდება ენთით ბინების  რელაციურ ბაზაში მოთავსება. შევეცდები, ყველაზე მნიშვნელოვან საკითხებზე ვისაუბრო. რასაც ვერ მოვასწრებ, შემდეგ სტატიაში შემოგთავაზებთ. დავიწყოთ.

@javax.persistence.Entity
@Entity ანოტაცია ფერსისთენს პროვაიერს ეუბნება, რომ შესაბამისი კლასი უნდა შეინახოს ბაზაში. ასე გამოიყურება ეს ანოტაცია:

როგორც ვხედავთ, აქ გვაქვს name() მეთოდო მხოლოდ. თუ სახელს არ გადავცემთ , დეფაულთად აიღებს ბინის სახელს.

@javax.persistence.Id 
განსაზღვრავს, თუ კლასის რომელი ველი იყოს ბაზაში promary key.
პატარა მაგალითი:


შესაძლებელია XML შიც გავაკეთოთ იგივე (persistence.xml ში).
მაგალითად:

@javax.persistence.GeneratedValue
რაც შეეხება primary key ს, შეგვიძლია ჩვენ ჩვენთვითონვე განუსაზღვროთ, ან საშვალება მივცეთ რომ თვითონვე დაგენერირდეს.
ასე გამოიყურება ჩვენი შესაძლებლობები:

როგორც ვხედავთ, დეფაულთად AUTO გვიყენია. დანარჩენებზე 3 ზე, დეტალური გარჩევა შეგიძლიათ იხილოთ ამ ლინკზე. მარტივი მაგალითი:

@javax.persistence.Table
ენთითი მენეჯერს ვეუბნებით რომ შესაბამისი ანოტაციის მნიშვნელობა ეხება რელაციური ბაზის ცხრილს. კერძოდ მაგალითად ფხრილის სახელის განსასაზღვრავად.
მთლიანად კი ასე გამოიყურება:

@javax.persistence.Column
სვეტებზე სამუშაო ანოტაცია. სულ ეს მეთოდები გვაქვს:


რელიციური ბაზები ვინც იცის, ადვილად მიხვდება ყოველივეს. მაგალითად, name განსაზღვრავს სვეტის სახელს.  table გამოიყენებას ახლა არ გავნმარტავ დეტაულად, თორე სხვა თემაზე მომიწევს გადახტომა- კერძოდ Multitable მეფინგის დროს გამოიყენება. მაგალითად, თუ გვინდა რაღაც ველები პარალელურად სხვა ცხრილშიც ჩავწეროთ. VARCHAR ის ზომას length განსაზღვრავს. დანარჩენიც ადვილი მისახვედრია ვინც რელაციური ბაზები იცით და აღარ გავაგრძელებ.




@Basic and FetchType

@Basic  ანოტაცია არის დეფაულთი მონაცემების ჩამწერი შემდეგი ტიპის მონაცემებისთივს:  java.lang.String, byte[], Byte[], char[], Character[], java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time ,  java.sql.Timestamp .

არ არის საჭირო ჩვენ ვუთხრათ ფერსისთენს მენეჯერს თუ როგორ ჩაწეროს მონაცემები, ის ავტომატურად ჩაწერს ისე როგორც საჭიროდ ჩათვლის.

აგერ ვიხილოთ ჩაწერის სახეებიც.



თუ fetch() ატრიბუტი არის LAY, შესაბამისი ფროფერთის ინიციალიზება არ მოხდება მანამ, სანამ მასზე წვდომას არ მოვახდენთ.   თუმცა აქ ერთი დეტალია გასათვალისწინებელი, ზოგადად @basic ანოტაცია არ არის პირდაპირ და ცალსახად განმსაზღვრელი თუ როგორ ვამუშაოთ პროგრამა. ეს უფრო მიმათითებელი არის, რომელიც შესაძლოა შესრულდეს სხვანაერადაც. ზოგმა JPA -ს იმპლემენტაციამ შეიძლება ეს აღიქვას, როგორც პირდაპირ განსაზღვრულად, ზოგმა შეიძლება არა. ანუ იმას ვამბობ რომ შეიძლება LAZY მივუთითოთ მაგრამ ინიციალიზება მაინც გაუკეთოს( ანუ EAGRLY სავით მოიქცეს). ეს მხოლოდ იმიტომ , რომ ოპტიმიზაციის გამო კარგად იმუშაოს - თვითნ ხვდება რომელი არის უკეთესი.
მოვიყვანოთ მაგალითი

XML შიც შეიძლება იგივე გავაკეთოთ:

@Temporal

საშუალებას გვაძლევს, რომ დამატებითი ინფორმაცია მივცემთ ფერსისთენს პროვაიდერს java.util.Date ან java.util.Calendar ზე. ანუ ამ ანოტაციის წყალობით შეგვიძლია შევინახოთ ბაზაში DATE, TIME, TIMESTAMP. მაგალითად გვინდა შევინახოთ ენთითს შექმნის თაღირი. ამაზე მაგალითსაც შემოგთავაზებთ ქვემოთ (სათითაოდ რომ არ ვწერო @Lob ზე და @Enumarated-ზე, ერთად დავწერ).

@Lob

ზოგჯერ არის შემთხვევები, როდესაც დიდი ინფორმაცია გვაქვს შესანახი ბაზაში. ამისათვის JDBC ში არის, მაგალითად, სპეციალური ტიპები ობიექტებისთვის. მაგალითად, ჩვენ ვიცით რომ java.sql.Blob არის binary მონაემებისთვის, ხოლო java.sql.Clob არის character მონაცემებისათვის. javax.persistence.Lob ანოტაცია არის სწირედ იმისთვის რომ შევინახოთ ესეთი ტიპის დიდი მონაცემები. (მაქალითს ქვემოთ დავწერ)

 @Enumerated

ეს ანოტაცია საშვალებას გვაძლევს შევიანახოთ ენამის ტიპის მონაცემები ბაზაში.

ამ ბოლო სამ ანოტაციაზე მაგალითი კი ეს არის:

ახლა მოვრჩები წერას :) კიდევ აუცილებელი და მნიშვნელოვანი საკითხებია @Embeddable ობიექტები,   Primary-Key კლასები, რელაციები ბაზებს შორის და ასე შემდეგ.   როცა დრო მექნება გავაგრძელებ წერას:)


Monday, November 18, 2013

PRS MNG FlushModes

ამ სტატიაში ვისაუბრებთ FlushModeType-ზე.














ენამი გამოიყურება შემდეგნაირად:

public enum FlushModeType{
 AUTO,
 COMMIT
}

შესაბამისი მისამრთი:
################################
javax.persistence.FlushModeType
################################


იმის შემდეგ რაც persist(), merge(), remove() გამოვიყენებთ, ცვლილებები ბაზაში არ აისახება მანამ სანამ ენთითი მენეჯერი არ გააუკეთებს flush-ს. ჩვენ შეგვიძლია იძულებით მოვახდინოთ დასინქრონიზირება, თუ გამოვიყენებთ flush() მეთოდს. ზოგადად, დეფაულთად ისე არის კონფიგურირებული რომ, flush ხდება მაშინ, როდესაც ტრანზაქცია მთავრდება და ასევე მაშინაც, როდესაც რაიმე ქუერის ეგზექიუთს გავუკეთებთ - აქ დასაზუსტებელია query ში რას ვგულისხმობთ და რა გამონაკლისები არსებობს: მაგალითად, მოვახდინეთ რაიმე ობიექტის persist და შემდეგ find() ით დავაბრუნოთ შესაბამისი ობიექტი. შედეგი ის იქნება , რომ null დაგვიბრუნდება. find და getReference არიან ისეთი ტიპები, რომლებიც არ ახდენენ ბაზაში ცვლილებებს,
შესაბამისად, flush იც არ იქნება გამოძახებული, მის შესრულების შემდეგაც. აქ, getReference() ვახსენე, და ბარემ განვმარტავ რა განსხვავებაა ამათ შორის.

 განსხვავება იმაში მდგოამრეობს რომ თუ find() -ს ვიყენებთ, თუ ბაზაში შესაბამისი ჩანაწერი არ მოიძებნა null დაბრუნდება,  getReference()-ს შემთხვევაში  კი javax.persistence.EntityNotFoundException-ს ისრვრის.

როდესაც შეეხეაბაზ FlushModeType-ს, დეფაულთად AUTO აყენია. ყველაფერს თავისი გამოყენება აქვს, გააჩნია რა ამოცანა გავაქვს გადასაჭრელი, შესაბამისად შეიძლება AUTO გამოგვადგეს, შესაძლოა COMMIT. ამიტომაც გვაქვს setFlushMode(), რომლის საშუალებითაც შეგვიძლია ვაკონტროლოთ flush -ის მუშაობა. მაგალთად, თუ ბევრი აბდეიტებია გასაკეთებელი, შეგვიძლია ფერფორმენსის მიზნით აბდეიტი ერთ batch ში გავაკეთოთ, ამისთვის სწორედ COMMIT გვჭირდება. მოვიყვანოთ მაგალითიც.




Saturday, November 9, 2013

EX $PATH Linux

წარმოვიდგინოთ სიტვაცია როდესაც პროგრამა დავაყენეთ და კლასფასში არ ჩაჯდა, მაგალითად:
linux:~ #  aming-ng 

და გვეუბნება:

#If 'airmon-ng' is not a typo you can use 
command-not-found to lookup the package that contains it, 
like this:  cnf airmon-ng 


პრობლემა ორიდან ერთია, არ პროგრამა არ მიყენია ან კლასფასში არ მიზის[ხდებახოლმე].

მოვძებნოთ სად გვიგდია ჩვენი airmon - [ან თუ არის საერთოდ]

linux:~ #  find / -name airmon-ng
/usr/local/sbin/airmon-ng


ისე მოსაძებნად ესეც შეგვიიძლია

linux:~ #  locate airmon-ng 


   

კარგია, ახლა კლასფასი ვნახოთ:

 linux:~ #  echo $PATH
#/home/vakhoq/bin:/usr/local/bin
:/usr/bin:/sbin:/usr/sbin:/bin
:/usr/bin/X11:/usr/X11R6/bin
:/usr/games 



როგორც ჩანს ჩვენი პროგრამ არ ზის. ოკ ჩავსვათ მარტივად:

linux:~ #  export PATH=$PATH:/usr/local/sbin


სულ ეს იყო, შევამოწმოთ ფასი:

linux:~ # airmon-ng

და მივიღეთ აუთფუთი:
Interface       Chipset         Driver
wlan0                   ath9k - [phy0]

Tuesday, November 5, 2013

EJB PersistenceContextTypes



EJB 3.X ში გვაქვს extended persistence context და  მეორეა transaction-scoped.  თუ მეორეზე გვაქ საუბარი, ბინის ინსტანსი არის წვდომადი [managed] მანამ სანამ ტრანზაქციაში ვართ [ტრანზაქცია როგორც კი მორჩება, წვდომა აღარ გვექნება, ამ მდგოამრეობას detached-ს ვუწოდებთ]. ანუ როგორ კი ტრანზაქცია დამთავრდება პერსისთენს ობიექტები გახდეაბიან detached.

თუმცა სხვაგვარად გვაქვს საქმე  extended scoped კონტექსტში. მიუხედავად ტრანზაქციის დასრუელბისა, ენთითის ინსტანსი რჩება წვდომადი კვლავ - ყველა ობიექტის ისნტანცი რჩება წვდომადი.

ანუ ეს ორი ვარიანტი გვაქვს:

PersistenceContextType.EXTENDED
PersistenceContextType.TRANSACTION

მაგალითად, შევქმნათ Stateful (!)) ბინი.

@Stateful
public class ShoppingCartBean implements ShoppingCart{

   @PersistenceContext(type=PersistenceContextType.EXTENDED)
   EntityManager em; 

   private Account account

   public void addAccount(){
      account= new Account();
      account.setName("valhtang");
      account.setAge("21");
      em.persist(account)
   }


   public void updateAge(){
      account.setAge("22");
   }

}
თუ, EXTENDED არ გვექნებოდა, როდესაც addAccount შესრულდებოდა, ტრანზაქციაც მორჩებოდა, და updateAge სთვის შეცვლიდა მხოლოდ detached entity ინსტანსს, და რათმქაუნდა ეს ბაზაზე არ მოახდენდა გავლენას. ამ შემთხვევაში კი, ტრანზაქციის დასრულების შემდეგაც გვაქვს წვდომა.

kernel/debug/vgaswitcheroo


ლეპტოპობი, რომლებსაც ჰიბრიდული ვიდეო კარტა აქვთ [იგულისხმება, როდესაც  2 ვიდეო კარტა არის ლეპტოპზე, ძმლავრი მხოლოდ მაშინ ირთვება, როდესაც ამის რესურსი არის საჭირო. მიზანი ამ ვიდეო კარტების შექმნისა იყი ის რომ, დაეზოგად ბატარეის რესურსი. ცხადია GT 550 M რომ იყოს სულ ჩართული, ერთ საათიც არ დაჭირდება ბატარეა მთიანად რომ დასვას], საჭიროებენ ოპტიმიზაციას.

ერთერთი საშვალება ეკონომიის გასაკეთებლად არის პროექტი სახელად Bumblebee რომელიც რათქმაუნდა იდეალური არ არის, თუმცა ნელნელა ახალ ფუნქციონალურობას უმატებენ, და თანდათან უკეთესი ხდება. მეორე საშვალება კი ეს არის მექანიზმი კერნელისა, რომელსაც vga_switcheroo ვუწოდებთ. დავიწყოთ განხილვა:


vgaswitcheroo საშვალებით ადვილად შეგვიძლია ვაკნტროლოთ ჩვენი ვიდეოკარტების მუშაობა). vgaswitcheroo არის მექანიზმი კერნელში [ისე ზოგს სისტემა linux გონია, არადა მხოლოდ კერნელია ეს სისტემა კი Gnu/Linux] რომლის საშვალებითაც შეგვილია გადავერთოდ სხვადასხვა ვიდეოკარტებზე [ან ერთი გავთიშოთ ან მეორე და ასე შემდეგ]

იმის გასაგებად თუ რა ვიდეოკარტები გაქვთ შეგიძლიათ მარტივად მოვძებნოთ:

lspci | grep 'VGA'

და შედეგიც გვაქვს:
00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)
01:00.0 VGA compatible controller: NVIDIA Corporation GF108 [GeForce GT 540M] (rev ff)
შეგვიძლია ასეც შეცამოწმოთ ჩვენი ვიდეოკარტები:
lspci -vnn | grep '\''[030[02]\]'

-ეს მექანიზმი ყველა გნუ/ლინუქსში არის ჩადებული?
- გააჩნია ვიდეო კარტის რა დრაივერს იყენებს. მხოლოდ იმ შემთხვევაში არის თუ უფენსორს დრაივერს იყენებს სისტემა. კერძოდ nouveau, radeonს. თუ Nvidiaსას იყენებს ან fglrx-ს, მაშინ არ აქვს. და შეგვიძლა შევამოწმოთ კერნელში არის თუ არა ჩადებული შემდეგნაირად:

grep -i switcheroo /boot/config-*
CONFIG_VGA_SWITCHEROO=y




შეგვიძლია შევქმნათ სკრიპტი, რომელსაც ხელით გავუშვებთ ხოლმე.
vakhoq@linux:~> cd [dir]>
vakhoq@linux: [dir]>  touch hybrid.sh
vakhoq@linux: [dir]>  vi hybrid.sh

შიგნით ვწერთ მაგალითად ვიდეოკარტის გათიშვას.

###################################################
#!/bin/sh
# მხოლოდ გავთიშოთ მეტი არაფერი echo OFF > /sys/kernel/debug/vgaswitcheroo/switch ####################################################

ვინახავთ :wq საშვალებით. მოკლედ, Nvidia ვთიშავთ, რათა ინტეგრირებულზე იყოს მხოლოდ ჩვენი ლეპტოპი. (გაითვალისწინეთ ფერმიშენები იქნება საჭირო ამ სკრიპტის გასაშვებად. ამიტომ sudo ან su გამოიყენეთ)
პ.ს საერთოდოდ rc.local ში შეგიძლიათ ჩააგდოთ სკრიპტი. ან after.local  ში , გააჩნია რომელ დისტროს იყენებთ. rc.local უბუნტუში after.local კი OpenSuse ში).



ამასთან სტატუსების შემოწმება, თუ რა მდგომარეობაშია ჩვენი ვიდეო კარტა შეგვიძლია შემდეგნაირად:
cat /sys/kernel/debug/vgaswitcheroo/switch
შევამოწმოთ რამდენად ოპტიმალურია ჩვენი სამუშაო.

ამისთვის ჯერ ჩავთოთ/გამოვრთოთ ვიდეოკარტაზე წვდომა, შემდეგ სტატუსები გამოვაჩინოთ და acpi საშვალებით დროებიც ვნახოთ  (დებიანზე apt-get install acpi , suse  zypper install acpi და ასე შემდეგ)

#############################################################
vakhoq@Gnulinux:~> su
Password: ******

Gnulinux:/home/vakhoq# echo ON > /sys/kernel/debug/vgaswitcheroo/switch Gnulinux:/home/vakhoq # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0 linux:/home/vakhoq# acpi Battery 0: Discharging, 85%, 00:55:07 remaining
Gnulinux:/home/vakhoq# echo OFF > /sys/kernel/debug/vgaswitcheroo/switch Gnulinux:/home/vakhoq # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Off:0000:01:00.0 Gnulinux:/home/vakhoq# acpi Battery 0: Discharging, 85%, 01:35:12 remaining #############################################################


როგორც ხედავთ საკმაოდ კარგი შედეგები გვაქვს.
ახლა სათითაოდ განვამრტოთ რას ნიშნავს გამონატილი შედეგები
IGD - ნიშნავს Integrated Graphic Device (ძირითადად Intel)
DIS: denotes DIScrete graphic device (nVidia ან ATI)
+ რომელსაც უწერია, ნიშნავს რომ ის ვიდეოკარტაა აქტიური.
დანარჩენს აღარ გავნამრტავ, ისედაც ცხადია. :)

Monday, October 28, 2013

Jboss AS7, Datasource configuration

მოკლედ, დღეს ვისაუბრებთ Datasource configuration-ზე. კერძოდ mysql სერვერს დავუკონფიგურირებთ EJBს, რომელიც Jboss 7.1 ზე იქნება გაშვებული.


1) შევდივართ სერვერის  modules ფოლდერში და com\mysql\main ფოლდერში module.xml ში ვწერთ:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.mysql">
     <resources>
              <resource-root path="[connector-jar]"/>
     </resources>
     <dependencies>
             <module name="javax.api"/>
     </dependencies>
</module>

ამასთან აქვე ვაგდებთ mysql-connector-java-[version]-bin.jar -ს. დაგუგლეთ და გადმოწერეთ, დეტალური ინფორმაციისათვის ასევე just google

ყურადღება მიაქციეთ name="com.mysql" - იგივე გამეორდება დრაივერებში.


2) standalone\configuration-ში, ხსნით თქვენს შესაბამის standalone-[version].xml-ს(რომლითაც უშვებთ სერვერს - არ გავნმარტავ ამ თემას). აქ ვამატებთ დატასორსებში დრაივერს:              

 <driver name="mysqlDriver" module="com.mysql">
  <xa-datasource-class>com.mysql.jdbc.Driver</xa-datasource-class>
 </driver>

თვითონ დატასორსს აქ არ ვაგდებთ, განცალკევებით -ds.xml ფაილს გავაკეთებთ და დეპლოი ფოლდერში ჩავაგდებთ. თუმცა ასეც აკეთებ. მაგრამ დიზაინის მხრივ არ მიმაჩნია სწორე მიდგომად სტენდელოუნში კონფიგურაცია.


3) deployments ში ვაგდებთ [name]-ds.xml-ს:

<datasources>
      <datasource jndi-name="java:/MySQLDS" pool-name="MySQLDS" enabled="true" use-java-context="true">

                    <connection-url>
                         jdbc:mysql://localhost:3306/db
                     </connection-url>

                    <driver>mysqlDriver</driver>

                    <security>

                           <user-name>[usr]</user-name>
                           <password>[pass]</password>
                    </security>

       </datasource>
</datasources>




4) დავაკონფიგურიროთ ბაზასთან ჩვენი აპლიკაცია. მოკლედ შევდივართ ჩვენი აპლიკაციის ejbModule -ის META-INF ფოლდერში და ვქმნით persistence.xml-ს

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="JPADB">
  <jta-data-source>java:/MySQLDS</jta-data-source>
    <properties>
     <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
     <property name="showSql" value="true"/>
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
    </properties>
  </persistence-unit>
</persistence>
აღარ გავბმარტავ აქ persistence-unit რა არის, და property ების მნიშვნელობები რას ნინშავს jta-data-source სი. არსებობს გუგლი და დოკუმენტაცია ამისთვის :)





Saturday, October 26, 2013

lz init, dc locking, volatile


ამ სტატიაში ვისაუბრებთ შემდეგ თემებზე:
->lazy initialization
->Singleton
->double-checked locking
->volatile (JIT ში და ASM შიც)

Ok, lets start it!...

###  lazy initialization ####

lazy initialization არის ტაქტიკა, როდესაც თქვენ აფერხებთ ობიექტის შექმნას. ამასთან ომპიტიზაციასაც ვაკეთებთ.

class ResourceManager{ 
private Resource resource;
  public Resource getResource(){

    if ( resource == null ){
      resource = new Resource();
    }
    return resource;
  }
}

შევხედოთ სრდედების თვალით, რა შეიძლება მოხდეს. მოვიდა სრედი I , ნახა ობიექტი არის ნალი,  და შექმნა ობიექტი. ამასთან, II სრედმაც ნახა რომ null არის და შექმნა... თუ გვინდა, რომ ორივე სრედს ერთიდაიგივე instance ქონდეს, მაშინ  singleton დაგვჭირდება (ერთერთი GoF Design Pattern იდან).

### singleton Pattern ####
class Resource{
  private static Resource instance;
  public static Resource getInstance(){
    if ( instance == null){
      instance = new Resource();
    }
    return instance;
  }
}

როდესაც აქ მულტი სრედინგით დავიწყებთ ყურებას synchronized დაგჭირდება... მაგრამ, როდესა ერთ სრედი გაეშვება პრობლემა lock-ისა დაგვხვდება....  ამ პრობლემის გადასაჭრელად Double-Checked Locking პატერნი გამოვიყენოთ...

### Double-Checked Locking ###
ამ შემთხვევაში, მეთოდები არ არიან დასინქრონიზირებულები (წინა შემთხვევაში გვქონდა და ლოქის პრობლემა გვქონდა),
არამედ ინსტანსის შექმნის კოდი ჩაჯდება სინქრონიზაციის ბლოკში.


class Resource{

  private static Resource instance;
  public static Resource getInstance(){
    if ( instance == null ){
      synchronized(Resource.class){
        if ( instance == null ){
          instance = new Resource();
        }
      }
    }
    return instance;
  }
}

თუ ერთი სრედი შესული არის სინქრონიზაიის ბლოკში, სხვები დაელოდებიან სანამ ინიციალიზება არ მოხდება.

პრობლემა ისაა რომ ინიიალიზება და ობიექტის შექმნა სხვადასხვა ადგილასაა. ანუ , პრობლემა ისაა, რომ ერთი სრედი სანამ სინქრონიზაციის ბლოკშია, მეორე როდესაც შემოვა  ( და ამასთან იმის გამო რომ instancce==null), ეს სრედი  ეცდება შექმნას ობიექტი... ოოპს! გავიჭედეთ! stuck in the desert! - ფიქრის შედეგად აღმოვაჩენთ , რომ ის არ არის რაც ჩვენ გვიდნა. ნუ, თუ არ ვიფიქრეთ ვერც აღმოვაჩენთ.

(პ.ს ისე ამაზე ინფო დეტალურად Java Concurrency in Practice წიგნში შეგიძლიათ წაიკითხოთ, ეს არის ძალიან ძალიან მაგარი წიგნი, და ყველა პროგტამისტს უნდა ქონდეს წაკითხული. ამაზონზე თან სულ ახლახანს გაიაფდა).

აბა პრობლემას როგორ გადაჭრით? რამდენიმე გზა არსებობს. აი იმ წიგნში მე რომელიც გითხარით, იქ ნახავთ დაწვრილებით ისე ყველაფერს. უცბათ ერთერთ გზას შემოგთავაზებთ:

class Resource{

  private static class ResourceHolder{
    static final Resource instance = new Resource();
  }

  public static Resource getInstance(){
    return ResourceHolder.instance;
  }

}

მოდით გავაგრძელოთ და ეგრედ წოდებული volatile ზე გადავიდეთ და თან ამ თემასაც დავუკავშირებთ.

მოკლედ, იმისათვის რომ volatile ზე ვისაუბროთ, ჯერ ჯავას memory model უნდა ვიცოდეთ, თუ როგორ მუშაობს -  ყველა სრედი, ჯავაში, გამოიყოფს თავის ცალკეულ ადგილს მემორიდან. ანუ თუ კვენ ერთ სტორიჯს გამოვუყობთ ყველაფერს ეშველება - გავიხარებთ ყველანი. ანუ ვიპოვეთ გზა რითიც Virtual Mahine-ს ვაიძულებთ რომ არ შექმნას ტემპორარი კოპოიოები ცვლადების. (მოკლედ, ბევრს აღარ გავაგრძელებ, სიღრმისეულია ეს თემა, და atomc variable ზე ბევრი რამეს დაწერა შეილება - სალაპარაკოს რა გამოლევს, დრო ვთქათ თორე...)

პატარა მგალით მოვიყვანოთ. წარმოიდგინეთ ორი სრედი, ერთში ცვლადს ენიჭება მნიშვნელობა, მეორეშ სრედში ამ ცვლადს ვკითხულობთ პირდაპირ. ეს შეილება მარტივად გამოვიყენოთ სრედის გაჩერებაშიც  (რათქმაუნდა interruptი შეგიძლიათ), მხოლოდ loop დაგვჭირდება.

public void run(){
 while(stop!=true){
  // სრედი არ კვდება
 }
}
ვიზუალურადაც ვაჩვენოთ. ორი სრედი. როდესაც ერთში შეიცვლება მნიშვნელობა, მეორე იგივე STORE დან იღებს. მოკლედ ASM ში როგორ არის იმას დაბლა დავწერ. ჯერ ეს საკმარისია.



ასეთი რამეც შეიძლება გავაკეთოთ (აქაც იგივე გავაკეთე, პროსტა,  ობიექტის რასაც ვანიჭებთ  volatile  არის. სხვა არაფერი). ანუ დარწმუნებული ვართ რომ თუ ერთმა სრედმა მნიშვნელობა მიანიჭა ცვლადს, მეორე ცვლადში ეგრევე აისახება.

class Foo {

  private volatile Helper helper = null;
  public Helper getHelper() {
    if (helper == null) {
      synchronized(this) {
        if (helper == null) {
          helper = new Helper();
        }
      }
    }
  return helper;
}


ახლა JIT ში რახდება ის ვნახოთ. რაც არ უნდა იყს, ვერ გავექცევით, JIT ში ომპტიმიზაცია ასე მოხდება

while (test.loop == true) ;

// გადავა შემდეგ კოდში =>

if (test.loop) { while (true); }


ოკ, და რეალურად მთლიანი STORE შეინახება EAX რეგისტრში.


volatile მდე იქნებოდა:
00000068  test        eax,eax 
0000006a  jne         00000068 

//შემდეგ კი 

00000064  cmp         byte ptr [eax+4],0 
00000068  jne         00000064 

ყოველი სრედი, იგივე მემორიდან ამოიღებს ცვლადის მნიშვნელბოას  (ptr [eax+4])


რა კითხვებიც გექნებად დაწერეთ, არ მოგერიდოთ! :-)

Friday, August 30, 2013

OpenSource Contribution




OpenSource კარგი მექანიზმია, მნიშვნელობა დიდად "შეიძლება" არ აქვს  პროგრამას  Apache License ადევს,  LGPL,  MIT  თუ სხვა- თუმცა ესეც საკამათო თემაა. GPL მაქსიმალურად სცილობს არ არსებობდეს პროგრამა კოდის გარეშე (მაშინ როდესაც შეგიძლია ლოკალური ცვლილებები Apache-ს ლიცენზიით გააკეთო და შენთან დაიტოვო) - რიჩარ სტელმანის მიზანიც Security დან გამომდინარე ის იყო, რომ ყოფილიყო ინტერნეტ სიცრცეში Freedom.  პირადად მე GNU-ს მამას ვეთახმები ამ საკითხსი, და მისი ლიცენზიის პირობებიც ნამდვილად მომწონს.




ერთერთი ყველაზე კარგი გმაოცდილება   პროგრამისტისთვის არის ღია კოდის პროექტებში მონაწილეობაა. აქ მკაცრად დაცულია კოდის სტილი, დიზაინ პატერნები, უფრო მეტიც თავად დაშორებები სიმბოლოებს შორისაც.  

ესენი კი არის ჩემი PATCH ები აპაჩეს პროექტში:

https://issues.apache.org/jira/secure/attachment/12597305/PDFBOX-1690.patch
https://issues.apache.org/jira/secure/attachment/12611618/VisibleSignature.patch
https://issues.apache.org/jira/secure/attachment/12613577/fixed.patch

https://issues.apache.org/jira/secure/attachment/12623115/TSATimeSignature.patch

Friday, August 23, 2013

JVM -D option

JVM ეშვება სისტემ properties ებთან ერთად. ჩვენ კი შეგვიძლია ისინი დავაკონფიგურიროთ -D პარამეტრით. მაგალითად, აპლიკაციის გასაშვება თუ გვინდა პროქსის გავლით, შეგვიძლია მარტივად დავწეროთ:



ან მაგალითად JNLP ვუშვებთ ჯივიემის პარამეტერებით:

ჩვენი კოდიდან კი თუ გვინდა მნიშვნელობის ამოღება:
System.getProperty("developmentMode");

Friday, July 12, 2013

EJB Timer Service API

Timer Service API.


Timer Service ის გამოსაყენებლად იმპლემენტაცია უნდა გავუკეთოთ javax.ejb.TimedObject ინტერფეისს, რომელშიც აღწერილია ქოლბექ მეთოდი ejbTimeout( ):



EJB  ში შეგვიძლია @javax.ejb.Timeout ანოტაციაც დავადოთ მეთოდს, რომელიც voidს აბრუნებს, და ექნება  javax.ejb.Timer პარამეტრი.
აქვე ორივეს ვნახავთ


ალტერნატივა  არი @javax.ejb.Timeout ანოტაცია:


}


იმისათვის რომ დავარეგისტრიროთ ბინი  დროის პერიოდში TimerService –ს ვიყენებთ. TimerService შეგვიძლია inject გავუკეთოთ @javax.annotation.Resource ით ან EJBContext იდან წამოვიღოთ.


ანუ ეს ორი ვარიანტი გვაქვს:
@Resourceprivate SessionContext ctx; ctx.getTimerService();
@Resource javax.ejb.TimerService timerService;


მაგალითად დარეგისტრირებისთვის შევქმნათ  CalendarTimer, ან შეგვილია პირდაპირ IntervalTimer, ანაც SingleActionTimer იც აქვს. დეტალურად API ში შეგიძლიათ ნახოთ, რა რას აკეთებს, აქ რო არ დავწყო მე პოემების წერა. აგერ ლინკიც:  http://docs.oracle.com/javaee/6/api/javax/ejb/TimerService.html  -  Just Google :-)



ტაიმერის წაშლაც ადვილადაა შესაძლებელი, პირდაპირ cancell() მეთოდი აქვს.


აგერ ერთი მაგალითიც  CalendarTimer–ის.



მოლკედ მთავარი მუღამი ისაა, რომ თუ სერვერი დარესტარტდება ან რამე მაგდაგვარი, ტაიმერრი თავის დროს მაინც გააგრძელებს მუშაობას. ანუ რომ შეხვიდეთ Jboss ის ფოლდერში, მაგალითად : /usr/jboss/standalone/data/timer-service-data ფოლდერში
მანდ ნახავთ თქვენს ობიექტებს ტაიმერისას.

რაც შეეხება EJB 3.1 აქ უკვე არის @Schedule ანოტაცია. ძალიან მარტიავად



აგერ XML ითაც შეგვიძლია გავაკეთოთ იგივე @Schedule რომ არ ვწეროთ:


ეს XML კი META-INF ში ჩავაგდოდ – Deployს მერე jar ის META_INF ში ჩახტება;



Thursday, May 23, 2013

Inversion of Control


 შეიელბა ასე გავმარტოთ. Inversion of Control (IoC) და Dependency Injection (DI) პატერნები არიან ყველანი იმისათვის რომ დეფენდენსები არ გქონდეთ თქვენს კოდზე და არხდებოდეს კოდის განმეორებები.  კოდის ოპტიმიზაცი ყოველთვის პრიორიტირებულია ჩვენთვის. ოპტიმიზაციის მთარავი მიზანიც ის არის რომ კოდი ლამაზად და გასაგებად ეწეროს, და ყველაზე მთავარი რაცაა არ ხდებოდის კოდის ხშირი გამეორებები, როდესაც მცირე რამეა შესაცვლელი.

ერთერთი მაგალითი ასეთი შეიძლება მოვიყვანოთ.

გვაქვს List რაღაც A ტიპის ობიექტებით სავსე და მინდა მისი გადაყვანა Map ში. შემდეგ ვაკეთებ ისევ სიას, ოღონდ B ტიპის ობიექტებით სავსეს და მინდა მისი გადაყვანა კვლავ Map ში. ამ შემთხვევაში შეგვიძლია მხოლოდ ერთი მეთოდი გვქონდეს გადაყვანის, არ ვაკეთოთ ტიპებით overload ები. თუ ასეთი 10 ტიპის ობიექტი მექნება, 10 overload არ გავაკეთებ.

მაგალითად, გვაქვს კლასი წიგნებისა.

შევავსოთ იგი:

ახლა დაგვჭირდება ერთი ინტერფეისი, რომელშიც მეთოდის პროტოტიპს ჩავწერთ – მეფითა keyს ამოღებისა. მთავარი პრობლემა ჩვენ ის გვაქვს რომ არ ვიცით ობიექტის key რა იყოს (ზოგ შემთხვევაში რა არის, ზოგში რა). ამიტომ თითოეული ობიექტისათვის გავაკეთოთ კლასი, რომელიც იმპლემენტაციას გაუკეთებს KeyFinder–ს.

მაგალითად ინტერფეისი:


და ჩვენი წიგნებისთვის გვექნება იმპლემენტაცია შემდეგნაირი, თუ Id გვინდა იყოს მეფსი key.


და გვექნება მხოლოდ ერთი მეთოდი, ზოგადი. რომელსაც გადაეცემა სია ნებსმიერი ტიპისა. და ინტერფეისი რომ გავაკეთეთ KeyFinder, აქაც განზოგადებული ტიპებით. მოხდება Mapის შექმნა. შემდეგ გადავუვლით ყველა ელემენტს სიაში, და
სათითაოდ ამოვიღებთ გასაღებს,

კოდს თუ დააკვირდებით ,  KeyFinder   finder გვაქვს, სადაც  KeyFinder ინტერფეისი არის.  resolver აქვს რეფერენსი რომელიმე კლასის ობიექტთან , რომელსიც აკეთებს ინტერფეისი იმპლემენტაციას ––> მას აქვს Overriden მეთოდი გასაღების ამოღებისა ––> მისი დახმარებით , სწორედ ამ ტიპის კლასის ობიექტიდან როგორ ამოვიღოთ გასაღები ვიცით.

თუ დავამატებთ მაგალითად მანქანების კლას. დაგვჭირდება უბრალოდ   CarKeyFinder -ის დაწერა რომელიც იმპლემენტაციას გაუკეთებს KeyFinder-ს. ან მეორე ვარიანტი ისაა რომ პირადპირ მანქანის კლასმა გაუკეთოს იმპლემენტაცია KeyFinder–ს და ცალკე არ გავიტანოთ - ნუ, გემოვნების ამბებია.




MVN Manifest Entries

თუ აღმოჩნდა რომ manifest ფაილის კონფოგურაციისათვის Maven–ის სტანდარტული პარამეტრები არ გყოფნით, იმისათვის რომ manifest თგვენს გემოზე ააწყოთ (თქვენი საკუთარი ველები დაუმატოთ), ამისთვის მავენს აქვს <manifestEntries>  ტეგი.  გამოყენება მარტივია:
<manifestEntries>
      <YOURTAG> value </YOURTAG>
</manifestEntries>

იხილეთ მაგალითაი:

შედეგი კი გვენქება დაახლოებით ასეთი.

Monday, May 20, 2013

Strategy Pattern

Stragegy patern.   ასევე ლიტერატურაში შეიძლება შეგხვდეს მისი სახელწოდეა როგორც  Policy pattern. მისი საშვალებით ალგორითმის ქცევის არჩევა ძალზედ მარტივად ხდება. იმას, თუ რომელი ალგორითმი იქნება გამოყენებული, კლიენტი განსაზღვრავს.

 დამავწყდა მეთქვა, რომ, ეს დიზაინ პატერნი Creational pattern ოჯხს განეკუთნება.

ამ დიზაინ პატერნის სტრუქტურა ასეთია:




როგორც სურათზე ხედავთ, გვაქვს სტრატეგიის ინტერფეისი, რომელთა მრავალი იმპლემენტაცია შეილება გვქონდეს–  მაგალითად გვინდა Payment ის შესრულება. იგი შეიძლება შესრულდეს Visa ელექტრონით, შეიძლება MasterCard -ით.

ალგორითმი უსმენს კლიენტს და იმ იმპლემენტაციას უშვებს რომელიც მოთხოვნას შეესაბამება. მოსმენას და შესაბამის სტრატეგის ალგორითმის გამოძახებას Context  ემსახურება.

დავიწყოთ მაგალითის წერა, და  თან განვმარტოთ. თავდაპირველად, გადახდისთვის გავაკეთოთ enum, რომლებითაც იქნება შესაძლებელი გადახდა. შემდეგ ამ ენამიდან რომელიმეს Context–ს გადავცემთ.  თუ სხვა ჯერზე ფეიმენთის გაკეთება  გადახდის სხვა ტიპით მომინდება, უბრალოდ  კონტექტს ვეტყვი ამ ყოველივეს.



PaymentContext, რომელიც განსაზღვრავს რომელი implement გაუშვას. აქ მარტივადაა ყველაფერი, switch ით ვნსაზღვრავ საჭიროს. როდესაც კონტესტის ობიექტს შევქმნი, კონსტრუქტორშივე ვახდენ შესაბამისი მეთოდის მინიჭებას.


PaymentRule ინტეფეისი ,რომლის შვილებიც იქნებიან კონკრეტული იმპლემენტაციები. ჩვენს შემთვევაში ერთი მასტერქარდთან მომუშავე, მეორე ვიზა ელექტრონთან. სწორედ კონტექსტში  PaymentRule  შვილის რომელიმე ობიექტს ვქმნი (switch ებში), და ვანიჭებ paymentRuleს, რომელიც არის PaymentRule   ტიპისა.


ახლა დავწეროთ კონკრეტული სტრატეგიის იმპლემენტაციები.

ეს VisaElectron იმპლემენტაცია.  ეს კი უკვე MasterCard–ის:


საბოლოოდ კი ყველაფერი ძალიან მარტივი გვაქ.

Tuesday, February 19, 2013

Dash panel


ახალი გრაფიკული გარემო და პრობლემები.
Gnu/linux -ში, კერძოდ ახალ დისტრო UBUNTU ში, სადაც დიდიხანია ახალი გრაფიკული გარემო გვაქვს, იქმნება პრობლემები Dash panel–ზე იკონკების დაგდებისა. მაგალითად თუ პროგრამას დააინსტალირებთ სინაპტიკიდან პრობლემა არ შეგექმნებათ, მაგრამ როდესაც ხელით აინსტალირებთ... შექმენი *.desktop ფაილი /usr/share/applications/ ში. gksudo gedit /usr/share/applications/სახელი.desktop ბ) შიგნით კი რაიმე ამის მზგავსი უნდ აგააკეთოთ:
[Desktop Entry] Type=Application Terminal=false Icon=/path/to/icon/icon.svg Name=give-name-here Exec=/path/to/file/executable Name=unmount-mount
 ჩემ შემთხვევაში არის ეს:


    [Desktop Entry]
    Type=Application
    Terminal=false
    Icon=/home/vakhoq/EclipseEE/e2.png
    Name=Eclipse EE
    Exec=/home/vakhoq/EclipseEE/eclipse Name=Eclipse EE



მერე Dash Home ში შედით და იქიდან გადმოგაგდეთ თქვენი პროგრამა. სულ ესაა :–)

Cross-domain communication problems


Cross-domain communication 


პრობლემა რიმლისათვისაც ბევრი framework არის დაწერილი, როგორებიცაა მგალითად easyxdm, YUI. მაგრამ საქმე გაცილებით გამარტივდა როდესაც HTML 5 თან გვაქვს უკვე საქმე. 


მაგალითად ავიღოთ 2 დომეინი A.net და B.net. გვინდა მათ შორის გვქონდეს კომუნიკაცია.

XmlHttpRequest ობიექტს ადევს   security  ბრაუზერებისაგან, რომელიც კრძალავს  მიწვდეს მონაცემებს სხვა სერვერზე. ეს კი  Ajax developer ებისთვის სერიოზული ლიმიტია.

წარმოვიდგინოთ გვინდა ასეთი სტრუქტორა. ჩვენ ფეიჯ  A.net ზე გვაქვს iframe რომელშიც არის B.net ის გვერდი. ახლა კი გვინდა კომუნიკაციები მათ შორის. მაგალითად , უმარტივესი, თუ დავაკლიკეთ iframe–ს შიგნით რაიმე ღილაკს, გვინდა A.net ის ფეიჯზე დაფიქსირდეეს და მათ შორის Request -Response კომუნიკაციები გავმართოთ.

ასეთი სტრუქტურები მრავლად არის პრაქტიკაში. მაგალითად Chrome Extension–ს რომ ვწერდი Gmail–ისთვის, მეილის გვერდზე როდესაც ვაწვებოდი Signe Document კნოპკას,  უნდა გამოსულიყო Iframe ჩემი სერვერის. აქ უნდა მქონოდა Listener ები გვერდებზე და Request-responze კომუნიკაციები ჩემ სერვლეტსა და extension -ს შორის.


HTML5-ს შემოთავაზებული გზა ასეთია , ვიძახებთ window.postMessage()-ს რომელსა ორი პარამეტრი გადაეცემა. 1 სტრუქტურა რაც გვინდა გადავცეთ და 2–ე არის მიმღები (ან * ყველასთვის);



  1. stuct=new Object();
  2. stuct.owner="admin";
  3. stuct.status="cancell";
  4. parent.postMessage(struct, "https://mail.google.com"
და მიმღები უსმენს მას:
  1. window.addEventListener("message", function( event ) {
  2. if ( event.data.status === "cancell" ) {
  3. console.log(event.origin)
  4. }
  5. }, false );
მაგალითად iframe ში რაღაცას რო დავაწვები, სერვერზე რო წამოვიდეს პასუხი:
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <script>
  5. var send= function(){
  6. // Post message
  7. // from Iframe Page to domain A
  8. parent.postMessage("FROM IFRAME ","http://a.net");
  9. }
  10. </script>
  11. </head>
  12. <body>
  13. INSODE
  14. <button onclick="send()">Inside The iframe</button>
  15.  
  16. <script>
  17. // Listen from Domain A
  18. window.addEventListener('message', function(event) {
  19. console.log(event.data+' : '+event.origin) ;
  20. }, false);
  21.  
  22. </script>
  23. </body>
  24. </html>
  25.  
  26.  
  27. <!DOCTYPE HTML>
  28. <html>
  29. <head>
  30. <script>
  31. function sendCommand() {
  32. // post massage to domain B
  33. var receiver =
          document.getElementById('frameId').contentWindow;
  34. receiver.postMessage("MSG", 'http://b.net');
  35. }
  36.  
  37. function load (){
  38. // Leasten messages from Domain B
  39. window.addEventListener('message', function(event) {
  40. console.log(event.data+' : '+event.origin) ;
  41. return;
  42. }, false);
  43. }
  44. </script>
  45. </head>
  46. <body onload="load()">
  47. <iframe id="frameId" src="http://b.net/2.html" onload="sendCommand();"> No Frame!</iframe>
  48. <button onclick="sendCommand()">OutSide The Frame</button>
  49. </body>
  50. </html>
რაც შეეხება Request-Response–ბს. ჰედერში მოგიწევთ Access-Control-Allow-Origin ის ჩამატება.

მაგალითად სერვლეტებში
  1. protected void doPost(HttpServletRequest request, HttpServletResponse response) {
  2. response.addHeader("Access-Control-Allow-Origin","UR");
  3. ...
  4. }
 Ajax–ში თუ გვინდა ჰედერში ასე ჩავამატებთ.
  1. var xhr = new XMLHttpRequest();
  2. xhr.open("GET", url, true);
  3. xhr.responseType = "arraybuffer";
  4. xhr.setRequestHeader('Access-Control-Allow-Origin', 'URL');
XDomainRequest object  არის, რომელიც IE სთვის. CORS–ს გვთავაზობს Firefox. რომელიც ყველა ბრაუზერში კარგადაა.


  1. function createCORSRequest(method, url){
  2. var xhr = new XMLHttpRequest();
  3. if ("withCredentials" in xhr){
  4. xhr.open(method, url, true);
  5. } else if (typeof XDomainRequest != "undefined"){
  6. xhr = new XDomainRequest();
  7. xhr.open(method, url);
  8. } else {
  9. xhr = null;
  10. }
  11. return xhr;
  12. }
თორემ გამოვარდება ბრაუზერისგან შეცდომა:
XMLHttpRequest cannot load http://b.net/.../. Origin https://a.net is not allowed by Access-Control-Allow-Origin.


Sunday, January 27, 2013

Bridge Pattern

Bridge Pattern 

ვიდეოში  მაქ ახსნილი ეს პატერნი როგორ მუშაობს. ვიდეოს ხარისხიანად სანახავად HD ხარისხი აირჩიეთ.

Saturday, January 26, 2013

Java Service Loader




JDK 1.1  მა შემოგვთავაზა მექანიზმი, რომლითაც ჩვენ შეგვიცლია JDBC driver დავამათოთ უბრალოდ  სწორი Class ის დალოადებით.   მაგალითად, შეგვიძლია JDBC-ODBC დრაივერი დავალოადოთ Class.forName ის  დახმარებით.   Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")

Java 6 დან მოყოლებული ჩვენ შეგვიძლია უკვე java.util.ServiceLoader ის გამოყენება. ჩვენ ვიყენებთ  META-INF/services/ დირექტორიას, სადაც ვინახავთ იმპლემენტაციების სერვისებს - ფაილს ,  რომელის სახელი არის interface -ის მისამართი (package  +ClassName), მასში კი წერია  კონკრეტული იმპლემენტაციის მისამართი (package  +ClassName);

მაგალითად JDBC-ODBC  driver თან წვდომა თუ გვინდა, ამ შემთხვევაში ჩვენ აღარ გვჭირდება  Class.forName()-თი დალოადება (instance რომ ავიღოთ).  JRE/lib/resources.jar შეიცავს META-INF/services/java.sql.Driver ფაილს  (java.sql.Driver არის interface) , რომელშიც ერთი ხაზია  sun.jdbc.odbc.JdbcOdbcDriver.  ამ დროს ServiceLoader დაუვლის ყველა jar ფაილს, რომელიც  კლას path ში აქვს მითითებული, და  ყველა შესაძლო დრაივერებს იპოვის (თუ მოიძენა ასეთი).

მაგალითად, ჩვენ თუ გვინდა MS SQL-ის ბაზასთან წვდომა, ჩვენ მისი jar უნდა მივაბათ ჩვენს პროექტს კლას path ში. ან დერბიზე მაგალითად derby.jar და დრაივერი ავტომატურად იქნება წვდომადი ჩვენთვის.

ეს მექანიზმი ეხება ყველა სერვისს, და არა მხოლოდ JDBC-ს. მაგალითად თუ გვინდა   JRuby სკრიპტი  გამოვიძახოთ ჯავადან, ჯვენ მხოლოდ jar ფაილს მივაბამთ, რომელიც შეიცავს  META-INF/services/javax.ScriptEngineFactory ფაილს.  ეს უზრუნველყოფს შესაბამისი სკრიპტის  დალოადებას VM -ში.

მგალითად, გავაკეთოთ შემდეგი რამ. დავწეროთ ინტერფეისი Upload Service-სი. მის იმპლემეტაციებიც ბევრი შესაძლებელია გვქონდეს. მაგალითად აპლუადო google Drive-თი, ან Drop Box ით.   თუ მომხმარებელი ახალ იმპლემენტაციას დაამატებს, მას მხოლოდ JAR ფაილის  მიმატება მოუწევს კოდში (path). ანუ Plug In ების პონტში გვაქვს.



პირველრიგში ინტერფეისს ვაკეთებთ.

package ge.storage.remote
public interface FileStorage {
 . . . 
 void deleteFile(RemoteFile fileData) throws IOException; 
 void createFolder(RemoteDirectory directory) throws IOException; 
 . . . 
 boolean isProviderOf(String Name);

}
შემდეგ იმპლემენტაციებს, მაგალითად google სას (იმპლემენტაციის jar დაგვჭრდება მერე. რომ მივაბათ კლასფასში)
 
package ge.storage.google
public class GoogleStorage implements FileStorage {
  @override
  public boolean isProviderOf(String Name) {
  // გადმოვცემთ სტრინს და ვეუბნებით არის თუ არა ეს იმპლემენტაცია
  // მოთხოვნისა. თუ DropBox მოგვთხოვეს, Google -ს შესბამისად ხომ
  // არ დავუბრუნებთ
  }
  . . .
}


აქ ჩვენ ახლა გვინდა  META-INF/services/ge.storage.remote.FileStorage ფაილი, რომელიც შეიცავს ტექსტს ge.storage.google.GoogleStorage ს.


ახლა კი ვითრევთ ჩვენს სერვისებს. აქ უქვე  პროექტს დეფენენსი ინტერფეისზე გვინდა.
 
ServiceLoader<FileStorage > Services = ServiceLoader.load(FileStorage.class); 
    for (FileStorage service : Services) {
       if (service.isProviderOf(name)) {
         return service;
        }
 }

თუ მოთხოვნაა google-სი, და მისი jar მიბმულია. service.isProviderOf(name) დაგვიბრუნებს ჩვენს სერვისს. შედეგად კი, გვაქ იმ იმპლემენტაციასთან წვდომა  რომელიც ჩვენ გვინდოდა.

ესეიგი ჩვენი პროექტი უყურებს მხოლოდ ინტერფეისს და არა რომელიმე იმპლემენტაციას ინტერფეისიას. ხოლო თუ რომელი jarიქნება მიბმული ფასზე, მის მიხედვით აირჩევა შესაბამისი იმპლემენტაცია.


.net ში service loader-ს აქ შემდეგი სახე:

  1. Assembly asm = Assembly.
  2. LoadFrom(@"c:\myapp\plugins\myAssembly.dll");
  3. MyInterface IMy = null;
  4. foreach (Type t in asm.GetTypes()) {
  5. if (t.GetInterface("MyInterface") != null) {
  6. IMy = (MyInterface)Activator.CreateInstance(t);
  7. break;
  8. }
  9. }




Friday, January 25, 2013

Inside JSP 'n Servlet




სტატიკური და დინამიური გვერდები
თუ მონაცემები ფორმიდან იგზავნება ჩვეულებრივ HTML გვერდზე, არანაერი გზა არ არსებობს მონაცემების ამოღებისა ამ გვერდიდან. ანუ ვგულისხმობ რომ, თუ html გვერდზე იგზავნება მონაცემები, მისი დამამუშავებელი იქ არავინ გვყავს, რადგან ეს სტატიკური გვერდია, და არა დინამიური . იმისთვის რომ ამ მონაცემების დამუშავება შევძლოთ ერთერთი ვარიანტია რომ გვერდი იყოს JSP,  ან Servlet, რომელიც განთავსებული იქნება Web Application-ში.




აპლიკაციის მდებარეობა
აპლიკაცია გაშვებული უნდა იქნას servlet მანქანისგან. შესაბამისად მისი მდებარეობას განსაზღვრავს თვითონ მანქანა. მაგალითად Tomcat ის შემთხვევაში webapps დირექტორია გვაქვს.


აპლიკაციის სტრუქტურა
თუ სტრუქტურაში ჩავიხედებით შეგხვდება WEB-INF , რომელიც web.xml-ს შეიცავ. Web Application-ში ერთერთი ყველაზე მნიშნელოვანი ფაილია web.xml რომელსაც ვიყენებთ ვებ აპლიკაციის ინიციალიზებისთვის.   ეს დირექტორია არ არის პირდაპირ წვდომადი გარედან. შესაბამისად მხოლოდ სერვერს შეეძლება წვდომა– იმ ფაილებს მოვათავსებთ, რომლებსაც არგვინდა რომ ვინმე მიწვდეს პირდაპირ. WEB-INF/lib - სადაც jar თავსდება. root-მხოლოდ ეს დირექტორიაა წვდომადი ინტერნეტიდან.

JSP ანუ Java Servlet Page
JSP გამოიყურება როგორც HTML ტეგები, თუმცა მათ აქვთ შესაძლებლობა ცონტექსტის გენერირების. JSP შეგვიძლია როგორც აბსტრაქცია აღვიქვათ, რადგან ისინი საბოლოოდ იქნებიან გადაყვანილნი servlet ებში. ტრანსლატორი რომელსაც გადაყვანის ფუნქცია ევალება ეს არის servlet engine. Servlet კი თავად   ჯავას კოდს შეიცავს.  Servlet engine-მ იცის როგორ გაუკეთოს execute სერვლეტს და JSP–ს.






Request
ვებ სერვერებმა იციან როგორ წამოიღონ სტატიკური კონტენტი , მაგრამ ჭირდებათ სხვა პროგრამები, რომლებსაც ექნებათ წვდომა დინამიურ კონტენტთან. თუ request მოხდება სერვერზე JSP–სი, სერვერი მოთხოვნა უნდა გუაგზავნოს პროგრამას რომელიც შეძლებს მის დასრულებას. მაგალითად თუ form ში გვაქ დატა ჩაწერილი, და მას ვაგზავნით JSP ზე, ამ დროს Servlet engine-მ  უნდა დაიიჭიროს და დაასრულოს მოთხოვნა. დეტალურად ქვემოთ ვისაუბრებთ.


როდესაც ფორმა შეივსება request იქმნება ბრაუზერიდან ვებ სერვერის მიმართლებით. ვებ სერვერი ხვდება რომ ეს .jsp ფაილია, და ამიტომ იძახებს Servlet Engine–ს, რომელიც შეძლებს მასთან მუშაობას. ადმინისტრატორმა უნდა დააკონფიგურიროს ვებ სერვერი ისე, რომ ჯოველი jsp ფაილი მივიდეს Servlet Engine–სთან.  თუ ის ადგილი, სადაც მოთხოვნა გავაგზავნეთ სტატიკური გვერდია, response დაბრუნდება პირდაპირ ბრაუზერში. და თუ დინამიური გვერდია სერვერი გააგზავნის response ინფორმაციას Servlet Engine–სთან. Servlet Engine  კი   აბრუნებს response–ს ბრაუზერისკენ.



Servlet Engine Reponse
რაც შეეხება დეტალურად სერვლეტ ენჯინის რისპონს, აქ შემდეგი ნაბიჯები გვაქვს.
1 თავიდან უნდა მოხდეს JSP–ს გადაყვანა Servlet–ებში. თან ინახავს გადაყვანილ JSP–ს კოპიოს თავისთან, რადგან ყოველ მოთხოვნაზე არ მოუხდეს მისი ხელახლა გადაყვანა. ენჯინი მხოლოდ მაშინ შექმნის სერვლეტს, თუ არ არსებობს იგი, ან როდესაც მოდიფიკაცი ამოხდება JSP სორსში.

2 შემდეგი ნაბიჯი არის დალოადება სერვლეტის. იგი ლოადდება მემორიში პირველივე რექუესთზე.  ესეიგი, სერვლეტის .class ფაილი თავსდება მყარ დისკზე, პირველი რექუესთს შემდეგ და ლოადდება მემორიში. იმისშემდეგ რაც მემორიშია ელოდება გამოძაღებებს მის მეთოდებზე. სისწრაფის გამო თითოეული რექუესთის დამთავრების შემდგომ არ იშლება იგი.

დავამატებდი ვებ სერვერი უგზავნის ინფპორმაციას, რომელიც ბრაუზერიდან მიიღო, სერვლეტ ინჯინს. და ასევე რისფონს ინფორმაციასაც. შემდეგ კი სეტრვლეტ ენჯინი რისფონსს უბრუნებს ბრუზერს. ანუ რისფონსის და რექუესტის, ორივეს ინფორმაცია, ეგზავნება სერველეტ ენჯინს. სერვლეტი იღებს ამ ინფორმაციას და აკეთებს ორ ობიექტს, ერთი რომელიც ახდენს ენკაფსულაციას რექუესტ ინფორმაციისას, და მეორე რომელიც ახდენს ენკაფსულაციას რისფონს ინფორმაციისას. ეს ორი ებიექტი არის სულ, რომელიც არის საჭირო ბრაუზერთან კომუნიკაციისათვის.



3 რისპონსი მთავრდება _jspServices–მეთოდში.


მეთოდს ორი პარამეტრი აქვს, რექუესთი და რისპონსი. ეს პარამეტრები ის მეთოდებია რომლების სერვლეტის მანქანამ გააკეთა რექუესთ მონაცემებიდან, რომელიც იყო გამოგზავნილი ბრაუზერიდან და ასევე რისპონს მონაცემებიდან, რომელიც იყო გადმოსროლილი ვებ სერვერისგან. ეს ობიექტები არიან
  javax.servlet.http.HttpServletRequest და javax. servlet.http.HttpServletResponse ტიპისა