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