Sansür, bir toplumun kendine olan güvensizliğini yansıtır ve otoriter rejimlerin belirgin bir özelliğidir.

--Potter Stewart

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

30.12.2010

Spring ile Hibernate Annotation Kullanılan Entity Sınıfların Otomatik Algılanması

Veri erişim katmanında JPA standartını kullanırken annotation ile tanımladığımız entity sınıflarımızın algılanması, proje ayağa kalkarken otomatik gerçekleştirilir. Araya JPA standartını sokmak yerine doğrudan Hibernate çatısını kullanmak istediğimizde annotationlarla tanımlanmış bu entity sınıflarının algılanabilmesi için kullanılagelen yaygın yöntem ya hibernate.cfg.xml içersinde bu sınıfları algılatmak ya da her bir entity sınıfını Spring'in Hibernate entegrasonu için kullanıma sunduğu AnnotationSessionFactoryBean tanımı içinde tek tek belirtmektir:

<bean id="sessionFactory"
 class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 <property name="dataSource" ref="${dataSourceType}" />
 <property name="hibernateProperties">
  <props>
   <prop key="hibernate.dialect">${hibernate.dialect}</prop>
   <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
   <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
   <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
  </props>
 </property>
 <property name="annotatedClasses">
  <list>
   <value>com.prime.ExampleClass1</value>
   <value>com.prime.ExampleClass2</value>
  </list>
    </property>
</bean>


annotatedClasses'ın bu şekilde kullanımı entity sınıf sayısı arttıkça sıkıntı yaratmaya başlayabilir. Bunun yerine aynı Spring bean'in packagesToScan değişkeni uygun paket yapısıyla kurarak uzun uzadıya sınıf tanımları yapmaktan kurtulabilirsiniz:

<property name="packagesToScan" value="com.prime" />

ya da

<property name="packagesToScan">
 <list>
  <value>com.prime.package1.model</value>
  <value>com.prime.package2.model</value>
 </list>
</property>

Hibernate annotation kullanan entitylerinizin otomatik algılanması için yukardaki tüm kullanımlara ek olarak proje classpath'inde javassist.jar kütüphanesi de bulunmalıdır..

21.12.2010

Spring - JSF Yeniden (JSF 2.0)

Blogta ziyaret edilen girdilere göz attığımda "Spring - JSF Bütünleştirmesi" yazımın son zamanlarda tekrar ziyaret edildiğini farkettim. Hazır geçen hafta da JTPD'nin eğitim seminerlerinde bu konular üzerine eğilmişken iki çatının entegrasyonunu, değişen yeteneklerini de dikkate alarak tekrar gözden geçirelim istedim.

Eski girdide bu iki çatıyı birbirleriyle anlaşır hale getirebilmek için JSF'ye variable resolver olarak Spring'in bize sunduğu DelegatingVariableResolver sınıfını tanıtmıştık. Bu sınıf iki çatı arasında bean aktarımlarını gerçekleştirmek için aktarımı yapılacak beani öncelikle JSF beanlerinde, bulamazsa Spring beanlerinde arıyordu. Benzer şekilde, önce Spring bean tanımlarına sonra da JSF bean tanımlarına bakan SpringBeanVariableResolver Spring sınıfını da JSF 1.1 ve 1.2 sürümlerinde kullanabiliriz.

JSF 1.2+ sürümlerinde ise variable resolver kullanımı yerini ELResolver'a bırakıyor:

<faces-config>
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
  </application>
</faces-config>


Spring ile JSF'i bu şekilde ilişkilendirdikten sonra eski yazıdaki örneği bu sefer JSF 2.0'ın annotationlarını kullanarak Spring beanini JSF bean tanımı içine aktarımını yapalım:

@ManagedBean(name="member")
@RequestScoped
public class Member {

 @ManagedProperty(value="#{memberService}")
 private MemberService memberService;

 // memberService getter/setter
}

Spring bean tanımını da @Service("memberService") ya da @Component("memberService") annotationlarını kullanarak da xml'e bulaşmadan MemberService sınıfı içinde yapabiliriz:

@Service("memberService")
public class MemberServiceImpl implements MemberService {
    // ...
}

Spring annotationlarının çalışması içinse Spring context xml tanımınına ya <context:component-scan base-package="com.prime.packname"></context:component-scan> satırını eklemeli ya da web.xml içerisinde Spring bean tanımlarını xml yerine annotation kullanarak yapacağımızı belirten gerekli düzenlemeleri yapmalıyız:

