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 ტიპისა