Spring etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Spring etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

15 Nisan 2015 Çarşamba

Spring Service Sınıfları

Giriş
Klasik bir servis sınıfı veritabanıyla çalışmak için kullanılır. Şöyle tanımlanır.

@Service
public class UserServiceImpl implements UserService
{
  @Autowired
  private UserDAO userDAO;

  @Override
  @Transactional
  public void addUser( User user )
  {
    userDAO.addUser( user );
  }
}

20 Eylül 2013 Cuma

Spring Bean XML Tanımları

Spring IoC XML tanımları ile ilgili aldığım notlar aşağıda.

Yaratılmış Olan Bean'e Değer Atamak
Tek Parametreli Setter İle Bir Başka Bean Atamak
Örnek buradan geldi.
<property name="beanTwo" ref="yetAnotherBean"/>
Tek Parametreli Setter İle Değer Atamak
Örnek buradan geldi.
<property name="name" value="myvalue" />
Tek Parametreli Setter İle List Atamak
Örnek buradan geldi.
<property name="list">
    <list>
        <value>1</value>
    </list>
</property>
Bean Yaratmak
Constructor metoduna parametre geçmek
Örnekte constructor parametreleri string ise aynen geçilir. int long tipleri ise XML'de hangi tip oldukları belirtilir.

<bean id="Pool" class="org.apache.commons.pool.impl.GenericKeyedObjectPool">
  <constructor-arg type = "int" name = "maxActive" value="3" />
  <constructor-arg type = "long" name = "maxWait" value="3000" />
  <constructor-arg name = "testOnBorrow"  value="true" />
</bean>

Factory Sınıf ile Bean Yaratmak
Elimizdeki sınıfın bean yaratmak için static bir metodu varsa aşağıdaki gibi kullanabiliriz. Örnekte Pattern sınıfının static olan compile metodu yeni bir bean yaratmak için kullanılıyor.
<bean id="pattern" class="java.util.regex.Pattern" factory-method="compile">
    <constructor-arg value="abc"/>
</bean>

1 Temmuz 2013 Pazartesi

Spring TaskExecutor ve AsynchTaskExecutor

Anotasyon Kullanarak Asenkron ÇalışabilmekSpring ile anotasyon kullanarak asenkron çalışabilmek için eklenmesi gereken bir kaç konfigürasyon parametresi var. Örnek aşağıda.
<task:annotation-driven executor="executor"/>
<task:executor id="executor" pool-size="2"/>

task:annotation-driven ile @Async ile işaretlenmiş metodların bir thread içinde çalıştırılması sağlanıyor. Ayrıca @Scheduled olarak işaretlenmiş metodların da periyodik olarak çalıştırılıyor.

Burada task:annotation-driven sadece tek bir bean olabileceği yazılı. Eğer birden fazla olsaydı, anotasyonlu metodların hangi executor tarafından çalştırılacağını belirtmek gerekirdi, ancak şu anda bunu destekleyen bir tasarım yok.

Executor Hiyerarşisi

Executor hiyerarşisini aşağıya ekledim.

TaskExecutor
Java'dan türeyen bir başka arayüz.
AsynchTaskExecutor
AsynchTaskExecutor bir arayüz ve verilen işin bir başka thread içinde koşabilmesini sağlıyor.
En önemli metodu bir Future nesnesi döndürebilen Future<?> submit(Runnable task) metodu.

ThreadPoolTaskExecutor
ThreadPoolTaskExecutor AsynchTaskExecutor arayüzünü gerçekleştiren bir sınıf. Bu sınıfını yaratmanın en kolay yolu aşağıdaki gibi. Bu sınıf arka planda ThreadPoolExecutor sınıfını kullanıyor.

pool-size:
 ile "core pool size" yani kaç thread'in hayatta kalacağı belirtiliyor.

queue-capacity:
Örnek: core pool size sayısınca thread hayattaysa ve hiçbiri boşta değilse, yeni gelen iş kuyruğa eklenir. Bu kuyruğun büyüklüğü atanır. 

Anotasyonlar
@Async
Bu anotasyon ile işaretlenmiş metodlar, task executor içindeki bir thread tarafından çalıştırılır.


