5 Ekim 2015 Pazartesi

SQL Join Tipleri

Not : Join'lerin nasıl çalıştığını anlamak için Visual Representation of SQL Joins çok iyi bir kaynak.

Kartezyen Çarpım - Cartesian Product
Join'lerden önce kartezyen çarpımı bilmek gerekiyor. Cartesian kelimesi sanırım Rene Descartes'in soyadı ile ilgili bir kelime.
Kabaca bir tablodaki tüm satırların diğer tablodaki tüm satırlar ile yanyana koyulması şekilnde düşünülebilir.

left_01
, 1 left_02, 1 right_01, 1 right_02, 1 right_03, 1 left_01 joins to right_01 using key 1 left_01 joins to right_02 using key 1 left_01 joins to right_03 using key 1 left_02 joins to right_01 using key 1 left_02 joins to right_02 using key 1 left_02 joins to right_03 using key 1

Aslında kartezyen çarpımın kombinasyon ile aynı şey olduğu görülebilir. İç içe döngülerden ibarettir.
IEnumerable<string> basket1 = new List<string> {...};
IEnumerable<string> basket2 = new List<string> {...};
IEnumerable<string> basket3 = new List<string> {...};

foreach (var item1 in basket1)
foreach (var item2 in basket2)
foreach (var item3 in basket3)
{
 Console.WriteLine("{0}, {1}, {2}", item1, item2, item3);
}

Many to Many (M:M) İlişki
M:M ilişki için en az 3 tane tablo gerekir. Car, Property isimli iki tablo olsun. CarProperty isimli bir ara tablo ile iki tablo birbirine bağlanır.

Inner Join - A ve B'nin kesişimi
Inner Join yazısına taşıdım

Left Outer Join - A + A ve B Kesişimi
Örnek
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*,b.*  from a,b where a.a = b.b(+);

a |  b
--+-----
1 | null
2 | null
3 |    3
4 |    4
Full Outer Join - A + B
Örnek
select * from a FULL OUTER JOIN b on a.a = b.b;

 a   |  b
-----+-----
   1 | null
   2 | null
   3 |    3
   4 |    4
null |    6
null |    5





4 Ekim 2015 Pazar

Windows Registry

Windows Registry Nedir?
Ağaç şeklinde bir veritabanıdır. Kullanıması artık pek tavsiye edilmiyor. Bazı sebepler şöyle.
  • The registry is a single point of failure. That's why every single registry editing tip you'll ever find starts with a big fat screaming disclaimer about how you can break your computer with regedit.
  • The registry is opaque and binary. As much as I dislike the angle bracket tax, at least XML config files are reasonably human-readable, and they allow as many comments as you see fit.
  • The registry has to be in sync with the filesystem. Delete an application without "uninstalling" it and you're left with stale registry cruft. Or if an app has a poorly written uninstaller. The filesystem is no longer the statement of record-- it has to be kept in sync with the registry somehow. It's a total violation of the DRY principle.
  • The registry is monolithic. Let's say you wanted to move an application to a different path on your machine, or even to a different machine altogether. Good luck extracting the relevant settings for that one particular application from the giant registry tarball. A given application typically has dozens of settings strewn all over the registry.

Hive Nedir?
Windows Registry konu başlıklarına bölünmüş. Başlıklara da Hive (kovan) ismi verilmiş.


Temel hive'lar şunlar.
HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, HKEY_USERS

HKEY_CURRENT_USER
Giriş yapmış kullanıcı hakkında bilgi saklayan kovan.

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
sadece bir kere çalışmasını istediğimiz iş için kullanılır.

HKEY_USERS
Kullanıcılar hakkında bilgi saklayan kovan.

Registry Sınıfı
LocalMachine View
Şöyle kullanırız.
Registry.LocalMachine;

DeleteSubKey metodu
Örnek
var hklm = Microsoft.Win32.Registry.LocalMachine;
var subkey = hklm.OpenSubKey("Software\\Wow6432Node\\WindowsApplication1", true);
subkey.DeleteSubKey("Status");
DeleteSubKeyTree metodu
Örnek:
Registry.CurrentUser.DeleteSubKeyTree("Test9999");
DeleteValue metodu
Örnek
string keyName = @"Software\Microsoft\Windows\CurrentVersion\Run";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
{
  key.DeleteValue("MyApp");
}
RegistryKey Sınıfı
OpenBaseKey metodu
Bir key şöyle açılır.
RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)




