8. Sürüm 4 – web hizmeti mimarisinde istemci/sunucu
Bu yeni sürümde, [Pam] uygulaması bir web hizmeti mimarisinde istemci/sunucu modunda çalışacaktır. Önceki uygulamanın mimarisine tekrar göz atalım:
![]() |
Yukarıda, bir [C, RMI, S] iletişim katmanı, [ui] istemcisi ile uzak [metier] katmanı arasında şeffaf bir iletişim sağlıyordu. Benzer bir mimari kullanacağız; burada [C, RMI, S] iletişim katmanı, [C, HTTP / SOAP, S] katmanıyla değiştirilecektir:
![]() |
HTTP / SOAP protokolü, önceki RMI / EJB protokolüne kıyasla çoklu platform desteği sunması açısından avantajlıdır. Böylece web hizmeti Java ile yazılabilir ve Glassfish sunucusunda çalıştırılabilirken, istemci ise bir .NET veya PHP istemcisi olabilir.
Bu mimariyi üç farklı modda geliştireceğiz:
- web hizmeti EJB ve [Metier] tarafından sağlanacak
- web hizmeti, EJB ve [Metier]'i kullanan bir web uygulaması tarafından sağlanacaktır
- web hizmeti, Spring kullanan bir web uygulaması tarafından sağlanacaktır
Bir web hizmeti, EE adlı bir Java sunucusu içinde çeşitli şekillerde uygulanabilir:
- bir web kapsayıcısında çalışan @WebService ile işaretlenmiş bir sınıf aracılığıyla
![]() |
- EJB etiketli ve bir EJB konteynerinde çalışan bir WebService
![]() |
Bu son mimariyle başlayalım.
8.1. EJB tarafından uygulanan web hizmeti
8.1.1. Sunucu tarafı
8.1.1.1. NetBeans projesi
Öncelikle, EJB ve [mv-pam-ejb-metier-dao-jpa-eclipselink] projelerinin bir kopyası olan yeni bir Maven projesi oluşturalım:
![]() |
Aşağıdaki mimariye göre:
![]() |
[metier] katmanı, [ui] katmanı tarafından çağrılan web hizmeti olacaktır. Bu sınıfın bir arayüzü uygulaması gerekmez. POJO'i (Plain Ordinary Java Object) bir web hizmetine dönüştüren şey, anotasyonlardır. Yukarıdaki [metier] katmanını uygulayan [Metier] sınıfı, şu şekilde dönüştürülür:
package metier;
...
@WebService
@Stateless()
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Metier implements IMetierLocal,IMetierRemote {
// katmanlara ilişkin referanslar [DAO]
@EJB
private ICotisationDaoLocal cotisationDao = null;
@EJB
private IEmployeDaoLocal employeDao=null;
@EJB
private IIndemniteDaoLocal indemniteDao=null;
// maaş bordrosunu alma
@WebMethod
public FeuilleSalaire calculerFeuilleSalaire(String SS,
...
}
// çalışan listesi
@WebMethod
public List<Employe> findAllEmployes() {
...
}
// önemli - EJB için getter ve setter yok
}
- 4. satırda, @WebService anotasyonu, [Metier] sınıfını bir web hizmeti haline getirir. Bir web hizmeti, müşterilerine yöntemler sunar. Bu yöntemler, @WebMethod özniteliği ile anotasyonlanmalıdır.
- 19. ve 25. satırlar: [Metier] sınıfındaki iki yöntem, web hizmetinin yöntemleri haline gelir.
- 29. satır: Get ve set yöntemlerinin kaldırılması önemlidir; aksi takdirde web hizmetinde açığa çıkarlar ve bu da güvenlik hatalarına neden olur.
Bu açıklamaların eklenmesi NetBeans tarafından algılanır ve NetBeans, projenin yapısını şu şekilde değiştirir:
![]() |
[1]'te, projede [Web Services] adlı bir dizin yapısı ortaya çıkmıştır. Burada Metier web hizmeti ve bu hizmetin iki yöntemi bulunur. Sunucu uygulaması [2] olarak dağıtılabilir. MySQL sunucusunun başlatılması ve [dbpam_eclipselink] veritabanının mevcut ve doldurulmuş olması gerekir. Ad çakışmalarını önlemek için, önceden incelenen istemci/sunucu projesi EJB'ten [3] ve EJB'i silmek gerekebilir. Zira yeni projemiz, önceki projedekilerle aynı EJB öğelerini beraberinde getiriyor.
![]() |
[1]'te, Glassfish sunucusuna dağıtılmış serveur uygulamamızı görüyoruz. Web hizmeti dağıtıldıktan sonra test edilebilir:
![]() |
- [1]'te, mevcut projede [Metier] web hizmetini test ediyoruz
- web hizmetine farklı URL adresleri üzerinden erişilebilir. URL ve [2], web hizmetini
- [3]'te, web hizmetini tanımlayan XML dosyasına bir bağlantı bulunmaktadır. Web hizmetinin istemcileri, bu dosyanın URL değerini bilmelidir. Web hizmetinin istemci katmanı (stub'lar), bu değerden yola çıkılarak oluşturulur.
- [4,5] dosyasında, web hizmeti tarafından sunulan yöntemleri test etmeye yarayan bir form bulunur. Bu yöntemler, kullanıcının tanımlayabileceği parametreleriyle birlikte sunulur.
Örneğin, herhangi bir parametre gerektirmeyen [findAllEmployes] yöntemini test edelim:
![]() |
Yukarıda, yöntemi test ediyoruz. Ardından aşağıdaki yanıtı alıyoruz (kısmi görünüm). Burada, iki çalışanı da ödenekleriyle birlikte görebiliyoruz. Okuyucunun, [4] yöntemini de aynı şekilde, beklenen üç parametreyi ileterek test etmesi önerilir.

