SpringBoot ile Rest ve Soap Api Örneği

SpringBoot Nedir?

SpringBoot, hızlıca deploy edilebilir yeni nesil web uygulaması oluşturmaya yarayan güzel bir spring implementasyonudur. Çalıştırılabilir jar dosyası çıkartarak web uygulaması ya da servis yazılabilir. Ben bu alt yapıyı kullanarak bir servis yazmak istedim.

Uygulamanın Amacı Nedir?

Servisimde “Poi” adında bir entity’yi crud işlemlerine tabi tutarak, “spring ile nasıl soap api yazılır“, “spring ile nasıl rest api yazılır” sorularına çözüm göstereceğim. Asıl amacım poi’nin hangi property’sini işlediğim değil, spring ile onu nasıl kullandığım olacak.

Servisimi yazarken, Spring’i de yeni öğreniyor oluşumdan dolayı spring’in annotation’larını doğru kullanmaya ve neden kullandığımı da açıklamaya özen göstereceğim. Ayrıca core, webService ve business lojiklerini doğru kullanmayı hedeflediğim güzel bir alıştırma projesi olacak.

Neler Anlatacağım?

Kodları yazı içinde paylaşmak yerine github’ı kullanacağım. Burada anlatacağım şeyler ise, yazılma amacı ve nasıl çalıştığı olacak.

https://github.com/sefersezer/SpringRestSoapApiExample


Proje kaynaklarını anlatmaya öncelikle maven dependencylerinden başlayacağım.

lombok: Compile time’da pojo’lardaki getter, setter, default constructor vb şeyleri otomatik oluşturan, kod kirliliğini azaltmayı sağlayan bir eklenti. Lombok, başka bir makalede detaylıca anlatılabilir.

spring-boot-starter-web: Uygulama web projesi olarak ayağa kalkıp bir portu kullanılabilir sunacak. Ayrıca ws paketinde spring boot web annotationlarını da kullanacağız.

spring-boot-starter-data-mongodb: Veritabanı olarak mongodb kullanacağım. Mongodb bağlantısını da spring yetenekleriyle kuracağım.

spring-boot-starter-ws: Spring web service annotationları için kullanıyorum. Mesela @Endpoint annotation’u soap (ve rest) actionlarını işlemek için projeyi otomatik tarayarak geçtiği sayfadaki @ResponsePayload’lı methodları kullanılabilir kılacak.

wsdl4j: soap api için xsd şablonundan wsdl generate etmeye yarayacak. Örneğin servis endpointi sonuna .wsdl koyarak şablona erişebiliyor olacağım.  (localhost:9000/ services /poiservice.wsdl )

modelmapper-spring: Core package ile Web Service package’larının bağımsız olacağından bahsetmiştik. Hedef pojo’m olan Poi için Web Service katmanında PoiEntity objesi oluşturdum. Bunların her bir property’sini manuel maplemek yerine modelMapper kullanacağım.

jackson: Serializabled objelerimi json, xml setlere dönüştürüp, büyük angaryadan kurtaran muhteşem dependency. #tambiraltinbilezik 🙂

jaxb2-maven-plugin: xsd şablonunu oluşturduktan sonra servis katmanındaki objeler için elle uğraşmayacağım heralde! mvn clean generate-sources ile deploy ettiğimiz zaman belirtilen dizine otomatik generate edilecek. (Artık javada pojo oluşturmak angarya iş olarak gözüküyor. Örneğin eclipse’de Telosys Tools ile pojo, dta, dto, testler vs birçok şey generate edebiliyorsunuz.)