REST API Tasarımı - Naming Conventions

Giriş
Bu yazıdaki başlıkları buradan aldım.

Kısaca
1. REST isimlerinde noun kullanmak gerekir. İsimlerin çoğul olması iyidir.  Şöyle yaparız
# Kötü
http://api.example.com/v1/store/CreateItems/{item-id} 
#İyi
http://api.example.com/v1/store/items/{item-id}
Eğer isimler çok uzunda çizgi karakteri ile ayrılabilir. Şöyle yaparız
http://api.example.com/v1/store/vendor-management/{vendor-id} http://api.example.com/v1/store/item-management/{item-id}/product-type http://api.example.com/v1/store/inventory-management
HTT Verb'leri REST isminde kullanılmaz.   Şöyle yaparız
# Get Read employee with employee id 8345 example.com/employees/8345 #POST— Create an employee example.com/employees # PUT— Update employee with employee id 8345 example.com/employees/8345 #DELETE — Delete employee with employee id 8345 example.com/employees/8345
2. REST isimlerinde versiyon vermek gerekir. Yukarıdaki örnekte var
3. Filtreleme vs gibi şeyler için parametre kullanmak gerekir.  Şöyle yaparız
http://api.example.com/v1/store/items?group=124 http://api.example.com/v1/store/employees?department=IT&region=USA

HTTP Verb'leri Ne İşe Yarar
Rest tasarımında HTTP verb'lerini kullanmak gerekir.
GET     /items      # Read all items
GET     /items/:id  # Read one item
POST    /items      # Create a new item
PUT     /items/:id  # Update one item
DELETE  /items/:id  # Delete one item
Post ve Put
Post ve Put benzer şeyler çağrıştırdıkları için kafa karıştırıyorlar. Post create,insert Put ise update için kullanılır diye anladım. Post için primary key kullanmaya gerek yok
POST   /items        #=> create
Put için primary key kullanmaya gerek var.
PUT    /items/1      #=> update
1. Accept and respond with JSON

Örnek
Şöyle yaparız
GET /api/something?param1=value1
Accept:  application/xml (or application/json)

2. Use nouns instead of verbs in endpoint paths
Açıklaması şöyle
We shouldn’t use verbs in our endpoint paths. Instead, we should use the nouns which represent the entity that the endpoint that we’re retrieving or manipulating as the pathname.

This is because our HTTP request method already has the verb.
Örnek
Şöyle yaparız. Burada endpoint'te customer kelimesi kullanılıyor. Her Http verb ise kodda Createcustomer(), UpdateCustomer() gibi anlamlı kodlara gönderiliyor.
  • For creating new customer:
    URI = /customer/, type = POST, Methodname = CreateCustomer()
  • For updating:
    URI: /customer/{id}, type = PUT, method = UpdateCstomer()
  • For Delete customer:
    URI = /customer/{id}, type = DELETE, Methodname = DeleteCustomer()
  • For View:
    URI: /customer/{id}, type = GET, method = GetCustomer()
Örnek
Hatta şöyle sınıflar tanımlanabilir.
class Category {
    public static Category[] getList();
    public static Category getById($id);
    public static Subcategory[] getSubcategories($id);
    public void fetchDetails();
}

class Subcategory{
    public static Subcategory getById($id);
    public static Product[] getProducts($id);
    public void fetchDetails();
}
3. Name collections with plural nouns
Eğer endpoint bir collection ile temsil ediliyorsa çoğul isim kullanmak daha iyi olabilir.


4. Nesting resources for hierarchical objects
Örnek
Şöyle yaparız
'/articles/:articleId/comments'
5. Handle errors gracefully and return standard error codes

6. Allow filtering, sorting, and pagination

Örnek - pagination
Rest sorguları aslında biraz SQL cümlelerine benziyor. Bazen tek bir nesne, bazen liste bazen de sayfalama yapmak gerekiyor.

Şöyle yaparız
Tek bir nesneyi çekmek için
GET /authors/{id}
Liste şeklinde çekmek için
GET /authors/
Sayfalar şeklinde çekmek için
GET /authors?page={page}
Eğer ağaç şeklinde nesnelerimiz varsa önce ana nesneyi, daha sonra ağacın altındaki alt nesneleri bulmak gerekir.