<web-app>
      <context-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
      </context-param>

      <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.prime.packageName</param-value>
      </context-param>
</web-app>


Bu işlemlerin ardından annotationlarla tanımladığımız Spring ve JSF beanlerini birbirine entegre olarak kullanabiliriz. Bol Javalar..

12.12.2010

JTPD'de JSF, Spring ve JPA Sunumları

Dün JTPD'nin düzenlediği Java eğitimlerinin 3. haftasında katılımcılara JSF, Spring ve JPA sunumları yapma fırsatım oldu. Sunumların ardından küçük örnekler yaparak da anlatılan konuları pekiştirmeye çalıştık. Her ne kadar bahsi geçen konuları detaylı incelemek için 4-5 saat gibi çok çok kısıtlı süremiz olsa da mümkün olduğunca bu çatılar (framework) bizlere neler vaat ediyor, yetenekleri neler ve birbirleriyle nasıl entegre edebiliriz konuları üzerinden hızlıca geçtik. Anlatılan konular katılımcılar için zaman zaman detaylı ve karmaşık olsa da beni sabırla dinledikleri için kendilerine çok teşekkür ederim. Umarım faydalı olabilmişimdir. Hazırladığım eğitim sunumlarına ve örnek projelere buradan erişebilirsiniz. Java kültürünü daha geniş kitlelere yaymaya çalışan JTPD derneğini de tebrik ediyorum..

13.08.2008

POJO vs. EJB 3.0

POJO ve EJB, Java EE geliştiriminde tercih edilen iki ayrı programlama modeli. Bu iki teknoloji, EJB 3.0'ın öğrenilmesi zor ve karmışık programlama modelini terkederek POJO tabanlı bir model seçmesiyle aynı eksende ilerleyecek gibi duruyor. Ama hala göz ardı edilemeyecek farklılıklar mevcut. POJO programlama modelini temel alan Spring çatısını kendine örnek alan EJB ile POJO'yu kıyaslarken elde ettiğim sonuçları özetlemeye çalıştım:


POJO

EJB 3

Basitlik

Mimarinin geliştiriminde göz önünde tutulan nesne yönelimli ilkeler sayesinde öğrenilmesi ve kullanılması kolay bir yapıya sahip. Basitlik ve tutarlılık ön planda.

Getirdiği mimari artılarına karşın EJB 1.0 sürümünden bu yana değişen programlama modeli ve öğrenim maliyeti projeler için dezavantaj oluşturuyor.

Test Edilebilirlik

POJO yapısı sayesinde Bağımlılık aktarımı (Dependency Injection) örüntüsü kullanılarak bileşenlerin kolay ve hızlı test edilebilirliğine imkan sağlıyor. Testler containerdan bağımsız yapılabiliyor.

Bağımlılık aktarımının sadece JNDI nesneleri ile yapılabilmesi, Session ve message-driven beanlerinin POJO olmalarına rağmen EJB Container’a ihtiyaç duymaları sebebiyle test edilebilirlik kısıtlanıyor. Bu da geliştirim sürecini olumsuz etkiliyor.

Geliştirim Ortamı

Tomcat gibi hafif (lightweight) containerlarla geliştirilen web uygulaması hızlıca çalıştırılabiliyor.

Geliştirilen uygulamanın çalıştırılabilmesi için ağır uygulama sunucularına ihtiyaç duyuyor. Projenin ihtiyaç duymadığı özellikler de uygulama sunucusu ile ayağa kaldırılıyor.

Collections Desteği

Hibernate çatısı ile persistence katmanında Set<String>, Set<Integer> gibi entity beanlerden oluşmayan collectionlara doğrudan destek sağlıyor.

Persistence katmanında sadece entity beanleri için collection desteği sağlıyor. Set<String>, Set<Integer> gibi collectionlara doğrudan destek sağlamıyor.

Konfigürasyon

Spring Bean configuration dosyalarına ihtiyaç duyuyor. Annotation desteği sunuyor.

Spring Bean configuration dosyalarından daha karmaşık bir yapıya sahip EJB descriptor dosyalarına ihtiyaç duyuyor. Annotation desteği sunuyor.

Persistence API