Uygulamanın modüllerini (paketleri) ve sınıf isimlerini aşağıdaki gibi verdim:

  • config
    Spring'in Mongodb bağlantısını sağlamak için özel bir dependency eklemiştik.
    Bu dependency @EnableMongoRepositories annotation'ı sağlıyor. Mongodb
    repositorylerinin bulunduğu paketi göstererek (bir nevi) register ediyoruz.
    Ayrıca bağlantı kurarken host, port, db parametrelerini de
    AbstractMongoConfiguration sınıfını extend ederek set edebiliyoruz.
    
    Burada kullandığım Environment değerleri ise /resources/application.properties
    dosyasından geliyor.
    • MongoConfig.java
  • model
    Uygulamada Poi.java ve PoiEntity.java adında aynı gözüken ama 2 farklı amaca
    hizmet eden pojo bulunuyor. Ben her ne kadar bu projede extreme işlem yapmasam
    da modüllerin bağımsızlığının sağlanması gerektiğini gösterebilmek adına bu
    iki pojo'yu oluşturdum.
    
    Poi.java, uygulamanın core tarafındaki model entity'm olacak. Core tarafındaki
    işlemlerde bunu istediğim gibi manipule edeceğim; complex type olarak kullanıp içine istatiksel veriler vs ekleyip, gerekirse başka yerden
    implemente edilmiş özellikler vs kullanıp istediğim gibi kullanabileceğim.
    Servis tarafındaki PoiEntity.java ise, Poi.java'daki implementasyonlarımın
    çıktısı olacak. Kullanıcıya göstermek istediğim şeyleri en yalın haliyle
    oraya atacağım. Kullanıcı benim arka planda ne yaptığımdan, core'daki
    bağımlılıklarımdan haberdar olmayacak, sadece bu çıktıyı alıp kendi işine
    bakacak.
    
    Mapper, poi ile poiEntity'deki gerekli property'leri birbirine map ettiğim
    mapping servisim. Sınıfı incelediğimizde, normalde daha çok karışık olması
    gerekir ama bu uygulamada bişey yapmadığımdan ModelMapper dependency'sini
    kullanarak direkt mapping sağladım.
    
    repository/ dizinindeki poiRepository ise, mongodb'deki collection'a ulaşmamı
    sağlayan mongoDbRepository örneğim. FindAll, save, delete default işlemlerini
    mongoDbRepository sayesinde yapabiliyorum. Spesifik sorgularım için ise
    namedQuery denilen spring özelliği ile yazdığım methodlara uygun ismi ve dönüş
    tipi vererek crud işlemimi gerçekleştirebiliyorum. Detaylar için şu adrese
    bakabilirsiniz.
    • repository
      • PoiRepository.java
    • Mapper.java
    • Poi.java
  • service
     (acıklama)
    • endpoint
      • PoiRestEndpoint.java
      • PoiSoapEndpoint.java
    • PoiRepositoryService.java
  • ws
     (acıklama)
    • model
       (acıklama)
      • PoiEntity.java
      • ServiceResponse.java
    • rest
       (acıklama)
      • EntityService
      • EntityServiceImpl
    • soap
       (acıklama)
      • dao
        • DeletePoiRequest.java
        • GetPoiRequest.java
        • GetPoiResponse.java
        • ObjectFactory.java
        • package-info.java
        • SavePoiRequest.java
      • SoapWebServiceConfig.java
  • Application.java
    Uygulama bu sınıf ile ayağa kalkıyor. Sınıfa SpringBootApplication annotation
    ve diğer annotationları vererek, springBoot uygulaması olmasını, servis olarak
    çalışmasını, konfigurasyonları okumasını vs söylüyorum; ilk kıvılcımı buradan veriyoruz.
  • resources
     (acıklama)
    • application.properties
    • poiservice.xsd

 

Advertisements

Java Uygulama için Api’ın Geçerli Sertifika Dosyasını Set Etmek

Https protokolü ile SaaS hizmet sağlayan https://api1.paritus.com servisi mevcut. Bu servisin cevabını, yazmış olduğumuz bir java uygulaması içinde kullanmayı planlıyoruz. Jackson – JaxRS, Jersey-Client veya başka bir rest client kütüphanesi kullanarak normal bir http isteğini handle edebiliriz. Ama iş https üzerinden veri çekmeye gelince java tarafında daha önce karşılaşmadığım javax.net.ssl.SSLHandshakeException hatası ile karşılaştım.

Biraz araştırınca .Net tarafında da benzer problemler olduğunu, .Net tarafında aşağıdaki gibi bir yöntem ile kod içinde çözülebildiğini gördüm.

//System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object s, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; };

Java tarafında daha farklı çözümler varmış. Biri application server’ın conf/server.xml konfigurasyon dosyası üzerinde cert dosyasını tanımlamak. Diğeri ise uygulamanın çalışacağı java’nın keystore dosyasına api1.paritus.com’un .cer dosyasını import etmek. Ben ikincisini uyguladığımdan onu açıklayacağım.

