Bir önceki girdide Spring Web Service kullanarak anlaşma-önce web service geliştirme yaklaşımından ve bu yaklaşımının artılarından bahsetmiştik. WSDL belgesinin değişmesinin istemci ve sunucu kodlarını etkileyeceği için önce WSDL belgesinin oluşturulması gerektiğine değinmiştik. Bunun yanında anlaşma-önce yaklaşımın kullanılması geliştiriciyi Web Service geliştiriminin ayrıntılarından uzak tutacağı için küçük çaplı projelerde avantaj sağlayabilir. Bu girdide de Apache CXF kullanarak anlaşma-önce yaklaşımla basit bir web service geliştireceğiz.
Apache CXF’nin kullanacağı kütüphaneleri indirdikten sonra projemiz için gerekli olanları .zip kütüğünün lib dizininde yer alan WHICH_JARS kütüğünde bulabilirsiniz. Temel kullanım için gerekli olan kütüphanelerin listesi şu şekildedir:
- cxf.jar
- commons-logging.jar
- geronimo-activation.jar (Or the Sun equivalent) *
- geronimo-annotation.jar (Or the Sun equivalent) *
- geronimo-javamail.jar (Or the Sun equivalent) *
- geronimo-stax-api.jar (Or the Sun equivalent) *
- neethi.jar
- jaxb-api.jar *
- jaxb-impl.jar
- stax-utils.jar
- XmlSchema.jar
- wstx-asl.jar *
- wsdl4j.jar
- xml-resolver.jar
* Bu kütüphaneler Java 6 Update 4’den sonra JDK içinde mevcuttur.
Ayrıca Java sınıflarımızda Annotation kullanacağımız için Aegis ve JAX-WS kütüphalerine de ihtiyacımız var:
- jaxen.jar
- jdom.jar
- stax-utils.jar
- geronimo-ws-metadata.jar [6]
- jaxws-api.jar [6]
- saaj-api.jar [6]
- saaj-impl.jar [6]
- asm.jar
Örnek servis olarak kişi listesi döndüren bir servis yazalım:
package com.blogspot.mdasgin.examples.model;
import org.apache.cxf.aegis.type.java5.IgnoreProperty;
public class Kisi {
private String isim;
private String soyisim;
private Integer kimlikNo;
public Kisi() {
}
public Kisi(String isim, String soyisim, Integer kimlikNo) {
this.isim = isim;
this.soyisim = soyisim;
this.kimlikNo = kimlikNo;
}
public String getIsim() {
return isim;
}
public void setIsim(String isim) {
this.isim = isim;
}
public String getSoyisim() {
return soyisim;
}
public void setSoyisim(String soyisim) {
this.soyisim = soyisim;
}
/*
* @IgnoreProperty tells Aegis that I don't want getTamIsim() to show up in the auto-generated WSDL.
* It's just a read-only convenience method.
*/
@IgnoreProperty
public String getTamIsim() {
return soyisim + ", " + isim;
}
public Integer getKimlikNo() {
return kimlikNo;
}
public void setTamIsim(Integer kimlikNo) {
this.kimlikNo = kimlikNo;
}
}
@IgnoreProperty annotation’ı sayesinde Aegis, otomatik üretilen WSDL belgesinde bu niteliği göz ardı edecek. Web service arayüzü ve geliştirimi de şu şekilde olacaktır:
package com.blogspot.mdasgin.examples.contractlast.services;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.blogspot.mdasgin.examples.model.Kisi;
/*
* @WebService annotation bu arayuzun bir web service arayuzu oldugunu belirtir.
*/
@WebService
public interface KisiService {
List<Kisi> getKisiList();
/*
* @WebParam annotation allows us to use an HTTP parameter called "message" to reference the operation's argument
* instead of having to call it "arg0", which is the default.
*/
void addKisi(@WebParam(name = "kisi")Kisi kisi);
}
---
package com.blogspot.mdasgin.examples.contractlast.services.impl;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.blogspot.mdasgin.examples.contractlast.services.KisiService;
import com.blogspot.mdasgin.examples.model.Kisi;
/*
* @WebService annotation bu sinifi bir web service geliştirimi olarak isaretler. Ayrica kullandigi arayuzu de belirtir.
*/
@WebService(endpointInterface="com.blogspot.mdasgin.examples.contractlast.services.KisiService")
public class KisiServiceImpl implements KisiService {
public List<Kisi> getKisiList() {
List<Kisi> kisiList = new ArrayList<Kisi>();
kisiList.add(new Kisi("Mustafa", "Dasgin", "11111111111"));
kisiList.add(new Kisi("Huzur", "Oncu", "22222222222"));
return kisiList;
}
public void addKisi(Kisi kisi) {
System.out.println(kisi.getTamIsim());
}
}
Bu aşamadan sonra web.xml’de gelen web service istemlerinin yönlendirilebilmesi için gerekli tanımları eklemeliyiz:
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>
Tanımdan da anlaşılacağı gibi sunucumuza “/webservices/*” örüntüsünde gelen istemler CXFServlet’e yönlendirilecektir. Spring bean tanımlarımızı da yapalım:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<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" />
<!-- CXF'nin loglama ozelligi kullanilabilir fakat performans soz konusu ise kullanilmamasi onerilir.
-->
<cxf:bus>
<cxf:features>
<cxf:logging />
</cxf:features>
</cxf:bus>
<!-- The service bean -->
<bean id="kisiService"
class="com.blogspot.mdasgin.examples.contractlast.services.impl.KisiServiceImpl" />
<!-- Aegis data binding -->
<bean id="aegisBean"
class="org.apache.cxf.aegis.databinding.AegisDatabinding"
scope="prototype" />
<bean id="jaxws-and-aegis-service-factory"
class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"
scope="prototype">
<property name="dataBinding" ref="aegisBean" />
<property name="serviceConfigurations">
<list>
<bean
class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration" />
<bean
class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration" />
<bean
class="org.apache.cxf.service.factory.DefaultServiceConfiguration" />
</list>
</property>
</bean>
<!-- Service endpoint -->
<!-- See http://incubator.apache.org/cxf/faq.html regarding CXF + Spring AOP -->
<jaxws:endpoint id="kisiServiceEndPoint"
implementorClass="com.blogspot.mdasgin.examples.contractlast.services.impl.KisiServiceImpl"
implementor="#kisiService" address="/kisiws">
<jaxws:serviceFactory>
<ref bean="jaxws-and-aegis-service-factory" />
</jaxws:serviceFactory>
</jaxws:endpoint>
</bean>
Sunucu tarafımız hazır. Aşağıdaki istemlerle deneme yapabilirsiniz:
http://localhost:8080/denemeWSProje/webservices (Hizmet veren web servis listesi)
http://localhost:8080/denemeWSProje /webservices/kisiws?wsdl (Üretilen wsdl belgesi)
http://localhost:8080/denemeWSProje /webservices/kisiws/getKisiList
http://localhost:8080/denemeWSProje /webservices/kisiws/addKisi?kisi=...
Sunucuya bağlanacak istemci tarafında tanımlanması gereken spring bean’leri de şu şekilde olmalıdır (Sunucu tarafında tanımlanan aegisBean ve jaxws-and-aegis-service-factory beanleri de istemci tarafında tanımlanmalıdır):
<bean id="client"
class="com.blospot.mdasgin.examples.contractlast.services.KisiService"
factory-bean="clientFactory" factory-method="create" />
<bean id="clientFactory"
class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass"
value=" com.blogspot.mdasgin.contractlast.services.KisiService" />
<property name="address"
value="http://localhost:8080/denemeWSProje/webservices/kisiws" />
<property name="serviceFactory"
ref="jaxws-and-aegis-service-factory" />
</bean>
Kaynaklar:
http://wheelersoftware.com/articles/spring-cxf-web-services.html
http://wheelersoftware.com/articles/spring-cxf-consuming-web-services.html
Mustafa Bey bu harika yazınızı Ceviz.Net'te yayınlayabiir miyiz?
YanıtlaSilTabi ki. Kolay gelsin.
YanıtlaSilGerçekten çok sade anlatmışsınız teşekkur ederim. Çok faydalı oldu.
YanıtlaSil