7. Maintain Good Security Practices
Rest Authentication
Authentication için 3 yöntem var.
1.basic http authentication
2.Oauth 1.0
3. Oauth 2.0
1. Basic Authentication yönteminde HTTP Authorization header alanı kullanılıyor. Bu yöntemin eksisi, her istekte credentials'ın tekrar gönderilmesi, tekrar authenticate edilmesi. Bu işlemin CPU maliyeti var. Daha detay için HTTP Basic Authentication Nedir? yazısına bakabilirsiniz.

2. OAuth1 yönteminde access key URL ile gönderiliyor.

8. Cache data to improve performance

9. Versioning our APIs
Açıklaması şöyle
There are various strategies that one can employ to version the APIs. The following are a few commonly used ones:

1. Using URI versioning. In this approach, we use a version number identifier in the REST API URI to indicate the different version of the API

2. Using request parameter based versioning. In this approach, we use a HTTP request parameter to identify the API version

3. Custom HTTP header based versioning. This approach uses an HTTP request header to identify the API version

4. Media Type based versioning. In this approach, we use HTTP “Accept” header to identify the version

All these approaches are commonly used and have their own merits and drawbacks. You can refer to this GitHub URL to find detailed example on each of these techniques.
URI versioning
Açıklaması şöyle
Versioning is usually done with /v1/, /v2/, etc. added at the start of the API path.
10. API Gateway
API Gateway yazısına  taşıdım

Eclipse

Eclispe
Eclipse ile ilgili aldığım bazı notlar aşağıda.

Proje Silme
Proje silinince Debug / Configuration altındaki çalıştırma ayarları da silinir.

Build Path
Build'i görmek için şöyle yaparız.
Right click on your project -> Java Build Path -> Libraries

"JRE System Library" seçili JRE ile gelen jar dosyalarını içerir. Seçili JRE değiştirilebilir.
Eğer Maven kulllanıyorsak "Maven Dependencies" başlığı altında jar dosyalarını görürüz.

Derleyici
Java projeleri için Eclipse kendi derleyicisini kullanıyor. Bu derleyici artırımsal (incremental) çalışıyor. Yani kod yazarken sadece değişen kısımları derliyor.

Kod Formatlayıcı
Ctrl + Shift + F kısa yolu ile seçili dosyayı formatlar.
Window | Preferences | Java | Code Style | Formatter
menüsü ile erişilir.
Line Wrapping ayarları ile illaki oynamak gerekir.

Javascript
Eclipse bazı javascript dosyalarını doğrulamaya çalışırken hata varmış gibi algılıyor. Örneğin jquery.min.js dosyasını hatalıymış gibi algılıyor. Bu durumdan kurtulmak için How do I remove javascript validation from my eclipse project? sorusunda açıklandığı gibi JavaScript altındaki "Include Path" seçeneği kullanılarak hata veren javascript dosyası hariç bırakılabilir.

Tomcat
Tomcat ile çalıştırılan projelerde yeni parametre tanımlamak istiyorsak Run As -> Run configuration ->Arguments menüsü altında yapabiliriz.

SVN
Editörde kaynak koda sağ tıklayıp  "Team/Show Annotation" seçimi ile koda yapılan commitleri bloklar halinde görebiliriz.