Öncelikle api1.paritus.com’un kullandığı sertifikayı tarayıcı üzerinden görüntüleyip exportunu alıyoruz. Aşağıdaki .cer dosyası tarayı üzerinden inmiş sertifika bilgi dosyasıdır.

./jre_linux/bin/keytool -import -noprompt -trustcacerts -alias api1.paritus.com -file ../api1_paritus_com.cer -keystore ./jre_linux/lib/security/cacerts -storepass changeit

Yukarda “keytool” u kullanarak güvenilir ca sertifikalarına yenisini ekliyoruz. Alias ile bir isim veriyoruz. file ile tarayıcıdan indirdiğimiz sertifika bilgi dosyasını belirtiyoruz. keystore ile ca sertifikalarının olduğu caCerts dosyasını belirtiyoruz.

Bundan sonra kodu geliştirdiğimiz ortamı veya kodun çalıştığı application server’i restart ediyoruz ve handshake hatasını almayıp kodumuzun başarılı çalıştığını görüyoruz.

Not: linux ve windows makine üzerinde aynı komutu çalıştırdım. Problem yaşamadım. Sormak istediğiniz birşey olursa sefersezer@gmail.com adresime mail atabilirsiniz.

Saygılarımla

Blog Başlıkları

Merhabalar,

Aklımda yüze yakın sayıda blog konusu var. Bunları yazmak isterim ama tipik Y kuşağı insanı olduğumdan hiçbirşey yapmamak daha cazip geliyor.

Tabi, o kadar da değil; yazıcam bu blogları. Buraya aklımdaki blog başlıklarını not etmek, ilerde de yazdıkça burada üzerini çizmek istiyorum.

Listeye şöyle başlıyorum:

  • Arduino İle Digital Port Dinlemek
  • Maven Parent <> Dependency Versiyon İlişkisi
  • Maven Deneyimlerim
  • Jenkins Hakkındaki Yorumlarım
  • Docker Hakkındaki Yorumlarım
  • Coordinate Clustering (DBSCAN Algorithm)

İlk Spring Boot Uygulaması

Bu yazıdaki hedefimiz spring boot’un derinlerine inmek değil, hello-world uygulama yazıp, çalıştırılabilir .jar olarak paketleyip servisin çalışırlığını test etmektir.

Başlamadan önce biraz bahsetmek isterim. Spring boot, eskide kalan ve uygulama sunucusuna ihtiyaç duyan .war paketi yerine tüm ihtiyaçlarını .jar paketi içinde toparlamayı sağlayan bir Spring framework kütüphanesidir. En temel özelliği, yazılacak uygulamanın servis katmanını, istenilen methodlar veya interface method signature’ları üzerindeki notasyonlar ile kolaylıkla yönetebilmektir.

Hızlıca günün gereksinimlerini açıklayayım:

  • maven 3.0 +

  • java 1.8

  • Ide (eclipse)

1. Method ve Notasyonları

Klasik bir maven projesi oluşturup, “hello-world” yazdırabilmek için App.java sınıfını şu şekilde düzenliyoruz. Daha başka konfigurasyona ihtiyaç duymadan servisimizi kullanılabilir hale getiriyoruz…

Aşağıdaki commentlerde hangi satırın ne işe yaradığı açıklanmaktadır.

@EnableAutoConfiguration
@RestController
public class App {
public static void main(String[] args) { // starter method
SpringApplication.run(App.class, args); // spring boot uygulaması burada tetikleniyor.
}

@RequestMapping(“/”) // request mapping sağlanıyor. şimdilik sadece root dizininde, parametresiz, yalın bir çağırım gerçekleştiriliyor.
public String home() {
return “Hello Docker World”;
}
}

2. Bağımlılıklar ve Parent

Kodu yazdıktan sonra .pom dosyasına sadece şu dependency’leri eklememiz yeterli olacaktır:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>

Projenin parent’i olarak spring-boot-starter-parent belirliyoruz. Bu parent projenin .jar olarak start edilebilmesini sağlayacak olan manifestleri içermektedir. Bir konfigurasyon beklememektedir. Eğer parent’i eklemek istemezseniz manifest ve diğer konfigurasyonları manuel yapmanız gerekecektir. <dependencies> node’unun üstüne / dışına yazmamız uygun olacaktır.

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>

