4 Aralık 2018 Salı

Komut Satırından Google'lamak



googler isimli komut satırı aracı ile terminalden google aramaları yapabilir, sonuçlar üzerinde dolaşabilirsiniz. Ubuntu makinenize kurmak için github'daki kodunu klonlamak ve

sudo make install 

komutunu çalıştırmanız yeterli.

Kurulumu oldukça basit olan aracın bir çok parametre seçeneği bulunuyor. Dokümanda bahsedilen özelliklerden bazıları:
  • Google Arama
  • Google anahtar kelime tabanlı site içi araması
  • Google Haberler içinde arama
  • Sonuçları reklamsız dönme
  • Sonuç sayfalarını tarayıcıda açma, tekli veya toplu olarak 
  • Sonuç sayfaları arasında dolaşma
  • Otomatik yazım düzeltmeyi devre dışı bırakma ve tam olarak anahtar kelimeleri arama
  • Google anahtar kelimelerini kullanma (ör. filetype: mime, site:somesite.com) desteği
  • İlk sonucu doğrudan tarayıcıda açma (şanslı hissediyorum özelliği)
  • Kullanışlı kullanım örnekleri ile kapsamlı dokümantasyon
  • Minimum bağımlılık

Geliştiricisi ayrıca eğlenceli örnekler de paylaşmış. Örneğin, yazılım hatalarını terminalden StackOverflow üzerinde aratan komut geliştirmiş.

Ayrıca, geliştiricilere ufak birkaç ipucu. --json parametresiyle sonuçlar JSON formatında alınabiliyor. googler, sonuçları Google API'leri kullanmadan, standart HTML çıktıyı parse ederek üretiyor. Bu nedenle, API token sahibi olmaya gerek kalmadan belli sayıda istek sınırına takılmadan kullanılabiliyor. Gerisi hayal gücüne kalmış.

Site içi arama örneği:

googler -w n11.com raspberry pi



PDF türünde kitap arama örneği:








27 Haziran 2018 Çarşamba

SSHJ ile Raspberry'de Uzaktan Python Çalıştırmak

Merhabalar, Bu yazımızda, Java ile uzaktaki bir makineye programatik olarak SSH ile bağlanıp Python kod çalıştırmayı göreceğiz. Örnek olarak Raspberry 3 makinesi kullanacağız.
SSH işlemleri için SSHJ kütüphanesini kullanacağız. Bu kütüphane ile lokal makinenizde bulunan önceden bağlandığınız makinelerin ssh keylerini kullanarak bağlantı kurulabildiği gibi, kullanıcı adı - şifre bilgilerini kullanarak da bağlantı kurulabilmektedir. Kullanıcı adı - şifre yöntemini kullanarak bağlantı kuracağız.

Öncelikle basit bir komut çalıştırıp çıktısını konsola basalım.
Kısaca örnek kodumuzu anlatalım. IP, port, kullanıcı adı ve şifre bilgilerini kullanarak bir bağlantı açılıyor. SSH client nesnesi ile bir session açılıp komut çalıştırılıyor. Komutun bitmesini beklemek için 5 sn bekletiliyor. Daha sonra komut çıktısı okunarak konsola basılıyor.

Şimdi de SSH client ile session açıp, shell arayüzü ile komutları inputstream şeklinde shell'in standart input'una gönderelim. Örnek basit bir Python kodunu String içerisinde ByteArrayInputStream'e çevirerek gönderiyoruz. Çıktıyı da standart output'dan okuyup konsola basalım.


 Programın çıktısı örnek kodun aşağısında yorum içerisinde bulunmaktadır.

Özetle, programatik olarak SSH ile makineye bağlantı sağlayıp uzak makinanın komut satırını elimizin altına alabiliyoruz.

12 Mayıs 2018 Cumartesi

Spring Boot ile Veri Tabanına İlk Verileri Ekleme

Önceki yazımızda oluşturduğumuz örnek projede

spring.jpa.hibernate.ddl-auto = update

özelliği ile veritabanı şemasının Hibernate tarafından otomatik oluşturulmasını sağlamıştık. Fakat, çoğu zaman veri tabanı şemasının oluşturulması yeterli olmayıp, uygulamanın kullanılabilmesi için bazı ilk verilerin de eklenmiş olması gerekmektedir. Bu yazımızda uygulama ayağa kalkarken uygulama içinden ilk verilerimizi nasıl kaydedeceğimizi göreceğiz.