@Scheduled ve cron
Spring ile cron benzer belli zamanlarda iş çalıştırmak mümkün. Cron zamanlaması için kullanılan syntax 6 kısımdan oluşuyor . Solda sağa okursak:
1. Saniye
2. Dakika (0-50 arasında değer alır)
3. Saat (0-23 arasında değer alır)
4. Ayın kaçıncı günü (Rakamla)
5. Hangi ay
6. Gün   (Rakamla. Pazar 0'dan başlar veya yazı ile)

Eğer syntax'ta * varsa tüm anlamına geliyor. Eğer birimin yanına /(slash) ile başlayan bir sayı eklenmişse her anlamına geliyor. Eğer birim ,(vigül) içeriyorsa işlem birden fazla defa yapılacak demektir.

Tekrar Eden Örnek

*/5 * * * * : Her 5 dakikada bir tüm zamanlarda çalıştır


Tekrar Eden Mutlak zaman örneği
Ayda bir çalıştırmak
 @Scheduled(cron="0 0 1 6 * ?")  //Her ayın 6'sında gece 1 de başla

Gün içinde bir kaç defa çalıştırmak
0 1,13 * * * /etc/init.d/httpd restart //Gece 1 ve gündüz 13'te apache sunucusunu yeniden başlat

29 Ocak 2013 Salı

Spring ve DAO

Spring ve DAO

Spring ile Hibernate veya JDBC kullanan DAO sınıfları yazmak mümkün.Aşağıdaki şekilde kırmızı çerçeve içinde DAOSupport sınıfından türeyen HibernateDaoSupport ve JdbcDaoSupport sınıfları görülebilir.


DAO ve Repository Arasındaki Fark Nedir
Yukarıdaki sınıf hiyerarşisinde de görüldüğü gibi sınıflarımız xxxDaoSupport kelimesi ile biten sınıflardan türemesine rağmen,  @Repository anotasonu ile işaretleniyorlar. Repository ile DAO arasındaki fark nedir ?
DAO aynı zamanda Table Data Gateway olarak ta adlandırılıyor. Repository, Domain Modelini dönen nesne. Çoğunlukla DAO ile Repository aynı şeyler. Farklı oldukları durumu açıklayan bir yazı burada.

JDBCDaoSupport

JdbcDaoSupport sınıfı da kendi içinde bir hiyerarşiye sahip. Aşağıdaki şekilde bunun bir örneğini görmek mümkün. Örneğin NamedParameterJdbcDaoSupport sıfını buna bir örnek olarak verilebilir.


Aşağıda NamedParameterJdbcDaoSupport sınıfını biraz daha detaylı gösteren bir şekil var.


DAO ve Template Kullanımı

Spring ile gelen tüm sınıflarda template tasarım örüntüsü kullanılıyor. Veritabanına erişim için kullanılan kodlar bir template içinde gizli. Aşağıdaki şekil bunu gösteriyor.


DAO ve Exception
 
DAO sınıflarını @Repository anotasonu ile kullanırsak alt tarafta kullanılan veritabanı erişimi kütüphanelerinden atılabilecek exceptionlar Spring tarafından belli bir hiyerarşi altında gruplanırlar. Böylece veritabanı kütüphanesinden daha bağımsız kod geliştirmek mümkün olur. Aşağıda Spring tarafından kullanılan exception hiyerarşisini gösteren bir şekil bulabilirsiniz.


11 Aralık 2012 Salı

Spring ve Bean Yaratılması

Not : Dependency Injection sınıflar arasındaki bağımlılığı azaltırken altyapıya olan bağımlılığı artıyor.
Dependency injection increases coupling by requiring the user of a subsystem to provide for the needs of that subsystem.

1. Spring İçindeki Olayları Dinlemek

Spring Container da diğer tüm container tarzı yazılımlar gibi, kendisine abone olunup Observer tasarım örüntüsünün kullanılmasına imkan tanımaktadır. Bu durumu gösteren şekli buradan aldım. Böylece ApplicationListener arayüzü vasıtasıyla bir çok olayı öğrenmek mümkün.



2. Spring ve Bean'lerin Yaratılması

2.1 Bean Yaratılmadan Önce

Aşağıdaki şekli buradan aldım. Bean yaratılmadan önce BeanFactoryPostProcessor ile bean tanımında değişiklik yapabilmek mümkün.



Aşağıdaki şekilde ise BeanFactoryPostProcessor arayüzünden türeyen bazı sınıfları görmek mümkün.


2.2 Bean Yaratıldıktan Sonra

Spring içindeki bean'lerin yaşam döngüsünü (lifecycle) bir nebzeye kadar detaylandırmak mümkün. Bunun için kullanılabilecek 3 yöntem var.

  1. BeanPostProcessor Yöntemi
  2. XML içinde Custom Metod  Yöntemi
  3. InitializingBean ve DisposableBean Yöntemi
BeanPostProcessor Yöntemi
Bu başlığı ikiye ayırmak lazım. Birincisi Spring içinde tanımlı olan BeanPostProcessor sınıfları, ikincisi ise kendi tanımladığımız sınıflar.
Spring içinde tanımlı olan BeanPostProcessor sınıfları
BeanPostProcessorYöntemi burada anlatılıyor. Örneğin <tx:annotation-driven> XML cümlesi ile BeanPostProcessor yöntemi aracılığıyla transaction yönetimi gerçekleştiriliyor. Bir bean yaratılmadan önce bir BeanPostProcessor @Transactional anotasyonu kullanılmışmı diye kontrol ediyor ve eğer kullanılmışsa yaratılmak istenen bean için bir proxy üretiyor.

Bir başka örnek olarak org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor sınıfına da bakılabilir. Bu sınıf ile ilgili güzel bir örnek te burada bulunabilir.

Bu sınıf sayesinde @Autowired, @Inject, @Resource gibi tagler kullanılabiliyor.

Bu sınıfı Spring'e dahil etmek için <context:annotation-config /> veya <context:component-scan> XML cümlelerini eklemek yeterli. Bu ikisi arasındaki farkı anlamak için Difference between <context:annotation-config> vs <context:component-scan> başlıklı yazıya bakabilirsiniz.

<context:component-scan> ile @Component, @Repository, @Service ve @Controller olarak işaretli bean'ler Spring'e dahil ediliyor. Eğer bu taglerden bazılar hariç bırakılmak istenirse aşağıdaki gibi yapılabilir.

<context:component-scan base-package="com.java.test.app org.java.support">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

Kendi Tanımladığımız BeanPostProcessor Sınıfları
Buradaki örnekte Spring ile yaratılan bir bean nesnesinin Guava EventBus nesnesine eklenmesi örneği var.
 

Custom Metod Yöntemi
Bu yöntemde XML içinde bean'in çağırılacak metodu belirtliyor.

InitializingBean ve DisposableBean Yöntemi
Bu yöntemde bean InitializingBean ve DisposableBean arayüzlerinde türetiliyor.

Yöntemler arasında öncelik sırası bulunmakta. Bu öncelik sırasını gösteren bir şekli burada buldum.

Görüldüğü gibi InitializingBean arayüzü tarafından istenen afterPropertiesSet() metodu custom init metodundan önce çağırılır. Aynı zamanda DisposableBean arayüzü tarafından istenen destroy() metodu da yine custom destroy metodundan önce çağırılır.



Benzer bir şekli ise burada buldum.


InitializingBean yöntemi Spring'e mahsus. JSR-250 ile @PostConstruct ve @PreDestroy  tagleri tanımlanmış. Using JSR-250's @PostConstruct Annotation to Replace Spring's InitializingBean başlıklı yazıda da anlatıldığı gibi Spring'e mahsus bu arayüzler yerine @PostConstruct ve @PreDestroy anotasyonlarının kullanımı tercih edilmelidir.

2.3 new() ile Yaratılan Bean'ler
How to inject dependencies into a self-instantiated object in Spring? sorusunda da cevaplandığı gibi AutowireCapableBeanFactory arayüzü kullanılarak manuel olarak yaratılmış olan bir bean'e de dependency injekte edilebilir.


2.4 Bean ve Yaratılış Kapsamı (Scope)

Spring ile default gelen scope singleton scope'tur. Yani container bir bean'i bir defa yarattıktan sonra onu önbellekte saklar ve tekrar istenirse yine aynı nesneyi döndürür. Bu durum gösteren bir şekli buradan aldım.

Konuyu daha iyi açıklayan bir örneği ise burada bulabilirsiniz.


19 Eylül 2012 Çarşamba

Spring ve Factory Bean

Spring içindeki bazı FactoryBean sınıflarına örnekler. Collections başlıklı yazıya bakmakta da fayda var.

ListFactoryBean
ListFactoryBean sınıfı ile ilgili gördüğüm güzel bir cevap how does the <list> tag work in spring başlıklı soruda var.

Buradan aldığım örnekte List yaratan bir ListFactoryBean örneği var.


12 Eylül 2012 Çarşamba

Apache Wicket ve Spring


Yazıya başlamadan önce hem Apache Wicket hem de Spring'in  bir servlet container içinde çalıştığını unutmamak lazım. Dolayısıyla ilk yapılması gereken iş, Servlet container ile bu iki yazılımı birleştirmek olmalı.

Spring ve Servlet Container


Spring ile Servlet Container'ı birleştirmeyi buradan aldığım şekil güzel açıklamış. Servlet Container bir spring sınıfı olan org.springframework.web.context.ContextLoaderListener sınıfını kullanarak Spring'i ayağa kaldırır. org.springframework.web.context.ContextLoaderListener sınıfının hiyerarşisi aşağıda.




ContextLoaderListener web.xml dosyasına aşağıdaki gibi tanımlanır.

ContextLoaderListene sınıfının okuması gereken dosyalar ise aşağıdaki gibi tanımlanır.

Burada okunacak dosyanın WEB-INF dizini altında olduğuna dikkat etmek lazım. Çünkü war dosyasının yapısı aşağıdaki gibi.

ContextLoader okuması söylenen dosyaları aşağıdaki şekildeki gibi okur ve Spring framework çalışmaya başlar.

Spring ayağa kalkınca herşeyin kalbi olan "ApplicationContext" nesnesini bir yerde saklaması gerekir. Bu iş için de ServletContext arayüzünü kullanır. Bu durumu gösteren şekli buradan aldım.

ServletContext içinde bir nesne saklanmasını göstern örnek kodu buradan aldım.

// following method is invoked one time, when you web application starts (is deployed)
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    // ...
    final int numberOfThreads = ...;
    final ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads); // starts thread pool
    final ServletContext servletContext = servletContextEvent.getServletContext();
    servletContext.setAttribute("threadPoolAlias", threadPool);
    // ...
}