Eğer “parent kullanmak istemiyorum. Projemdeki jpa’nın persistence dosyası veya diğer bağımlılıklar ile çakışmalar yaratıyor” diyorsanız spring-boot-maven-plugin eklentisini aşağıdaki ikinci yöntem gibi düzenleyebilirsiniz.

3. Plugin’ler

Aşağıda targetteki java sürümünü 1.8 olarak belirlememizi sağlayan compiler plugin ve spring boot’u executable package haline getirmemizi sağlayan eklentiler yer almaktadır.

Maven compiler plugin, projenin diğer bağımlılıklarını .jar dosyasına include etmeyi sağlar. Ayrıca bu plugin ile compiling jre version belirlenebilir.

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

Parent’i kullanıyorsanız:

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin></plugins></build>

Parent’i kullanmadan:

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.3.5.RELEASE</version>
<configuration>
<mainClass>com.test.App</mainClass>
<finalName>${project.build.finalname}</finalName>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

Yukarda spring-boot ile paketleme işlemi yaptık. Normal paketleme executable package oluşturamıyor; spring boot’a özel paketleme gerekiyor. Ayrıca yukarıda görüldüğü gibi bir main class ve harici output dir verilebiliyor.

4. Packaging

Benim kullandığım projede “jpa ile ilgili problemlerimi” görmezden gelirsek, sadece mvn package çalıştırarak paketimizi oluşturabiliyoruz.

mvn clean package spring-boot:repackage

5. Start

Sonrasında windows konsolu, linux konsolu veya Jenkins CI Tool ile aşağıdaki kodu tetikleyerek servisi çalışır hale getirebiliriz.

java -jar bootsample.jar

Not: Ben docker içinde kullanacağım için işim henüz bitmedi. Docker’in image’ında çalışma ortam bilgileri de set edilmesi gerekiyormuş… araştırmaya devam edeceğim ve bir container içinde harici kaynaklar ile çalışan bir uygulama yazacağım.

Saygılarımla

sefersezer@gmail.com

Apache Solr Notlarım

Post.jar ile windowsta döküman indexleme:
java -Dc=istenenCoreAdı -jar post.jar .\example\*.xml
Indexleme aracı post.jar, http üzerinden core veya collection’un /update pathine curl isteği göndererek iş yapar. Post.jar’da input için default olarak ayarlanmış 3 tip vardır. Xml, json ve csv. Eğer bir pdf veya doc dosyası indexlenmek istenirse Apache Tika tool’u kullanılmalıdır.