Veri tabanımıza veri kaydetmenin çeşitli yöntemleri vardır. SQL script dosyaları hazırlayıp, bu scriptleri çalıştırarak da veri tabanımızı doldurabiliriz. Fakat kullandığımız veri tabanına göre değişik scriptler hazırlamamız gerekebilir. Örneğin, MySQL ile çalışırken hazırladığımız scriptleri, Oracle veya başka bir veri tabanı kullanmaya karar verdiğimizde tekrar yazmamız gerekebilir. Hibernate teknolojisi bizi kullandığımız veri tabanı teknolojisinden soyutluyorken neden bunu ilk veri kaydederken de kullanmayalım?

Spring Boot Data JPA teknolojisini kullanarak oluşturduğumuz Repository'leri kullanarak, ApplicationReadyEvent'i dinleyen ApplicationListener beanlerimiz ile uygulama ayağa kalktığında veri atacağımız tabloyu kontrol edeceğiz. Eğer boşsa, eklemek istediğimiz entityleri oluşturup kaydedeceğiz.

Bu sınıflarımıza Data Populating Unit (Dpu) diyebiliriz. Uygulamamız ayağa kalktığında dog, bird, cat tipleri hâl-i hazırda eklenmiş olsun istiyoruz. 

Birden fazla Dpu çalıştırmak istediğimizde dpu'ların çalışma sırası önem kazanıyor. Örneğin, dog tipinde Pet kaydedeceğimiz PetDpu çalıştırmak istiyorsak, öncelikle dog PetType nesnesinin veri tabanında kayıtlı olduğundan emin olmalıyız. Bu nedenle PetTypeDpu sınıfımızın, yazacağımız PetDpu'dan önce çalışması için @Order anotasyonu ile sıra belirliyoruz.


Tüm örnek proje kodunu Github'da şuradan indirebilirsiniz.

29 Nisan 2018 Pazar

MapStruct ile Entity Dto Dönüşümü

Merhabalar,
REST servislerimizde domain entity (hibernate) nesnelerini direk dönmek güvenlik açığı oluşturabildiği gibi, bidirectional ilişkilerde JSON'a serialize etmeye çalışırken sonsuz döngüye girip hata verme tehlikesi bulunmaktadır. Bu sorunu entity nesnelerimizi basit data transfer object (DTO) nesnelerine dönüştürüp dönerek aşabiliriz. Peki her defasında onlarca defa getX() setX() metodlarını çağırmak yorucu olmayacak mı? Bunun için de MapStruct (java bean mapping) kütüphanesini kullanabiliriz. Tanımlayacağımız basit mapper nesneler ile get set metod çağırım yükünden kurtulabiliriz.



Bu yazımızda Spring Boot projesi içinde H2 veritabanı ile, MapStruct kullanımını göreceğiz. Veri modeli olarak klasik Pet Clinic yapısını kullanacağız. Evcil hayvan, evcil hayvan sahipleri, veteriner, hayvan tipleri gibi veri yapıları ile Hibernate Mapping örneklerini de görmüş olacağız.

Tüm örnek proje kodunu Github'da şuradan indirebilirsiniz.

Veri modelimiz aşağıdaki gibidir. Owner ve Pet arasında karşılıklı (bidirectional) ilişki bulunmaktadır. Bu nedenle Owner nesnesini JSON olarak dönmek istediğimizde, içindeki Pet'leri JSON'a çevirirken, Pet içindeki Owner nesnesini de yine JSON'a çevirmeye çalışacağı için sonsuz döngüye girerek başarısız olmaktadır.

Projeye yapısına genel olarak bir bakalım.

model paketi altında domain entity nesnelerimiz bulunuyor. Dto paketi içinde test için kullanacağımız entity nesnelerinin dto nesneleri bulunuyor. mapper paketi içinde MapStruct mapper interface sınıfları bulunuyor. repository paketinde Spring Data JPA repository sınıflarımız bulunuyor. service paketi içinde ise repository nesnelerini kullanan servis sınıflarımız bulunuyor.

application.properties dosyası içeriği aşağıdaki gibidir:

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
server.port = 8080
spring.datasource.url = jdbc:h2:file:~/h2/app_db;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username = sa
spring.datasource.password =
spring.datasource.driverClassName = org.h2.Driver
spring.jpa.hibernate.ddl-auto = update


Projemiz Maven projesi olduğundan bağımlılıkları incelemek için pom.xml içerisinde bağımlılıkları tanımlıyoruz.
        <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-jdk8</artifactId>   

                <version>${org.mapstruct.version}</version>
        </dependency>