// following method is invoked one time when your web application stops (is undeployed)
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    // following code is just to free resources occupied by thread pool when web application is undeployed
    final ExecutorService threadPool = (ExecutorService) servletContextEvent.getServletContext().getAttribute("threadPoolAlias");
    threadPool.shutdown();
}

Apachet Wicket ve ServletContainer

 Apache Wicket ile ServletContainer'ın nasıl birleştiğini aşağıdaki şekil gösteriyor.
Daha sonra javax.servlet.ServletContext nesnesine erişmek için Wicket Notes yazısındaki kod parçası kullanılabilir.


Eğer bir war dosyası içindeki relative path kullanmak istiyorsak Wicket - Relative Image Path without Mounting Page sorusundaki gibi UrlUtils.rewriteToContextRelative metodu kullanılabilir. context.getRealPath() metodu /MyApp gibi bir dizin döndürdüğü için rewriteToContextRelative  metodu /MyApp/images/img1.png gibi bir path döndürür. Aşağıda war dosyasının dizin yapısı görülebilir.


Benzer bir işi How do i link to my Image-Folder inside my Apache Wicket Application? sorusunda cevaplandığı gibi ContextRelativeResource sınıfını kullanarak ta yapabiliriz.
  Apachet Wicket içinden Spring ApplicationContext'e erişmek