Select parametreleri:
Örnek Adres: http://localhost:8983/solr/techproducts/select?q=video

  • fl: field. Sonuçlarda hangi fieldın gözükeceğini belirtmek istediğinizde bu parametre ile veriyorsunuz. fl=name,features gibi bir yazım ile birden fazla alanın gözükmesini sağlayabilirsiniz.
  • q: query. Aranan kelimedir. Örnek indexte herhangi bir alanda video kelimesi aranabilir durumdadır. field belirtilmezse tüm alanlarda (schema.xml’de öyle yapılandırılmış olmalı) arama yapacaktır. Name alanında da video ile eşleşse, id alanında da video ile eşleşse bu kayıtları response ile getirecektir. Ayrıca q içinde field da belirtebilirsiniz.
    Örneğin: http://localhost:8983/solr/techproducts/select?q=name:Apple
    q=price:[0 TO 400]&fl=id,name,price
    bu şekilde bir kullanım ile price alanına aralık verebilirsiniz
  • facet=true&facet.field=cat
    Facet Solr’ın temel özelliklerinden biridir. Facet ile sonuçlar üzerinde gruplama, kategorilendirme, sınıflandırma yapılabilir. İçeriğe göre çok farklı nitelikleri yakalayarak gruplama yapabilirsiniz. Sadece alanlara bağlı değil, içeriğe bağlı da çalışıyor olması ve çok yüksek hızlarda çalışıyor olması büyük avantajlar sağlamaktadır. Facet =true ile gelen sonuçlarda facet özelliğini kullanılabilir yapıyoruz. Basit örneğimiz için facet.field ile de gruplama yapılacak alanı belirtiyoruz. Aşağıdaki ilk adresteki gibi bir sorgu gönderdiğimizde sonuçlar üzerinde, category alanına ilişkin kullanılabilir category alanlarının sayısı gözükmektedir. Burada sadece facet alanı tanımlaması ve temel işlem olan sayıya göre gruplama yaptık.
    Facet’in daha bir çok parametresi / özelliği bulunduğundan bu category sayılarını daha farklı şekillerde kullanabilme imkanına sahibiz. Mesela ikinci adresteki gibi fq=cat:software ile filter query‘i sadece software categorysinde olacak şekilde yapılandırabiliriz. Sonuçlarda price 200 400 arasında olan, software kategorisindeki kayıtların id, name, price alanları gözükecektir.

    1. http://localhost:8983/solr/techproducts/select?q=price:%5B200 TO 400]& fl=id,name,price & facet=true& facet.field=cat
    2. http://localhost:8983/solr/techproducts/select?q=price:%5B0%20TO%20400%5D&fl=id,cat,name,price&facet=true&facet.field=cat&fq=cat:software
  • qt: Request Handler. İstekleri /select pathi üzerinden gönderebilmemiz için kullanılır. Standalone’da bir collection üzerinden istek göndeririz. Fakat cloudda nodelardan birine isteği göndermemiz gereken durumlar olabilir. Bunun için core/collection altındaki /select path’i ile select sorgu isteklerini handle edebiliriz.
  • sort: Select sorgusu ile gelen sonuçları ascending descending sıralamaya olanak sağlar. Örneğin: price desc yazdığımızda fiyatı azalan sırada listeleyecektir. inStock desc, price asc yazarak da birden fazla sorting parameter belirtebiliriz. Temel olarak sort işlemi bunlarla yapılabilir fakat sum(x,y ) desc gibi bir yazım ile de sorting query parametresi verilebilirmiş. Ben kullanmadım.
  • start: /select sorgusu ile gelen sonuçlarda, eşleşen dökümanlardan baştan kaçıncıdan itibaren göstermesini istiyorsak start a belirtmemiz gerekir. Örneğin 30 sonuç gelen bir sorguda start:10 dersek, 10. kayıttan başlayarak dökümanları listeler.
  • rows: Eşleşen dökümanlardan kaç adedinin gözükeceği belirtilir.
  • wt: gelen sonucun gösterim formatını belirler. Xml, json, python, php, ruby, csv olabilir.
  • indent: okunabilir formatta gösterim sağlar

Console Maven Projesine Web Projesi Özelliği Katmak

Merhabalar,

Daha önce File/new/maven project… yolunu kullanarak oluşturduğunuz bir projeyi web’de yayınlama ihtiyacı hissettiniz. Projeyi web projesine dönüştürebilmemiz için gerekli anahtar kelime FACETS!.

Projeye adına tıkladıktan sonra ALT+Enter ile proje özelliklerini açtıktan sonra search kısmına Facets yazalım. Burada Project Facets‘i bulacağız. Facets geldikten sonra da Javascript ve JavaServer Facets olarak seçmemiz yeterli olacaktır. JavaServer Facets sürümü 2.2 desteklemiyor ise 2.1 seçerek ve application server tipimi seçerek burada işimi bitirebilirim.

Bu arada benim bahsi geçen projemin gereksinimi olmadığından “Further Configuration Available” seçeneğinden Jsf implementation library’i disable edebilirim.

Burada maven projesini maven web projesine çevirdik. Tomcat gibi web application server altında yayınlamak için Projeyi, web projesi olarak yayınlamak için packaging tipini jar yerine war olarak değiştirmemiz gerektiği gibi diğer gereksinimleri biliyor olduğumuzu farzediyorum. Olmadı sefer.social@gmail.com adresine mail atın iki geyik yaparız…

Adsız

Apache Web Server, Load Balance & Clustering ve Site Routing – Bölüm 2

Konu 2: Load balancing yönetimi sağlayan bir yapı tasarlamayı düşünüyorsunuz.