MapStruct, derleme aşamasında tanımlanan mapper interface veya abstract sınıflarım implementasyonlarını otomatik olarak oluşturmaktadır. Bunun için maven compile plugin içerisine bir mapstruct-processor tanımı yapmak gerekmektedir. 

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source> <!-- or higher, depending on your project -->
                <target>1.8</target> <!-- or higher, depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>

            </configuration>
        </plugin>
        </plugins>
    </build>


Domain ve Dto sınıflarımıza bir bakalım:




Mapper interfacelerimize bir bakalım. Dikkat edilirse Owner entity'si içinde Pet entity'si var. Bu nedenle Pet için de mapper tanımlamalı ve OwnerMapper sınıfını bu maperdan haberdar etmeliyiz:
Bunun için @Mapper anotasyonu içindeki uses alanını kullanıyoruz. Ayrıca Spring'in dependency injection kabiliyetinden faydalanıp mapper'ları bean olarak kullanabilmek için @Mapper anotasyonu içinde componentModel = "spring" tanımını yapıyoruz.

OwnerMapper 

PetMapper


PetTypeMapper

Maven ile derlendiğinde target klasörü altına otomatik olarak üretilmiş mapper impl dosyaları görünür olacaktır. 
mvn clean compile yapılarak derlenmelidir.


 Otomatik üretilmiş OwnerMapperImpl içeriği aşağıdaki gibidir:


Şimdi OwnerMapper'ı kullandığımız OwnerService koduna bakalım.


Repository'den dönen entity'lerin direk dönüldüğü ve mapper ile Dto'ya çevrilip dönüldüğü iki listeleme metodu tanımladık.

Test Vakti

Gelelim projeyi test etmeye. OwnerService sınıfında örnek Owner kaydedecek metod tanımladık. OwnerController içinde /owner/add ile istek gelirse bu metod çağrılacak. Listelemek için de controller içinde iki metod tanımladık. /owner/list ve /owner/listCorrect. /owner/list metodu normal Owner entity listesi dönmektedir. Bu sayede sonsuz döngüye girme hatasını görebileceğiz. /owner/listCorrect ile de OwnerDto listesi dönecek ve başarılı bir şekilde ownerların JSON dökümünü görebileceğiz.


Spring Boot projemizi çalıştıralım ve http://localhost:8080/owner/add adresine gidelim. Add metodu da aslında OwnerDto listesi döndüğünden JSON serialize hatasıyla karşılaşmadığımızı görebiliriz. 
Veritabanına bakmak için http://localhost:8080/h2-console linkine gidip jdbc adresi alanına application.properties kısmında yazan jdbc adresini yazarak giriş yapabiliriz.





http://localhost:8080/owner/list adresine giderek hatayı üretelim.


Konsola düşen Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException hata loglarına bakalım:




 http://localhost:8080/owner/listCorrect adresine giderek sorunsuz dönen cevaba bakalım:

MapStruct kullanırken unutmaması gereken ufak bir not: Mapper sınıfların implementasyonları maven derleme sırasında üretildiği için, kullandığınız IDE'nin otomatik build ettiği sırada üretmeyecektir. Bu sebeple uygulama ayağa kalkarken bean bulunamadı hatası alabilirsiniz. Bu nedenle impl dosyalarının üretildiğinden emin olup uygulamayı öyle başlatınız.

Tüm örnek proje kodunu Github'da şuradan indirebilirsiniz.




17 Mart 2018 Cumartesi

Selenium ve Python ile Otomatik Ekran Testine Giriş

Yazılım projelerimizde birim testleri önemli bir yer tutuyor. Birim test denilince nedense servis katmanına yazılan testler akla ilk gelen oluyor. Fakat, ekranların da otomatik olarak test edilmesi geliştirme sırasında farkedilemeyen alakasız bir yerdeki hatanın farkedilmesini sağlar. Ekranların test edilmesi işini manuel olarak halletmeye çalıştığımızda harcayacağımız adam-gün'lük işin büyük bölümünü kazanmış oluyoruz.
Bu yazımızda Selenium web otomasyon kütüphanesi ve yazacağımız Python scriptlerini kullanarak basit bir html formunu otomatik olarak doldurup, tuşa tıklatıp sonucu test edeceğiz. Tüm örnek kodları şuradan indirebilirsiniz.