Spring ile entegre olmak için wicket-spring.jar dosyasının projeye dahil edilmesi gerekiyor.


Apache Wicket ve Spring'i birbirine entegre etmek çok kolay. Nasıl yapılacağı burada anlatılıyor.

Not : Spring ve Bean Yaratılması başlıklı yazıda Spring Container'ın çalışması ile ilgili biraz daha detaylı bilgi bulabilirsiniz.

1. Annotation Yöntemi

En kolay yöntem de Annotation Based Approach paragrafında anlatıldığı gibi yapmak. Aşağıda buradan aldığım @SpringBean anotasyonu kullanılan örnek bir kod parçası var.


Spring-Wicket: optional but named bean still required sorusunda da anlatıldığı gibi @SpringBean ile required=false kullanarak enjeksiyonu engellemek te mümkün.

2. Kod İle Elle Enjeksiyon Yöntemi
 
Yalnız bu dokümanda dikkat edilmesi gereken bir nokta var. Örnekte de verildiği gibi SpringComponentInjector sınıfı sadece Wicket Component'ları yaratıldığı zaman çağırılan bir listener.Aşağıdaki şekilde bir Component yaratılınca nasıl listener'ın çağırıldığını görmek mümkün.



Halbuki Wicket içindeki her sınıf Component sınıfından türemiyor. Örneğin Model sınıfı gibi. Aşağıdaki şekli buradan aldım ve Component hiyerarşisini kabaca gösteriyor.