Eclipse projelerinden şu doslayarın svn'e commitlenmesi uygun olur.
.classpath
.project
.launch
.settings/*

Kaynak Kodda Metod Arama
Ctrl + O seçeneği ile açılı kod dosyasında metod ismi kolayca aranabilir. Aynı şey eğer Visual Assist kurulu ise Visual Studio ile Alt + M tuşu ile yapılabilir.

Debug İşlemleri
Örnekte gösterildiği gibi  Run/Run to Line seçilerek, bulunulan satıra kadar koşturulabilir. Böylece break point konulup kaldırmaktan kurtuluruz.

Visual Studio
Konuyu Visual Studio başlıklı yazıya taşıdım.

Servlet

Aşağıda bazı notlarım var. Servlet teknolojisi Http protokolü için kullanılıyor.

WAR Dosyası Yapısı
War dosyası belli bir örüntüde olmalı. Aşağıdaki örnek şekilde test isminde bir uygulamanın tomcat altındaki webapps dizinine açılmış hali görülebilir.
http://localhost:<port>/test/abc

<TOMCAT_HOME>
 |-webapps
    |-manager
    |-data
    |-docs
    |-host-manager
    |-ROOT
    |_test <--- create this folder
      |-WEB-INF
         |-classes <--classes 
         |-lib <-- librares
         |-web.xml 
WEB-INF uygulama tarafından kullanılan deployment descriptor dosyalarını içerir.

Geliştirme esnasında ise kodlar şöyle görünür.
/main/webapp/WEB-INF/
/main/webapp/WEB-INF/spring/...
/main/webapp/WEB-INF/web.xml
/main/webapp/public/...
/main/webapp/resources/...
/main/webapp/views/...

web.xml
web.xml yazısına taşıdım.

Servlet Arayüzü
Bu arayüzde kalıtım hireyarşisi aşağıda. Sadece Http protokolü için değil, diğer protokoller için de kullanılabileceği düşünülerek, GenericServlet ve daha sonra HttpServlet kalıtımı izlenmiş.
Servlet
init metodu
Bu metod container tarafından servlet ilklendirilirken çağırılır. Parametre olarak verilen ServletConfig nesnesi ile ServletContext ve diğer konfigürasyon parametrelerine erişilebilir.

Persistent Servlet
Http persistent connection istek geldikten sonra TCP bağlantısının kapatılmaması demek.

HttpServlet
HttpServlet Sınıfı yazısına taşıdım.

ServletContext
Bu arayüz servlet container ile haberleşmek için kullanılır. Aşağıdaki şekilde görülebilir.

getRequestDispatcher
Gelen istekleri başka bir adrese göndermek mümkün.Örnek:

ServletContextListener
ServletContextListener yazısına taşıdım.

Request İle İlgili Konular
Konuyu Servlet Request ve Response API'si başlıklı yazıya taşıdım.

Response ile İlgili Konular
Konuyu Servlet Request ve Response API'si başlıklı yazıya taşıdım.

ServletInputStream
Bu sınıf POST ve PUT metodu ile gönderilen veriyi okumak için kullanılır.

HttpSessionListener
Bu sınıf yeni oturum açıldığında veya oturum kapandığında tetiklenir. Örnek'te @WebListener kullanılarak web.xml dosyasına satır girilmesine gerek kalmamıştır.


HttpSession
Bu sınıf oturumla ilgili bilgileri tutar. Bilgiler key/value çiftleri şeklindedir.

Eğer session dağıtık bir yapıda başka makineler arasında paylaşılmak istenirse içinde sakladığı her nesnenin Serializable (Session Serialization) olması gerekir.

Bir Çok Key/Value Çifti veya Tek Bir Nesne
Session içinde saklanmak istenen bilgi bir çok key/value girdisi şeklinde saklanabilir.
"user" --> UserObject
"preferences" --> List
veya tek bir SessionObject nesnesinin parçaları şeklinde saklanabilir.
"sessionObject" --> SessionObject


getAttributeNames
Örnek:

getId
Servlet içinde session id'ye erişmek için aşağıdakine benzer bir kod lazım. Örnek buradan geldi.

@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
    String sessionId = request.getSesion().getId();

}
Filter 
Servlet 3.0 yazısına taşıdım.

Servlet Dizin Yapısı
WEB-INF/lib
Bu dizine servlet tarafından kullanılmasını istediğimiz kütüphaneleri yerleştiriyoruz.  Eclipse ise Deployment Assembly ayarlarını aşağıdaki gibi yaparsak export komutunu kullanırken projemizdeki lib dizini altındaki jar dosyaları WE-INF/lib altına taşınırlar.


Servlet ile Dosya Yükleme
Dosya yükleme için aşağıdakine benzer bir HTML lazım.
Buradaki cümle neden enctype="multipart/form-data" kullandığımızı açıklıyor.
By specifying the enctype value of "multipart/form-data", each file's contents will be packaged for submission in a separate section of a multipart document.
Ancak Servlet 3.0'dan önceki standartta servlet sadece application/x-www-form-urlencoded formlarını okumayı biliyordu. Bu tür sabit form anlamına geliyor. Örnek:


Bu durumda Apache Commons FileUpload projesindeki sınıfları kullanmak gerekiyordu. 

Servlet 3.0 ile @MultipartConfig kullanarak FileUpload projesine ihtiyaç kalmadı.

FileItemFactory arayüzü
Bu arayüzü gerçekleştiren sınıflar bir FileItem nesnesi yaratırlar.

DiskFileItemFactory
Bu sınıf yukarıdaki FileItemFactory arayüzünü gerçekleştirir.

FileItem arayüzü
isFormField
Bu metod ile parse edilen request'ten elde edilen FileItem nesnesinin form alanı olup olmadığı belirlenir. Örnek:
HttpServletRequest request;
ServletFileUpload upload = //...
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()) {
 FileItem item = iterator.next();
 if (item.isFormField()) {}
}
 
ServletFileUpload sınıfı
constructor metodu
Bir FileItemFactory alır. Örnek:
 
isMultipartContent
ServletFileUpload ile gelen HttpServletRequest nesnesinin multipart olup olmadığı kontrol edilebilir. Örnek:
protected void doPost(HttpServletRequest request,HttpServletResponse response) {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);
}
parseRequest
Örnekte dosyalara nasıl erişileceği gösteriliyor.

HttpServletRequest req;
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(req);
for (int i=0; i<items.size(); i++){
    System.out.println(items.get(i).getName());
    System.out.println(items.get(i).getFieldName());
    System.out.println(items.get(i).getString());
}

ServletFileUpload sınıfı ve Streaming API
Burada eğer Apache Commons FileUpload projesinin Stream API'si kullanılırsa, dosyanın bellekte tutulduğu açıklanmış.

1 Ekim 2015 Perşembe

Telnet

Windows'a Telnet Client Kurmak
Telnet programı yeni Windows'larda kurulu gelmiyor. Kurmak için appwiz.cpl komutu çalıştırılır. "Turn Windows features on or off" seçilir. Telnet Client kurulur.

Telnet Çıktısı
Bağlantı başarılı ise şuna benzer bir çıktı görürüz.
Trying 216.58.208.227... 
Connected to google.it.
Escape character is '^]'.
Telnet ve Altusen Power Switch
Altusen Power Switch (PN9108) cihazını telnet ile kontrol etmek için aşağıdaki PowerShell kodu kullanılabilir.

set oShell = CreateObject ("WScript.Shell")'r'n
oShell.run ("Telnet")'r'n
wScript.Sleep 1000 'r'n
oShell.SendKeys ("MyTelnetCommand")'r'n
oShell.SendKeys ("{Enter}")'r'n

nc komutu - Telnet Yoksa
Linux'ta nc (net chat) kullanılabilir.  nc standart akıma yazar (stdout) ve gönderilecek karakteri standart akımdan (stdin) okur. Gerekirse nc'nin önüne awk ile başka şeyler de yazdırılabilir.
Sunucu (Alice) için şunu yazarız.
awk -W interactive '$0="Alice: "$0' | nc -l -p 1234 -s <ip_of_alice>
İstemci (Bob) için de şunu yazarız.
awk -W interactive '$0="Bob: "$0' | nc <ip_of_alice> 1234

Böylee her iki taraf ta birbilerinin gönderdikleri metinleri önce Alice : xxx ve Bob : xxx şeklinde görürler.

-l seçeneği
Sunucu (Server) nc açar.

-p seçeneği
Port numarasını belirtir. Bir portu dinlemek için şöyle yaparız
nc -l -p xxxx
Bir porta bağlanmak için şöyle yaparız.
nc <ip_address> -p xxxx
-z seçeneği
 Bağlantı açılınca otomatik olarak kapatır.
nc -zv localhost 22
-v seçeneği
 verbose

Bağlantının başarılı olup olmadığını anlamak için $? kullanılır.
$ nc -zv localhost 22
localhost [127.0.0.1] 22 (ssh) open
$ echo $?
0
$ nc -zv localhost 23
localhost [127.0.0.1] 23 (telnet) : Connection refused
$ echo $?
1

nc ile dosya aktarımı
nc ile dosya aktarımı yapılabilir. Şöyle yaparız.
tar -cf - -C /path/of/small/files . | pigz | nc -l 9876
pigz paralel zip yapar.

İstemci taraf ise şöyle yapar. Yani nc çıktısını diske yazar.
nc source_machine_ip 9876 > smallstuff.tar.gz