Bir uygulamanız var. (seferOver v2.0) Bu Tomcat veya JBoss Application Server altında çalışıyor. Bir gün stabil çalışmayacak hale gelene kadar (memory leak – genellikle geliştirici hatasından kaynaklanan overflow error | https://plumbr.eu/  bir göz atın.) çok istek geldiğini gördünüz, uygulama çok trafik yükü altında kaldı ve dikey yükselmenin (bandwidth genişletme, yeni trafik alanı satın alma, memory upgrade, cpu upgrade) yetersiz olduğunu, yatay yükselmeye ihtiyacınız olduğunu farkettiniz.

Uygulamanının içinde session yönetimi yapılmalı ve bearer token kullanmıyor / kullanamıyorsunuz (http://en.wikipedia.org/wiki/OAuth) (Bu durumda MemCache veya EhCache kullanılmalı)

Yatay genişleme için birden fazla (vm veya dedicated fark etmez – Artık bizim için dedicated sunucu ayırımı yok. Hepsi aynı.) sunucuya sahipsiniz. Uygulama sunucunuzu ve uygulamanızı her birine kurup eşit veya isteğiniz oranlarda istek yükü paylaşımı yapmak (process yükü değil, request – response yükü) istiyorsunuz.

Uygulamanız sadece servis ve arayüz olarak değil dosya – lisans üretme yeteneğine sahip ve her istediğinizde her makineden doğru yanıt gelmesini istiyorsunuz… (bunun anlatacağım konuyla direkt olarak ilgisi yok. Bu konu için memcache veya ehcache kullanılmalı.)

Gereken Malzemeler:

  • Birden fazla server (test için aynı server üzerinde de yapabilirsiniz)
    Internal Lan Ip’leri 10.11.12.{13 , 14 ve 15} olan makineleri kullandım.
  • Apache Web Server (10.11.12.13)
  • Apache Web Server için mod_jk.so
  • Birden fazla Tomcat (tomcat1: 10.11.12.14 ve tomcat2: 10.11.12.15)
  • Bir uygulama. (uygulamanız kendi içinde tomcat veya jboss taşıyabilir halde de olabilir. Bu durum için farklı bir konfigurasyona gerek duyulmamaktadır.)

Uygulanan Ortam:

  • Centos 64 bit server (test amaçlı olduğu için önce 1 server üzerinde çalıştım. Sonradan farklı makinelerde test için workers.properties dosyasında localhost değerlerini internal lan IP’leri ile update etmem yeterli oldu)
  • text editör olarak nano,
  • iptables servisi,
  • Apache web server’ın yönetimi ele alması için SELinux ayarlarına erişim ve
  • Sistemi restart edebilmek için root kullanıcı yetkisi.

ve gelelim Yapılan İşlemlere:

  • Apache web server 80 portunda çalışacak. Bunda sorun yok.
    service httpd start | restart | stop ile yönetebiliyoruz. ok
  • Tomcat1‘ in conf/server.xml dosyasında aşağıdaki parametreyi http protokolü ile bu tomcat’e erişilmesini istemediğimden comment içine aldım.
<!-- <Connector port="8081" protocol="HTTP/1.1"
 connectionTimeout="20000"
 redirectPort="8443" />
 -->
  • Şimdi ajp protokolünü devreye sokalım. Tomcat1 için 8081 portu kullanılsın. Burda redirectPort parametresine karışmadım. Sadece port parametresini değiştirdim. Tomcatimiz apache’ye bu port üzerinden ajp protokolü ile haberleşecek. http üzerinden direkt tomcat’e erişme imkanımız, yukarıdaki blok comment’e alındığından mümkün değil. Eğer http de açık olsun isterseniz (test sürecinde) Http protokolü ile ajp protokolünü aynı porta vermemelisiniz.
 <Connector port="8081" protocol="AJP/1.3" redirectPort="8443" />
  • Aynı makinede 2 tomcat varsa ve birini kapatmanız gerektiği durumda diğerini etkilememesini – çakışmamasını istiyorsanız shutdown portunu da ayarlamanız gerekmektedir.
    Port değişimi:
 <Server port="8005" shutdown="SHUTDOWN">
  • Worker tanımlaması:Not: Eğer tomcat1 deki worker tanımlaması buna yapılırsa ağırlık ve istek önceliği bu sisteme verilecek. Hangisinin öncelikli yanıt vereceğini, hangisinin IDLE olarak bekleyeceğini jvmRoute parametresi belirliyor.
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1">
  • İçerik Tanımlaması:

Evet. Burası sıkıntılı. Şimdi ben uygulamamın adını myapp olarak ayarladım diyelim. Normal şartlarda tomcat’te “/myapp” veya “/”(root) path de çalıştırabilme imkanım var. Bunu zaten biliyoruz. Routing konfigurasyona geldiğimizde ise, sadece /myapp altında çalıştırma imkanım kalıyor. Ben root ‘ta çalıştırma imkanı bulamadım. Benim asıl uygulamam routing konfigurasyonunda yaptığım ayarlamalar ile root’ta çalışmadı. Belki de ben becerememiş olabilirim.

mod_proxy ile ve url redirect komutları ile /myapp dizinindeki uygulamayı root’ta göstermeyi de, virtual path yaratmayı da denedim. Belki de uygulamamdaki bir problemden kaynaklı olarak bunu becerememiş olabilirim. Çünkü küçükcük ufacık tefecik programlarla bunları becerebildim; benim kurmaya çalıştığım uygulama spring ile harmanlı olduğu için baharatları gaz yapmış olabilir (:

<Context path="/myapp" docBase="myapp" debug="0" privileged="true" />
  • Tomcat2 için yukardaki işlemleri tekrarlıyoruz
    jvmRoute=”Worker1″ konfigurasyonunu tomcat2 için yapmıyoruz. Ajp portunu aynı makinede ise 8082 yapabilirsiniz. Aynı makine üzerinde olacaksa port farklı olmalıdır. Farklı makine üzerinden apache web server’a request/response gönderecekse farklı port olmasına gerek olmamaktadır. Hatta bu durumda her ikisi de 80 bile olabilir yani.
  • Apache Web Server yüklenmiş olması gerekliliğini atlamış olabilir miyim – evet.
yum install httpd
  • Apache Web Server yüklemesinden sonra /etc/httpd/conf/httpd.conf dosyasında commentli olarak aşağıdaki yazıya benzer birşey bulunmaktadır. Onu pageDown ile gezerek bulup commentsiz olarak şunu yapıştırıyoruz
ServerName localhost:80
  • /etc/httpd/modules/ dizinine mod_jk.so dosyası kopyalandı
  • /etc/httpd/conf/httpd.conf dosyası içinde, diğer LoadModule işlemlerinin sonuna şu ayarlar yapıldı:

Burada Jk mount ayarlamalarım var. Eğer uygulamanızı root path’de çalıştırabiliyorsanız aşağıdaki gibi olacak. Eğer root path da çalışmıyorsa mecbur sonu yıldızlı isminin olduğu path’den çağırılacak. ” JkMount /myapp* myapp ”

#SEFER BEGIN
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/conf/workers.properties
#JkLogFile /etc/httpd/conf/mod_jk.log
#JkLogLevel info
#JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /status status 
JkMount /* myapp
JkMountCopy On
#SEFER END
  • Apache için /etc/httpd/conf/ dizinine yeni bir workers.properties dosyası oluşturuldu:
worker.list=loadbalancer,status
 worker.worker1.port=8081
 worker.worker1.host=10.11.12.14
 worker.worker1.type=ajp13
 worker.worker2.port=8081
 worker.worker2.host=10.11.12.15
 worker.worker2.type=ajp13
 worker.worker1.lbfactor=1
 worker.worker2.lbfactor=1
 worker.loadbalancer.type=lb
 worker.loadbalancer.balance_workers=worker1,worker2
 worker.status.type=status

Burada Tomcatler için tanımlanan portlar worker olarak girildi

lbfactor ile yük oranı 3:1, 4:2 tarzında (1:1) tanımlandı.

  • Centos sunucusu için SELINUX ayarı kapatıldı.

/etc/sysconfig/selinux dosyası için şu yönergeler izlenebilir.

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled. ***bununla değiştirdim.**
SELINUX=permissive
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
SELINUXTYPE=targeted
# SETLOCALDEFS= Check local definition changes
SETLOCALDEFS=0

  • Sistem restart edildi
  • Httpd servisi başlatıldı, tomcatler çalıştırıldı.

İşlemler bu kadar. Yazının başında bahsettiğim ihtiyaçları karşılayabilecek yapıyı kurduk. Balance ayarlarını kullacağınız sistemlerin ağ ve donanım hızlarına göre ayarlayabilirsiniz. Tertemiz oldu. Hepsi bukadar.

Apache Web Server, Load Balance & Clustering ve Site Routing – Bölüm 1

Konu 1: Bir apache Serverda birden fazla farklı tomcat’ı çalıştırmak istiyorsunuz.

Bunlar farklı uygulamalar çalıştıran tomcat’ler ve biri durdurulursa diğeri etkilenmemeli.

Aynı domain veya IP altından internete çıkmalılar. Port numarası görmek istemiyorsunuz.
Örneğin developer.sefersezer.com/jira ve developer.sefersezer.com/wiki

Dışarıdan bu uygulamalara erişilmesini istemiyorsunuz. Direkt olarak tomcat1’in bulunduğu makineye istek gitmesin, apache web server bunu yönetsin istiyorsunuz.

Yönetimini sağlayan apache web server makinesi ile aynı veya farklı makineler altında olabilme esnekliğine ihtiyacınız var; yani web server’a birşey olma durumunda farklı web server altından bu tomcatleri dışarıya çıkarmayı istiyorsunuz.

Sen Neymişsin Be Java!

“Java biliyorum” diyebilmek için neler gereklidir? Yazılımsal ve fikirsel olarak nelere ihtiyaç vardır? Sadece teorik olarak JAVA dilini bilmek yeter mi yoksa insanın canından bezdiren kurulum aşamaları, linux, mvc disiplini, en az bir framework ve gerekli araçların da (artık bu saatten sonra teorinin yetmeyeceğini anlamışsınızdır) öğrenilmesi biliyorum diyebilmeye yetecek mi?

.net frameworkune aşina, webde 2-3 yıl asp.net olsun .php olsun javascripti olsun deneyimler kazanan insanlar javaya ne kadar alışabilir? Ve daha birçok soru var aklımda cevaplanmayı bekleyen…


01.01.2015
Geçtiğimiz yılda java dili ve ortamı için önemli adımlar attım. Biraz anlatmak kendim için de iyi olacaktır. Hemen başlıyorum,
Geçtiğimiz sene Spring Framework’un kabiliyetlerine göz attım. Bunun için internette yabancı kaynaklı birçok pdf var. Bunlara boş vakitlerde göz gezdirerek Spring ile neler yapılabilir, genel olarak bahsetmek gerekirse notasyon yönetimi ne fark ve fayda sağlar, Spring Framework hangi ortamlarda kullanılabilir, MVC managment’i nasıldır bunları gördüm.
Bir örnekle; android için, web ortamı ve desktop ortamı için yazdığınız kodu Spring ile yönetebilirsiniz. Veritabanı için hazır kütüphaneleri kolaylıkla kullanabilir, Spring mvc & hibernate ile kurumsal projelere ayak uyduracak kodlar yazabilirsiniz.
Gerçekten de etkilendim. Java ortamı, Spring Framework & Yeteneklerini kullanabilen geliştiricileri kendine bağlıyor. Java, üzerine uzmanlaşıp onunla ömür boyu yaşamaya değer bir dil ve ortam sağlamış. Kod yazmaktan zevk alan insan daha ne ister ki! Bu aşık eder insanı kendine.

“Kurumsal işleri için Java kullanılır” sözünü java ile geçirdiğim süre içinde değerlendirdiğimde her şeyin bu ortamda yıllar önce temelinin atıldığını, bir düzenin kurulduğunu gördüm. Zor işlerin java ile başarıldığını gördüğümde, Jvm’in yeteneklerini, jvm’in big data managment projelerinde sağladığı esneklikleri gördümde “işte aradığım bu” dedim.

Hani şu beğenmediğimiz 200 – 300 mb’lık Eclipse var ya, öyle yeteneklere sahip olabiliyor ki .Net Visual Studiodan daha eğlenceli olabiliyor! Projelerin çoklu geliştirici desteği, repository ve code history yönetimi, -her konuda- bağımsızlık, testler (testler çok önemli. Ayrı başlıkta bunun önemine değinmeyi planlıyorum), taşınabilirlik, kütüphane yönetimi, mocking, dakikalar içinde service yazmak gibi konularının önemli olduğu projelerde (kısaca kurumsal ve büyük projelerde 🙂 ) java ve ortamı kullanılmalı. .Net artık benim için bir alternatif. Bundan eminim. .Net ortamı için Microsoft Foundation Server ve Cloud Development için Azure (bunların registration süreci bile insanı boğuyor) gerekiyorsa JAVA tarafında da elbet bir karşılığı var ve kullandığımız ortam; yıllar önce okulda Java dilinde ekrana “hello sefer” yazıp kapattığımız Eclipse ortamı …