Welcome

Spring Resource Konsepti

Bugüne kadar Java ile geliştirdiğimiz uygulamalarımızda mutlaka herhangi bir nedenle dosya sistemindeki bir kaynağa erişim ihtiyacımız olmuştur. Belki bir resim dosyasını ekranda göstermek, bir ses dosyasını çalmak, belki de uygulamanın ihtiyaç duydugu konfigürasyon parametrelerini bir property dosyasından yüklemek isteriz. Bu kaynaklar dosya sisteminde de bulunmayabilir, network üzerinden de erişim söz konusu olabilir.

Java’da bü tür kaynaklara erişim genelde ClassLoader sınıfının sağladığı findResource(s), getResource(s), getSystemResource(s) ve türevi metodlar yardımı ile olmaktadır. java.net.URL sınıfı da bu tür kaynakları ifade etmek için oluşturulmuştur. Ancak Java’nın sağladığı bu yapıların uygulama içerisinde kullanımında pek çok zorlukla karşılaşırız. Erişimde kullanacağımız ClassLoader’ı genelde o anda içinde bulunduğumuz nesnenin ait olduğu sınıfın getClassLoader() metodu ile elde edip, yukarıdaki metodları çağırabiliriz. Bu basit standalone uygulamalar için genelde bir sorun teşkil etmesede, web uygulamaları gibi birden fazla “classloader”ın yer aldığı classloader hiyerarşilerinde ciddi sorun olmaktadır. Sık sık yüklemek istediğimiz kaynağın classpath’de bulunamadığı hatası ile karşılaşırız. Kaynağın relatif veya absolute path ile belirtilip belirtilmemesi de uygulamanın geliştirme ortamında çalışırken, test veya üretim ortamlarında çalışmaması ile sonuçlanabilmektedir. Çoğu zaman, “bir de başına / koyarak yüklemeyi dene bakalım ne olacak…” şeklinde arkadaş tavsiyelerini sık sık duyarız. Birim testlerimizi yazarken kullandığımız path ile, uygulama deploy edildiğinde – genelde de web uygulamalarında – kullanmamız gereken path farklı farklı olduğundan bu durumları dikkate alacak biçimde test kodumuzu dallandırmamız, kaynağın dosya sisteminde veya bir jar veya zip dosyası içerisinde bulunması durumuna göre farklı erişim yöntemleri kullanmamız gerekebilir. Bu kaynakları yüklerken kullanılacak path bilgisini birden fazla muhtemel yeri kapsayacak biçimde wildcard karakterler ile ifade etme şansımız malesef yoktur.

Spring Application Framework bu tür kaynak erişimlerini daha kolay ve problemsiz hale getirmek için org.springframework.core.io.Resource ve kaynakları yüklemek için de org.springframework.core.io.ResourceLoader arayüzlerini tanımlamıştır. Bu temel yapılar vasıtası ile yukarıda bahsedilen problemlerin pek çoğundan arındırılmış biçimde yazılım geliştirme yapmak, kaynakları çok daha kolay ve etkin biçimde ilgili ortamlarında bulup yüklemek mümkün olmaktadır.

Şimdi Spring’in sağladığı bu yapılara, kaynak tanımlama ve yükleme örneklerine biraz daha yakından bakalım. Resource arayüzü aşağıdaki gibi ilgili kaynağın File, URL gibi görünümlerine erişimi sağlayan, kaynağın gerçekten fiziksel ortamda olup olmadığını kontrol etmeyi sağlayan, bu kaynağa relatif bir lokasyonda yeni bir Resource nesnesi oluşturmaya yarayan metodlara sahiptir.

public interface Resource extends InputStreamSource {
    boolean exists(); 
    boolean isOpen();
    URL getURL() throws IOException; 
    File getFile() throws IOException;
    Resource createRelative(String relativePath) throws IOException; 
    String getFilename();
    String getDescription();
}

Dosya sistemi, URL, classpath, servlet context gibi ortamın türüne göre farklı kaynak türleri bu Resource arayüzünden türetilmiştir. ClasspathResource, FileSystemResource, URLResource, ServletContextResource bu kaynak tiplerinden bazılarıdır.

Bu kaynakları yükleyen mekanizmalar da ResourceLoader arayüzünü implement ederler. Spring’deki bütün ApplicationContext nesneleri aynı zamanda birer ResourceLoader özelliğine sahiptir.