Bu durumda model sınıfında @SpringBean anotasyonu kullanılsa bile işe yaramaz.Bunun yerine


InjectorHolder.getInjector().inject(this)

kodunu kullanmak lazım.

Bu da Wicket'ın bir azizliği işte. Bir çok yazılım çatısında da çatıdaki her sınıfın ortak bir atadan türemediğini gördüm. Burada da aynı durum var ve nadiren de olsa bazen normal kullanımdan sapmayı gerektirebiliyor.

3. Kod İle ApplicationContext Nesnesine Erişim Yöntemi

Yukarıda kod ile enjeksiyon yönteminde enjekte edilecek nesnelerin sınıfın bir üyesi (member attribute) olması gerekiyor. Eğer bunu da istemiyorsak ve metod içinde kullanmak üzere ApplicationContext nesnesine erişmek istersek Spring bize kolaylık olması için WebApplicationContextUtils isimli sınıfı kullanılabilir.

Aşağıdaki örnekte olduğu gibi Wicket'ın Application sınıfından ApplicationContext nesnesine erişim mümkün.

public ApplicationContext getContext() {
        return WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
 }


Wicket Stateful ise Spring ile Nasıl Entegre Oluyor ?

Wicket statefull bir yazılım. Bu durumu anlatan güzel bir örneği burada bulabilirsiniz. Bu basit örnekte aynı safya defalarca tazelendiği halde Wicket'ın nasıl stateful çalıştığı anlatılmış. Aslında Wicket bir oturum içinde gösterilen tüm sayfalar için state tutuyor. Bu durumu gösteren güzel bir şekli buradan aldım.


Bu çalışma modeli bir sayfa'nın içindeki herşeyin Serializable olmasını gerektiriyor. Peki bu durumda sayfaya enjekte edilen Spring Bean'lerin de Serializable olması gerekmiyor mu ? Hal böyle ise bir bean ve onun bağımlı olduğu tüm beanlerin de yazılması gerekir.

Eğer böyle olsaydı Wicket Spring ile hayatta entegre olamazdı. @SpringBean ile enjekte edilen sınıf aslında bir proxy. Dolayısıyla @SpringBean ile Spring Framework'teki kullanımın aksine sadece interface kullanılabilir. Sayfa da session'a yazılınca üretilen proxy yazılıyor, atıfta bulunduğu Spring Bean sınıfı değil. Bu durumu açıklayan güzel bir soruyu burada buldum. Yine aynı konuya değinen güzel bir cevabı da burada buldum.. Bir diğer açıklama ise Double-click seems to disrupt Wicket-Spring injection sorusunda açıklanmış.

12 Nisan 2012 Perşembe

Spring ApplicationContext

Spring ApplicationContext ile Otomatik Yüklenen Beanler

Aşağıdaki şekli buradan aldım ve ApplicationContext ayağa kalkarken otomatik olarak yüklenilen bazı beanleri gösteriyor.

MessageSource
MessageSource bean'i Spring konfigürasyon dosyaları arasında varsa ApplicationContext ayağa kalkarken otomatik olarak yüklenilir. Bir örneği burada bulmak mümkün. Tek yapılması gereken ismi messageSource olan bir bean tanımlamak.

Bu bean'i kendi kodumuz içine enjekte etmek istersek tek yapmamız gereken kendi sınıfımızı MessageSourceAware arayüzünden türetmek. Örneği burada bulabilirsiniz.