Öncelikle Selenium'dan bahsedelim. Selenium web tarayıcılarını kodsal olarak otomatik kullanmak için geliştirilmiş bir kütüphanedir. Selenium WebDriver modülü ile Firefox, Chrome vb tarayıcıları otomatik olarak kullanabilmekteyiz. Bu tarayıcıların her biri için Selenium web driver bulunuyor. Tabii ki seçilen web tarayıcı sistemde kurulu olmalıdır. Sadece test için değil, sürekli tekrar eden sıkıcı işleri otomatikleştirmek için de kullanılabilir.
Geniş bir programlama dili desteği bulunuyor. Java, C#, Ruby, Python, Javascript resmi olarak desteklenen dillerden.

Kurulumlar

Python 2.7 kurulu olduğu varsayılarak aşağıdaki komutlarla Selenium'u bilgisayarımıza kuralım.

pip install selenium

Selenium'un tarayıcıları otomatik açabilmesi için geckodriver denen bir araç da kurulmalıdır. Mac OS'da aşağıdaki gibi kurulabilir.

brew install geckodriver

Örnek Kodlar

Öncelikle HTML form kodunu görelim.


Submit'e tıklandığında input alanlarının değerlerini alıp birleştirip tekrar sayfaya basan Javascript kodu.
Ad Soyad alanlarına girilen metin toplanarak, outputDiv id'li bir div elementin içine eklenerek sayfada gösteriliyor.
Şimdi de form alanlarını otomatik olarak doldurup tuşu tıklatacak Python koduna bir göz atalım.

Firefox Web Driver nesnesi oluşturuyoruz. Bu nesne ile yerel dosya sisteminde açmak istediğimiz html dosyanın full pathini veriyoruz.
Selenium selector fonksiyonlarını kullanarak HTML dosyadaki input alanları ve tuş nesnelerine ulaşıyoruz. Biz burada HTML elementlerin id ve name alanlarına göre elementi getiren fonksiyonları kullandık. Fakat Selenium HTML elementlerine ulaşmak için çok çeşitli seçenekler sunuyor. XPath'e göre, class alanına göre, CSS içeriğine göre, text içeriğine göre, hatta direk javascript çalıştırarak dahi HTML elementlerine ulaşılabiliyor.
İnput alanlarına örnek metinler girip tuşa tıklatıyoruz.
Sonuç olarak ekrana basılan output ile beklediğimiz output'u karşılaştırıyoruz.

Tüm kodların aynı klasörde olduğundan emin olduktan sonra aşağıdaki komutla testimizi çalıştırabiliriz.

python autotest.py

Çalıştırdığımızda Selenium yeni bir Firefox açacak, index.html dosyasını görüntüleyecek. İnput alanlarını doldurup tuşa tıklayacak. Tüm işlemler tamamlandığında da firefox kapatılacak.

Bu kodda driver ile yerel dosya sisteminde bulunan bir dosyayı açtık. Fakat istersek herhangi bir URL vererek tarayıcıda açabiliriz. Örneğin, driver.get("http://www.kodblog.net/"); gibi.

Selenium görüldüğü gibi oldukça güçlü bir araç. Klavye veya mouse kullanmadan tarayıcıda formlar doldurulabiliyor, tuşlar tıklanabiliyor. Projenizde oluşturacağınız test caseler ile Selenium ekranlarınızı test ederken siz de çayınızı yudumlayıp ekranda akıp giden uygulamanızı izleyebilirsiniz.


17 Şubat 2018 Cumartesi

Yazılımcı Özlü Sözleri


Odaklanmak, 1000 iyi fikre hayır diyebilmektir.
Steve Jobs

Kod yalan söylemez, yorumlar bazen söyler.
Ron Jeffries

Tasarım, nasıl başarısız olacağınızı seçmektir.
Ron Fein

Programcılar, geleceği düşündükleri için sürekli olarak işleri gereğinden fazla karmaşıklaştırmaktadırlar. Geleceği boşverin. Bugün için programlayın.
David Heinemeier Hansson


İnsanlar, yazılımın ürün olmadığını, ürün üretmek için kullanıldığını anlayacaklar.
Linus Torvalds


Kod, espiri gibidir. Açıklamak zorundaysanız kötüdür.
Cory House


Kötü yönetim yazılım maliyetini diğer tüm faktörlerden daha hızlı arttırır.
Barry Boehm


Servislerinizi birbirinden bağımsız olarak ayağa kaldıramıyorsanız mikroservis değillerdir.
Daniel Bryant

Basitlik, güvenilirlik için önkoşuldur.
Edsger W. Dijkstra


Kodunuzda NE yerine NEDEN'e odaklanmak sizi daha iyi bir geliştirici yapar.
Jordi Boggiano


Kullanıcıları, sistemin zaten bildiği bir bilgiyi vermeye zorlamayın.
Rick Lemons