public interface ResourceLoader {
    Resource getResource(String location);
}

ClasspathApplicationContext, FileSystemApplicationContext, WebApplicationContext bunlardan bazılarıdır. Herbir ApplicationContext tipi de varsayılan durumlar için kendi türüne karşılık gelen bir Resource tipini oluşturup kullanıcıya döndürmektedir. Örneğin,

Resource propertiesResource = applicationContext.getResource("some/path/to/file/cfg.properties");

ile bir Resource’a erişmek istediğimizde, applicationContext nesnesi eğer bir ClassPathApplicationContext ise, cfg.properties dosyası uygulamanın classpath’inde aranacaktır. Eğer context FileSystemApplicationContext tipinde ise, bu sefer dosya uygulamanın hali hazırda çalıştığı dizinde aranacaktır. Şayet context bir WebApplicationContext ise, bu sefer de dosya web uygulamasının context root dizininde aranacaktır. Bu örnekten de anlaşılacağı gibi uygulama geliştirme aşamasında ve uygulama deploy edildikten sonra aynı kaynağa erişim için farklı erişim yöntemleri izleme zorunluluğu ortadan kalkmaktadır.

Spring, yüklenecek Resource nesnesinin tipini belirterek ApplicationContext nesnesinin tipi ne olursa olsun bu tipte bir Resource oluşturma imkanı da sunmaktadır. Örneğin;

applicationContext.getResource("classpath:/some/path/to/file/cfg.properties");

ile WebApplicationContext kullanılsa bile, yüklenecek kaynak, uygulamanın classpath’inde aranır ve ClassPathResource tipinde oluşturulur. Spring’in resource tiplerine örnekler şöyle sıralanabilir;

file:/some/path/to/file/cfg.properties -->  Kaynak dosya sisteminde aranır, UrlResource olarak yüklenir.
http://10.0.0.1/myapp/cfg.properties -->  Kaynak UrlReource olarak network'den yüklenir.
classpath:/some/path/to/file/cfg.properties -->  Kaynak uygulamanın classpath'inde aranır, ClassPathApplicationContext olarak yüklenir.

Spring’in sağladığı diğer bir kolaylık da Ant sitilinde patternlar vasıtası ile yüklenecek kaynakların belirtilebilmesidir. Örneğin,

Resources[] resources = applicationContext.getResource("classpath:/some/path/**/*.properties");

ile classpath’in some/path ile başlayan değişik lokasyonlarındaki, uzantısı properties olan dosyalara erişmek mümkün olmaktadır.

Eğer spring-managed bean’larınızın resource yükleme ihtiyaçları olursa, kullanılabilecek değişik yöntemler mevcuttur. Eğer yüklenecek kaynağın path bilgisi dinamik olarak spring-managed bean içerisinde tespit ediliyor ise org.springframework.core.io.ResourceLoaderAware arayüzünün spring-managed bean tarafından implement edilmesi yeterli olacaktır.

public interface ResourceLoaderAware {
      void setResourceLoader(ResourceLoader resourceLoader);
}

Spring ApplicationContext, bean oluşturulurken kendisini ilgili bean’a ResourceLoader olarak enjekte eder. Daha sonra bean içerisinde bu ResourceLoader nesnesi kullanılarak istenen kaynak yüklenebilir.

Eğer yüklenecek kaynakların lokasyonu statik olarak önceden belirlenebiliyor ise ResourceLoaderAware arayüzünü implement etmeye gerek yoktur. ApplicationContext konfigürasyon dosyasında bean tanımlanırken lokasyon bilgisi belirtilir. Spring otomatik olarak, tanımlı PropertyEditor’leri vasıtası ile kaynağı yükleyip bean’a enjekte eder.

<bean id="myBean" class="com.ksevindik.beans.MyBean">
    <property name="resources" value="classpath:/some/path/**/*.properties"/>
</bean>

Sonuç olarak, Spring Application Framework’ün sağladığı bu soyutmalar ve kaynaklara erişim mekanizmaları, Java ile uygulama geliştirme sırasında karşılaşılan problemlerinin tamamını olmasa da, pek çoğunu standard Java’nın sağlayabildiğinden daha sistematik ve tutarlı arayüzler vasıtası ile çok daha esnek biçimde çözebilmektedir.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

This site uses Akismet to reduce spam. Learn how your comment data is processed.