Kendine ait bir persistence api olmamasına karşın Template örüntüsü ile desteklenen; Hibernate, Ibatis, JPA gibi popüler çatılarla ve JDBC ile kolayca entegrasyona izin veren bir mimari sağlıyor.

EJB 3 ile Entity beanlerin yerini Hibernate, Toplink, JDO gibi persistence API’lerden devşirilen JPA belirtimi alıyor. Belirtim olması sebebiyle belirtimin yetersiz kaldığı yerlerde geliştirim sağlayıcısına bağımlı kalınabilmektedir.

Transactions

Dağıtık transaction mimarisini JTA ile destekliyor. Spring AOP çatısı ile annotationlar kullanılarak 7 farklı Propagation-bazlı transaction tanımlanabiliyor. Transactionlar XML konfigürasyon dosyalarında ya da aspect yaklaşım kullanılarak tanımlanıyor. Spring JDBX, Hibernate ve JTA ile entegre olabiliyor.

Dağıtık transaction mimari geliştirimine olanak sağlıyor. Session beanlerin tüm public metodlarına transaction mantığı otomatik olarak uygulanıyor. Annotation tabanlı bir transaction yönetimi bulunuyor. Sadece JTA’yı destekliyor. JTA Tomcat gibi hafif containerlarda çalışmıyor.

Güvenlik

ACEGI güvenlik çatısıyla hem nesne method çağrımı hem de HTTP istemlerinde doğrulama ve yetkilendirme yapılabiliyor. Rol-bazlının yanı sıra ACL-bazlı yetkilendirme de sağlıyor. Uygulama sunucusundan bağımsız standart bir güvenlik katmanı sağlıyor.

Tanımlı method-düzeyi rol-bazlı yetkilendirme, programatik rol belirleme özelliklerine sahip. EJB belirtiminin yeterli olmaması sebebiyle, güvenlik gerçekleştirimini uygulama sunucusuna bırakıyor. Böylece güvenlik katmanı uygulama sunucuna bağımlı hale geliyor.
















































Summation of Persistence Comparison Between Spring and EJB 3.0.

Feature

Spring

EJB 3.0

Simple ORM Persistence

√

√

Implementation

Hibernate, JPA, JDO, TopLink, iBatis

JPA (providers include Hibernate, Kodo and Toplink)

JDBC Support

√

--

Mapping

XML, Annotations

Annotations, XML

Cache Propagation

Thread local

Transaction

Extended cache scoping

Open session in view

Extended persistence context


Equivalent Transaction Management Functionality in Both Spring and EJB 3.0.

Feature

Spring

EJB 3.0

Declarative Transactions

√

√

Programmatic Transactions

√

√

Demarcation

AOP

Session bean methods

Supported Transaction Types

JDBC, Hibernate, JTA

JTA

Support for Distributed Transactions

√ (With JTA)

√

Configuration

XML

Transactional by default, override with annotations or XML


Teknolojilerin Google Trend’ten elde edilen yıllara göre arama sonuçlarının karşılaştırma tabloları:

ejb

Frame2

1.00

pojo

Frame3

0.16



ejb

Frame4

1.00


hibernate

Frame5

1.84

jpa

Frame6

0.24



Sonuç olarak Java EE uygulamalarda EJB'nin tercih edilmesini gerektirecek tek durum dağıtık transaction yönetimi ihtiyacı. POJO (dolayısıyla Spring) bu ihtiyaca karşılık veremiyor. Bunun dışındaki senaryolarda değişen trendler de göz önüne alınarak POJO programlama modelini temel alan çözümlerin (Spring, Hibernate, vs.) (EJB 3.0 gibi kopyalarının yerine :) ) seçilmemesinde hiç bir neden yok.

Kaynaklar

1.02.2008

Spring JDBC Kalıplarının (Templates) Kullanımı

Hibernate, iBATIS, JPA, vb. veri erişim teknolojilerinin sağladığı artılar bir yana bırakıp veri tabanına daha alt düzey erişimlerde bulunmak için JDBC tercihi yapılabilir. JDBC soyutlaması için Spring üç ayrı kalıp sınıfı sunmaktadır:


  • JdbcTemplate (parametreleri indeks değerleri ile atama)

  • NamedParameterJdbcTemplate (parametreleri isimlerle atama)

  • SimpleJdbcTemplate (Java 5 için)



JdbcTemlate Kullanımı


JdbcTemplate bean tanımını şu şekilde yazılır:


<bean id="jdbcTemplate"

class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource">

<ref local="dataSource" />

</property>

</bean>


dataSource tanımlama ve Spring’in veri erişim katmanı için sunduğu desteğe şu blog girdisinde bahsetmiştik. Dao sınıfımız da JdbcDaoSupport sınıfını kalıtmalıdır:


public class OgrenciDaoImpl extends JdbcDaoSupport

implements OgrenciDao{

...

}




Dao sınıfımıza bağımlılık aktarımı ile jdbcTemplate bağlayalım:


<bean id="ogrenciDao" class="dao.OgrenciDao">

<property name="jdbcTemplate" ref="jdbcTemplate" />

</bean>



Veri Tabanına JdbcTemlate ile Kayıt Ekleme:


private static final String OGRENCI_INSERT =

"insert into ogrenci (id, ad, soyad) " +

"values (?,?,?)";


public void saveOgrenci(Ogrenci ogrenci) {

getJdbcTemplate().update(OGRENCI_INSERT,

new Object[] { ogrenci.getId(), ogrenci.getAd(),

ogrenci.getSoyad() });

}



Veri Tabanından JdbcTemlate ile Kayıt Sorgulama


private static final String OGRENCI_SELECT =

"select id, ad, soyad from ogrenci";


private static final String OGRENCI_BY_ID_SELECT =

OGRENCI_SELECT + " where id=?";


public Ogrenci getOgrenciById(long id) {

List matches = getJdbcTemplate().query(OGRENCI_BY_ID_SELECT,

new Object[] { Long.valueOf(id) },

new RowMapper() {

public Object mapRow(ResultSet rs, int rowNum)

throws SQLException, DataAccessException {

Ogrenci ogrenci = new Ogrenci();

ogrenci.setId(rs.getInt(1));

ogrenci.setAd(rs.getString(2));

ogrenci.setSoyad(rs.getString(3));

return ogrenci;

}

});

return matches.size() > 0 ? (Ogrenci) matches.get(0) : null;

}



Burada sorgudan dönen her sıra için JdbcTemplate, RowMapper sınıfının mapRow() yöntemini işletecektir.



NamedParameterJdbcTemplate Kullanımı


NamedParameterJdbcTemplate için yapılması gereken bean tanımları ve örnekler şu şekildedir:


<bean id="jdbcTemplate"

class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">

<property name="dataSource">

<ref local="dataSource" />

</property>

</bean>



public class OgrenciDaoImpl extends NamedParameterJdbcDaoSupport

implements OgrenciDao{

...



private static final String OGRENCI_INSERT =

"insert into ogrenci (id, ad, soyad) " +

"values (:id, :ad, :soyad)";




public void saveOgrenci(Ogrenci ogrenci) {

Map parameters = new HashMap();

parameters.put("id", ogrenci.getId());

parameters.put("password", ogrenci.getAd());

parameters.put("firstName", ogrenci.getSoyad());

getNamedParameterJdbcTemplate().update(OGRENCI_INSERT, parameters);

}


...


}


SimpleJdbcTemplate Kullanımı


Java 5’in getirdiği autoboxing, değişken sayıda parametre geçebilme gibi yenilikleri kullanan SimpleJdbcTemplate için yapılması gereken bean tanımları ve örnekler şu şekildedir:


<bean id="jdbcTemplate"

class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">

<property name="dataSource" ref="dataSource" />

</bean>



public class OgrenciDaoImpl extends SimpleJdbcDaoSupport

implements OgrenciDao{

...


public void saveOgrenci(Ogrenci ogrenci) {

getSimpleJdbcTemplate().update(OGRENCI_INSERT,

ogrenci.getId(), ogrenci.getAd(),

ogrenci.getSoyad());

}



public Ogrenci getOgrenciById(long id) {

List<Ogrenci> matches = getSimpleJdbcTemplate().query(

OGRENCI_BY_ID_SELECT,

new ParameterizedRowMapper<Ogrenci>() {

public Ogrenci mapRow(ResultSet rs, int rowNum)

throws SQLException {

Ogrenci ogrenci = new Ogrenci();

ogrenci.setId(rs.getInt(1));

ogrenci.setAd(rs.getString(2));

ogrenci.setSoyad(rs.getString(3));

return ogrenci;

}

},

id

);

return matches.size() > 0 ? matches.get(0) : null;

}


...

}