Konuşmak bedava, bana kodu göster!
Linus Torvalds


Ben sadece icat ederim. Sonra insanların gelip icadıma ihtiyaç duymasını beklerim.
R. Buckminster Fuller


Eğer fikrinizi yazıya dökemiyorsanız, onu kodlayamazsınız.
Peter Halpern

İlerlemenin sırrı başlamaktır.
Mark Twain

Eğer gerçekler teorinize uymuyorsa gerçekliği değiştirin.
Albert Einstein

Merak duygusunun zorunlu eğitimden sağ çıkması mucize.
Albert Einstein

Aynı şeyi sürekli tekrarlayıp farklı sonuç beklemek deliliktir.
Albert Einstein

Asla yanlış yapmamış insan, yeni hiç birşey denememiştir.
Albert Einstein

Mantık sizi A noktasından B noktasına götürür. Hayal gücü her yere.
Albert Einstein

Hızlı, İyi, Ucuz. Sadece ikisini seçebilirsin.
Bilinmiyor

Mücadele yoksa ilerleme de yoktur.
Frederick Douglass

Bir projeyi daha hızlı bitirmenin en iyi yolu, erkenden başlamaktır.
Jim Highsmith

En iyi performans arttırımı, çalışmayan durumdan çalışır duruma getirmektir.
John Ousterhout

Tüm büyük programlama felaketleri çok fazla fikri alıp tek bir yere koymaktan kaynaklanmıştır. Gordon Bell

Daha az kod yazmak, esnek kalmanın güzel bir yoludur.
Pragmatic Programmer

Performansın anahtarı zarafettir. Binlerce özel durum gerçekleştirimi değildir.
Jon Bentley. Doug MvIlroy

Neden hiçbir zaman DOĞRU yapmak için vaktimiz yok da, YENİDEN yapmak için vaktimiz var? Bilinmiyor

Üretken bir programcının işe alınabilir olmasını beklemek, ilk bulunan programcının üretken olmasını beklemekten iyidir.
Bjarne Stroustrup

Tasarımda mükemmellik, ekleyecek bir şey kalmadığında değil, çıkaracak bir şey kalmadığında yakalanır.
Antonie de Saint-Exupery

Gizemli bir cinayetin sırlarını çözmek iyidir. Fakat kodun sırlarını çözmek zorunda kalmamalısınız. Kodun kolaylıkla anlaşılabilir olması gerekir.
Steve McConnell

Yazılımcı; kahveyi koda çeviren organizma.
Bilinmiyor

Bazen Pazartesi günü tüm gün yatmak, haftanın kalanını Pazartesi yazılan kodu debug etmeye harcamaktan iyidir.
Dan Salomon

Gereksinim veya tasarım olmadan programlama, boş bir dosyaya bug eklemekten başka bir şey değildir.
Louis Srygley

Acı çekmeden öğrenemeyiz.
Aristotle

Mükemmel fikirleri çalmak konusunda her zaman yüzsüz davrandık.
Steve Jobs

Ancak ikisi de donmuşsa suda yürümek ve şartnameden yazılım geliştirmek kolaydır.
Edward V Berard

Debug sırasında, acemiler hata giderici kod eklerler; uzmanlar ise kusurlu olan kodu çıkarırlar. Richard Pattis

Programlamadaki ilerleyişi yazılan kod satırı sayısıyla ölçmek, uçak inşasındaki ilerleyişi ağırlıkla ölçmeye benzer.
Bill Gates

İyi bir yazılımcı, tek yön bir yoldan karşıya geçerken iki yöne de bakandır.
Bilinmiyor

Yazılım, yapmasını söylediğiniz işi yapar, yapmasını istediğinizi değil.
Bilinmiyor

Beta Latince'de "Hala çalışmıyor" demektir.
Bilinmiyor

Önce meseleyi çözün. Sonra kodu yazın.
John Johnson

Benim makinemde çalışıyor.
Bilinmiyor

İnternetten bulunan kodu canlıdaki koda yapıştırmak, yolda bulunan sakızı çiğnemek gibidir. Bilinmiyor

Bilgi güçtür.
Francis Bacon

Okulumun eğitimimi engellemesine asla izin vermedim.
Mark Twain

Sorunun kaynağını düzeltin, semptomunu değil.
Steve Maguire

Komut Satırından Google'lamak

googler isimli komut satırı aracı ile terminalden google aramaları yapabilir, sonuçlar üzerinde dolaşabilirsiniz. Ubuntu makinenize kurm...