8.1.2. İstemci tarafı
![]() |
8.1.2.1. Müşterinin NetBeans projesi konsol
Şimdi, uygulamanın client kısmı için [Java Application] türünde bir Java projesi oluşturuyoruz. Haziran 2012 itibarıyla bu istemci için bir Maven projesi oluşturmak mümkün olmadı. Bir hata ortaya çıkıyor; bu hata internette biliniyor gibi görünüyor ancak henüz çözülmemiş durumda.
![]() | ![]() |
Proje oluşturulduktan sonra, projenin Glassfish sunucusuna az önce dağıttığımız web hizmetinin istemcisi olacağını belirtiyoruz:
![]() |
- [2]'te yeni projeyi seçip [New File]
- [3]'te, bir web hizmeti istemcisi oluşturmak istediğimizi belirtiriz
![]() |
- ile bir web hizmeti istemcisi oluşturmak istediğimizi belirtiriz
- [5] penceresinde, [Web Services] dalına sahip tüm projeler listelenir; burada sadece [mv-pam-ws-metier-dao-eclipselink] projesi vardır.
- Bir proje birden fazla web hizmeti dağıtabilir. [6]'te, bağlanmak istediğimiz web hizmetini seçiyoruz.
![]() |
- [7]'te, web hizmetinin tanımını içeren URL görüntülenir. Bu URL, web hizmetiyle arayüz oluşturacak istemci katmanını üreten yazılım araçları tarafından kullanılır.
![]() |
- Oluşturulacak [C] ve [1] istemci katmanı, aynı pakete yerleştirilecek bir dizi Java sınıfından oluşur. Bu paketin adı [8] olarak belirlenir.
- Web hizmeti istemcisi oluşturma sihirbazı [Finish] düğmesiyle tamamlandığında, yukarıdaki [C] katmanı oluşturulur.
Bu durum, projede bir dizi değişiklikle yansıtılır:
- Yukarıdaki [10]'te, [Generated Sources] adlı bir ağaç yapısı görünmektedir; bu yapı, [C] katmanındaki sınıfları içerir ve bu sınıflar, [3] istemcisinin web hizmeti ile iletişim kurmasını sağlar. Bu katman, [3] istemcisinin [metier] ve [4] katmanlarıyla, sanki bunlar uzak değil de yerelmiş gibi iletişim kurmasını sağlar.
- [11]'te, bir istemci katmanının oluşturulduğu web hizmetlerini listeleyen bir [Web Service References] ağaç yapısı görünür.
Oluşturulan [C] [10] katmanında, sunucu tarafında dağıtılmış sınıfların bulunduğuna dikkat edilmelidir: Indemnite, Cotisation, Employe, FeuilleSalaire, ElementsSalaire, Metier. Metier, web hizmetidir ve diğer sınıflar bu hizmet için gerekli olan sınıflardır. Merak edip kodlarına bakabiliriz. Örneklendirildiğinde hizmet tarafından işlenen nesneleri temsil eden sınıfların tanımının, sınıf alanlarının ve erişim yöntemlerinin tanımlanmasından ve sınıfın XML akışında serileştirilmesini sağlayan anotasyonların eklenmesinden oluştuğunu göreceğiz. Metier sınıfı, içinde @WebMethod anotasyonuyla işaretlenmiş iki yöntem barındıran bir arayüz haline gelmiştir. Bu yöntemlerin her biri, örneğin [CalculerFeuilleSalaire.java] ve [CalculerFeuilleSalaireResponse.java] gibi iki sınıf oluşturur; bunlardan biri yöntem çağrısını, diğeri ise sonucunu kapsüller. Son olarak, MetierService sınıfı, istemcinin uzak Metier web hizmetine erişmesini sağlayan sınıftır:
- satırdaki getMetierPort yöntemi, uzak Metier web hizmetine bir referans elde etmeyi sağlar.
8.1.2.2. Metier web hizmetinin konsol istemcisi
Geriye sadece Metier web hizmetinin istemcisini yazmak kaldı. [mv-pam-client-metier-dao-jpa-eclipselink] projesinden, EJB sunucusunun istemcisi olan [MainRemote] sınıfını yeni projeye kopyalıyoruz.
![]() |
- adını, web hizmeti istemcisi sınıfı olan [1] olarak değiştiriyoruz. [MainRemote] sınıfında hatalar var. Bunları düzeltmek için, önce sınıfta bulunan tüm [import] komutlarını sileceğiz ve [Fix Imports] seçeneği ile yeniden oluşturacağız. Zira, [MainRemote] sınıfı tarafından kullanılan bazı sınıflar artık oluşturulan [client] paketinin bir parçasıdır.
- [3]'te, [metier] katmanının örneklendiği kod parçası [3]'tir. Bu, uzak bir EJB'e referans elde etmek için JNDI koduyla gerçekleştirilir.
Kodu şu şekilde değiştiriyoruz:
- JNDI kodu silinir
- [PamException] sınıfı istemci tarafında mevcut olmadığından, ilişkili catch'i siliyoruz ve ana sınıf [Exception] üzerinde yalnızca catch'i tutuyoruz.
![]() |
- [4]'te, [Metier] uzak web hizmetinden bir referans almamız gerekiyor; böylece bu hizmetin [calculerFeuilleSalaire] yöntemini çağırabileceğiz.
- [5]'te, fareyi kullanarak [Metier] web hizmetinden [calculerFeuilleSalaire] yöntemini sürükleyip (drag) [4]'e bırakıyoruz (drop). [6] kodu oluşturulur. Bu genel kod daha sonra geliştirici tarafından uyarlanabilir.
![]() |
- 112. satırda, [calculerFeuilleSalaire]'in [client.Metier] sınıfının (111. satır) bir yöntemi olduğu görülmektedir. Artık [metier] katmanını nasıl elde edeceğimizi bildiğimize göre, önceki kod şu şekilde yeniden yazılabilir:
- satırda Metier web hizmetine bir referans alınır. Bu işlem tamamlandıktan sonra sınıfın kodu değişmez; ancak 10. satırda, [Exception] türündeki istisna değil, daha genel olan Throwable türü işlenir; Exception sınıfının üst sınıfıdır. Bir istisna oluşursa, bunun iç içe geçmiş tüm nedenlerini, asıl nedenine kadar görüntüleriz.
Testlere hazırız:
- SGBD ve MySQL5'in başlatıldığından, dbpam_eclipselink veritabanının oluşturulup başlatıldığından emin olun
- web hizmetinin Glassfish sunucusuna dağıtıldığından emin olun
- istemciyi derlemek (Clean and Build)
- istemcinin çalışmasını yapılandırmak
![]() |
- İstemciyi çalıştırın
Konsoldaki sonuçlar şöyledir:
Aşağıdaki yapılandırma ile:

şu sonuçlar elde edilir:
[Metier] web hizmeti, [PamException] türünde bir istisna gönderirken, istemci tarafından alınan istisna [SOAPFaultException] türündedir. Hata zincirinde bile [PamException] türü görünmemektedir.
8.1.3. Metier web hizmetinin Swing istemcisi
Yapılması gereken iş: [mv-pam-client-ejb-metier-dao-jpa-eclipselink] projesinin Swing istemcisini yeni projeye taşımak, böylece onun da Glassfish sunucusunda dağıtılmış web hizmetinin istemcisi olmasını sağlamak.
8.2. Bir web uygulaması tarafından uygulanan web hizmeti
Şimdi şu mimari çerçevesine geçiyoruz:
![]() |
Web hizmeti, Glassfish sunucusunun web konteyneri içinde çalıştırılan bir web uygulaması tarafından sağlanır. Bu web hizmeti, EJB3 konteynerinde dağıtılmış olan EJB ve [Metier]'e dayanacaktır.
8.2.1. Sunucu tarafı
Bir web uygulaması oluşturuyoruz:
![]() |
- [1] içinde, [2] adında yeni bir proje oluşturuyoruz
- [2]'te, bu proje [Web Application] türündedir
- [3]'te, ona [mv-pam-ws-ejb-metier-dao-eclipselink] adını veriyoruz
![]() |
- [4]'te, Java sürümü olarak EE 6'yı seçiyoruz
- [6]'te, oluşturulan proje
Aşağıdaki şemada, oluşturulan web uygulaması web konteynerinde çalışacaktır. Uygulama, EJB ve [Metier]'i kullanacak ve bunlar da sunucunun EJB konteynerine dağıtılacaktır.
![]() |
Oluşturulan web uygulamasının EJB ve [Metier] ile ilişkili sınıflara erişebilmesi için, web uygulamasının kütüphanelerine [mv-pam-ws-ejb-metier-dao-eclipselink]'i ekliyoruz; daha önce incelediğimiz EJB ve [mv-pam-ejb-metier-dao-eclipselink] sunucu bağımlılıklarını ekliyoruz.
![]() |
- [1]'te, web projesinin bağımlılıklarına bir proje eklenir,
- [2]'te, [mv-pam-ejb-metier-dao-eclipselink] projesini seçiyoruz,
- [3]'te bağımlılık türü ejb'tir,
- [4]'te, bağımlılığın kapsamı provided'tir, yani bu bağımlılık çalışma ortamı tarafından sağlanacaktır,
- [5]'te bağımlılık eklenmiştir.
Daha önce oluşturduğumuz web hizmetinin aynısını oluşturmak için şunları yapmamız gerekir:
- @Webservice etiketli bir sınıf oluşturmak
- ve @WebMethod etiketli calculerFeuilleSalaire ve findAllEmployes adlı iki yöntem
[pam.ws] paketinde [PamWsEjbMetier] sınıfını oluşturuyoruz:
![]() |
![]() |
[PamWsEjbMetier] sınıfı şu şekildedir:
- 7-10. satırlar: Sınıf, Maven projesi proje bağımlılıklarına eklenmiş olan EJB ve [pam-serveurws-metier-dao-jpa-eclipselink] modüllerinden sınıfları içe aktarmaktadır.
- 12. satır: Sınıf bir web hizmetidir
- 13. satır: EJB modülünde tanımlanan IMetier arayüzünü uygular
- 18-19. satırlar: calculerFeuilleSalaire yöntemi, web hizmeti yöntemi olarak sunulur
- 23-24. satırlar: findAllEmployes yöntemi, web hizmetinin bir yöntemi olarak sunulur
- satır 15-16: EJB'in yerel arayüzü, [Metier], satır 16'daki alana eklenir. Web uygulaması ve EJB modülü aynı JVM içinde çalıştığı için yerel arayüzü kullanıyoruz.
- 20. ve 25. satırlar: calculerFeuilleSalaire ve findAllEmployes yöntemleri, işlemlerini EJB [Metier]'teki aynı isimli yöntemlere devrediyor. Dolayısıyla bu sınıf, yalnızca EJB ve [Metier] sınıflarındaki yöntemleri uzak istemcilere bir web hizmeti yöntemi olarak sunmak amacıyla kullanılır.
NetBeans'te, web uygulaması bir web hizmeti sunan uygulama olarak tanınır:
![]() |
Web hizmetini Glassfish sunucusuna dağıtmak için hem:
- web modülünü sunucunun web kapsayıcısına
- EJB modülünü sunucunun EJB konteynerine
Bunun için, her iki modülü aynı anda dağıtacak [Enterprise Application] türünde bir uygulama oluşturmamız gerekiyor. Bunu yapmak için, her iki projenin de NetBeans'e yüklenmesi gerekiyor: [2].
Bu işlem tamamlandıktan sonra, yeni bir [3] projesi oluşturuyoruz.
![]() |
- [4]'te, [Enterprise Application] türünde bir proje seçiyoruz.
- [5]'te projeye bir ad veriyoruz
![]() |
- [6]'te projeyi yapılandırıyoruz. Java sürümü EE, Java EE 6 olacaktır. Bir kurumsal proje, bir EJB modülü ve bir Web modülü olmak üzere iki modülle oluşturulabilir. Burada, kurumsal proje, daha önce oluşturulmuş ve NetBeans'e yüklenmiş olan Web modülünü ve EJB modülünü kapsayacaktır. Dolayısıyla yeni modüllerin oluşturulmasını talep etmiyoruz.
- [7]'te, bu şekilde oluşturulan [mv-pam-webapp-ear] kurumsal projesi. Aynı zamanda [mv-pam-webapp] adlı başka bir Maven projesi de oluşturulmuştur. Bununla ilgilenmeyeceğiz.
- [8] dosyasında, kurumsal projeye bağımlılıklar ekliyoruz
![]() |
- [9]'te, war türünde bir web projesi ekliyoruz,
- [10]'te, ejb türündeki EJB projesini ekliyoruz,
![]() |
- [11] dosyasına, iki bağımlılığıyla birlikte kurumsal proje eklenir.
"Clean and Build" komutuyla kurumsal projeyi derliyoruz. Glassfish sunucusuna dağıtmaya neredeyse hazırız. Öncesinde, olası isim çakışmalarını önlemek için sunucuya önceden yüklenmiş uygulamaları kaldırmak gerekebilir: EJB [11]:
![]() |
MySQL sunucusu çalıştırılmalı ve [dbpam_eclipselink] veritabanı kullanılabilir durumda ve doldurulmuş olmalıdır. Bu işlem tamamlandıktan sonra, kurumsal uygulama [12] olarak dağıtılabilir. [13]'te, uygulamanın Glassfish sunucusuna başarıyla dağıtıldığı görülebilir.
Az önce devreye alınan web hizmetini test edebiliriz:
![]() |
- [1] adresinde, [PamWsEjbMetier]
- [2]'e, yani test sayfasına yönlendirilmesini talep ediyoruz. Testleri gerçekleştirme görevini okuyucuya bırakıyoruz.
8.2.2. İstemci tarafı
Yapılması gereken iş: 8.1.2.1 numaralı paragrafta açıklanan adımları izleyerek, önceki web hizmetinin bir konsol istemcisi oluşturun.
8.3. Spring ve Tomcat ile uygulanan web hizmeti
Şimdi şu mimari çerçevesine geçiyoruz:
![]() |
Web hizmeti, Tomcat sunucusunun web konteyneri içinde çalıştırılan bir web uygulaması tarafından sağlanmaktadır. Uygulamanın mimarisi şu şekilde olacaktır:
![]() |
5.11. paragrafta oluşturulan [mv-pam-spring-hibernate] projesini temel alacağız:
![]() |
8.3.1. Sunucu kısmı
[mv-pam-ws-spring-tomcat] [1] adlı bir web türü Maven uygulaması oluşturuyoruz:
![]() |
[pom.xml] dosyasını, aşağıdaki [2] bağımlılıklarını içerecek şekilde değiştiriyoruz:
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mv-pam-spring-hibernate</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Apache CXF bağımlılıkları -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.12</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.12</version>
</dependency>
</dependencies>
- 3-7. satırlar: [spring-pam-jpa-hibernate] projesine olan bağımlılık,
- 8-17. satırlar: Apache CXF ve [http://cxf.apache.org/] çerçevelerine olan bağımlılıklar. Bu çerçeve, web hizmetlerinin oluşturulmasını kolaylaştırır.
Bu [pom.xml] dosyası, çok sayıda [2] bağımlılığını beraberinde getirir.
Uygulamanın mimarisine geri dönelim:
![]() |
Oluşturacağımız web hizmeti çağrıları, CXF çerçevesinin bir servlet'i tarafından yönetilir. Bu, [WEB-INF / web.xml] dosyasında şu şekilde yansıtılır:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>mv-pam-ws-spring-tomcat</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CXF yapılandırması -->
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
- CXF çerçeve, Spring'e bağımlıdır. 4-6. satırlar: bir dinleyici tanımlanmıştır. İlgili sınıf, web uygulamasıyla birlikte yüklenecektir. Bu sınıf, Spring yapılandırma dosyası [WEB-INF / applicationContext.xml]'i kullanacaktır:
![]() |
- 8-12. satırlar: Oluşturacağımız web hizmetine yapılan çağrıları yönetecek olan CXF servleti,
- 13-16. satırlar: CXF servleti tarafından işlenen URL'ler /ws/* türünde olacaktır. Diğerleri CXF tarafından işlenmeyecektir.
Web hizmetini tanımlamak için bir arayüz ve bunun uygulamasını tanımlıyoruz:
![]() |
[IWsMetier] arayüzü şu şekilde olacaktır:
package pam.ws;
import javax.jws.WebService;
import metier.IMetier;
@WebService
public interface IWsMetier extends IMetier{
}
- 7. satır: [IWsMetier] arayüzü, [mv-pam-spring-hibernate] projesinin [métier] katmanındaki [IMetier] arayüzünden türetilmiştir,
- 6. satır: [IWsMetier] arayüzü bir web hizmetine aittir.
Bu arayüzün uygulama sınıfı şöyledir:
package pam.ws;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
@WebService
public class PamWsMetier implements IWsMetier {
// iş mantığı katmanı
private IMetier metier;
// oluşturucu
public PamWsMetier(){
}
@WebMethod
public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillees, int nbJoursTravailles) {
return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillees, nbJoursTravailles);
}
@WebMethod
public List<Employe> findAllEmployes() {
return metier.findAllEmployes();
}
// alıcı ve ayarlayıcılar
public void setMetier(IMetier metier) {
this.metier = metier;
}
}
- 11. satır: [PamWsMetier] sınıfı, daha önce tanımlanan arayüzü uygular,
- 10. satır: Sınıfı bir web hizmeti olarak tanımlar,
- 14. satır: [métier] katmanı Spring tarafından enjekte edilecektir,
- 21. ve 26. satırlar: @WebMethod anotasyonu, bir yöntemi web hizmeti tarafından sunulan bir yöntem haline getirir,
- 23. ve 28. satırlar: Yöntemler, [métier] katmanı kullanılarak uygulanır.
Geriye Spring [applicationContext.xml] yapılandırma dosyasının içeriğini tanımlamak kalıyor:
![]() |
İçeriği şu şekildedir:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- Apache CXF -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- alt katmanlar -->
<import resource="classpath:spring-config-metier-dao.xml" />
<!-- web hizmeti -->
<bean id="wsMetier" class="pam.ws.PamWsMetier">
<property name="metier" ref="metier"/>
</bean>
<jaxws:endpoint id="wsmetier"
implementor="#wsMetier"
address="/metier">
</jaxws:endpoint>
</beans>
- 13-15. satırlar: Apache yapılandırma dosyaları CXF içe aktarılır. Bu dosyalar, projenin Classpath dosyasında aranır (classpath özniteliği:),
- 4., 9. ve 10. satırlar: Apache CXF'e özgü ad alanları tanımlanıyor,
- 18. satır: [mv-pam-spring-hibernate] projesinin Spring yapılandırma dosyası içe aktarılır,
- 21-23. satırlar: [métier] katmanına bağımlılığıyla birlikte web hizmeti bean'i tanımlanır (22. satır),
- 24-27. satırlar: web hizmetinin kendisi tanımlanıyor,
- 25. satır: Web hizmetini uygulayan Spring bean'i, 21. satırda tanımlanan bean'dir;
- satır 26: web hizmetinin erişilebilir olacağı URL'i tanımlar; burada /metier. Apache CXF tarafından işlenen URL'lerin alması gereken biçimle birleştirildiğinde (bkz. web.xml dosyası), bu URL, /ws/metier olur.
Projemiz çalıştırılmaya hazırdır. Projeyi çalıştırıyoruz (Run) ve bir tarayıcıda URL [http://localhost:8080/mv-pam-ws-spring-tomcat/ws] adresini giriyoruz:

Sayfa, dağıtılmış tüm web hizmetlerini listeler. Burada sadece bir tane var. WSDL bağlantısını takip ediyoruz:
![]() |
Görüntülenen [1] metni, web hizmetinin işlevlerini, nasıl çağrılacağını ve hangi yanıtları göndereceğini tanımlayan XML dosyasına aittir. Bu WSDL dosyasının URL ve [2] kısımlarına dikkat edin. Web hizmetinin tüm istemcileri bunu bilmelidir.
8.3.2. İstemci tarafı
Yapılması gereken iş: 8.1.2.1 numaralı paragrafta açıklanan adımları izleyerek, yukarıdaki web hizmetinin bir konsol istemcisi oluşturun.
Not: Web hizmetinin WSDL dosyasının URL değerini belirtmek için aşağıdaki şekilde ilerlenecektir:
![]() |
Daha önce [2] olarak not edilen URL değerini, [3] olarak gireceğiz.












































