Introduction
| Wiki Markup |
|---|
{link:SOAP|http://www.w3.org/TR/soap/}{link} |
은 분산분배 환경에서 구조적 데이터를 주고 받기 위한 lightweight protocol이다. Goovy는 SOAP서버나 SOAP서버로 부터 리모트 Call을 만들 수 있게 해주는
| Wiki Markup |
|---|
{link:Xfire |http://xfire.codehaus.org}{link} |
기반으로 SOAP을 구현했다.
Installation
| Excerpt |
|---|
| Wiki Markup |
|---|
$
{user.home}
/.groovy/lib안에 [이 jar |http://dist.codehaus.org/groovy/jars/groovysoap-all-jsr06-0.1.jar]파일을 다운로드 받아야 만한다. 이 jar 파일은 [groovy-1.0-JSR-06|http://dist.codehaus.org/groovy/distributions/groovy-1.0-jsr-06.zip]이 요구된다. |
|
Getting Started
The Server
Groovy class나 script를 사용해서 웹서비스를 개발할 수 있다. 두개의 groovy파일이 웹서비스를 작성한 것이다.
- MathService.groovy
| Code Block |
|---|
|
public class MathService {
double add(double arg0, double arg1) {
return (arg0 + arg1)
}
double square(double arg0) {
return (arg0 * arg0)
}
}
|
- Groovy어디서나 사용할 수 있다.
| Code Block |
|---|
|
double add(double arg0, double arg1) {
return (arg0 + arg1)
}
double square(double arg0) {
return (arg0 * arg0)
}
|
- 쉬운부분이라 코멘트를 필요없다.
| Code Block |
|---|
|
import groovy.net.soap.SoapServer
def server = new SoapServer("localhost", 6980)
server.setNode("MathService")
server.start()
|
That's all !
The Client
- Oh ... 두줄 정도면 테스트가 가능하다.
| Code Block |
|---|
|
import groovy.net.soap.SoapClient
def proxy = new SoapClient("http://localhost:6980/MathServiceInterface?wsdl")
def result = proxy.add(1.0, 2.0)
assert (result == 3.0)
result = proxy.square(3.0)
assert (result == 9.0)
|
- 더없다..끝이다!!
Custom Data Types
이 예제는 Groovy SOAP으로 사용자 정의 데이터 타잎을 어떻게 사용하는지를 보여준다. 이코드는 here에서 다운로드 받을 수 있다.
The Server
PersonService.groovy script는 서비스의 구현과 사용자 정의 데이터 타잎(Person)을 포함하고 있다.
| Code Block |
|---|
| title | PersonService.groovy |
|---|
|
class Person {
int id
String firstname
String lastname
}
Person findPerson(int id) {
return new Person(id:id, firstname:'First', lastname:'Last')
|
Server.groovy는 이전 예제와 동일한다.
| Code Block |
|---|
|
import groovy.net.soap.SoapServer;
def server = new SoapServer("localhost", 6980);
server.setNode("PersonService");
server.start();
|
Groovy 컴파일러로 컴파일 된 각각의 클래스들은 metaclass property가 바이트코드에 포함시켜야한다. 이 프로퍼티는 Xfire와 매핑되어지는걸 막아야만한다, 만약 그렇지 않으면 http://localhost:6980/PersonServiceInterface?wsdl로 부터 WSDL 문서에 획들할때 에러가 발생한다. 이 유는 Xfire가 groovy.lang.MetaClass를 맵핑할 수 없기 때문이다. 사용자 정의 타입 매핑은 메타 클래스 속성을 무시하고 디파인 해야함 한다. (참조 : Aegis Binding).
| Code Block |
|---|
|
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:sample="http://DefaultNamespace">
<mapping name="sample:Person">
<property name="metaClass" ignore="true"/>
</mapping>
</mappings>
|
하지만, 자바 부터 사용자 정의 데이터 타입을 컴파일 한다면 바이트 코드는 metaClass속성의 포함을 원하지 않을 것이다. 그러므로, 커스텀 맵핑을 정의할 필요가 없다.
The Client
| Code Block |
|---|
|
import groovy.net.soap.SoapClient
def proxy = new SoapClient('http://localhost:6980/PersonServiceInterface?wsdl')
def person = proxy.findPerson(12)
println 'Person (' + person.id + ') = ' +
person.firstname + ' ' + person.lastname
|
Current limitations (and workaround)
- 인증(authentication)이 없다. (see JIRA issue 1457)
- Proxy를 지원하지 않는다 (see JIRA issue 1458)
- Numeric values는 사용자 정의 데이터 타잎과 array에서는 String으로 의미되어진다.
- 사용자 정의 데이터 타잎은 현재 groovy-1.0 release에서 Grooby SOAP모듈을 사용하는 클라이언트 사이드에서 사용할 수 없다.
- It looks like the XFire dynamic client does not support complex datatypes. This may be a concern if you need for example to transfer an Image as a byte array. The workaround I use is to transform this in a String an transfer that String - As this is a bit painful I am investigating moving to the regular XFire client. Here is a little program demo-ing this (look at this "disco age" image - Is Groovy that old ?
클라이언트 (ImageClient.groovy)
| Code Block |
|---|
|
import groovy.swing.SwingBuilder
import groovy.net.soap.SoapClient
import javax.swing.ImageIcon
import org.apache.commons.codec.binary.Base64
proxy = new SoapClient("http://localhost:6980/ImageServiceInterface?WSDL")
// get the string, transform it to a byte array and decode this array
b64 = new Base64()
bbytes = b64.decode(proxy.getImage().getBytes())
swing = new groovy.swing.SwingBuilder()
// this is regular SwingBuilder stuff
i1 = swing.label(icon:new ImageIcon(bbytes))
frame = swing.frame(title:'Groovy logo', defaultCloseOperation:javax.swing.WindowConstants.DISPOSE_ON_CLOSE) {
panel(){
widget(i1)
}
}
frame.pack()
frame.show()
|
Base64로 인코딩된 이미가 포함된 서버:
| Code Block |
|---|
|
import groovy.net.soap.SoapServer
def server = new SoapServer("localhost", 6980)
server.setNode("ImageService")
server.start()
|
그리고 보호와 보이지 않는 부분은 []이다.
Demos with public web services
여기 테스팅을 위한 쓸모있는 웹서비스가 있다. 쉬운 예제 중 하나는 webservicex.net.에서 제공해주는 환율을 계산해주는 것이다.
여기 서비스를 사용을 데모해주는 작은 스윙 예제가 있다. Enjoy !
| Code Block |
|---|
|
import groovy.swing.SwingBuilder
import groovy.net.soap.SoapClient
proxy = new SoapClient("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL")
def currency = ['USD', 'EUR', 'CAD', 'GBP', 'AUD']
def rate = 0.0
swing = new SwingBuilder()
refresh = swing.action(
name:'Refresh',
closure:this.&refreshText,
mnemonic:'R'
)
frame = swing.frame(title:'Currency Demo') {
panel {
label 'Currency rate from '
comboBox(id:'from', items:currency)
label ' to '
comboBox(id:'to', items:currency)
label ' is '
textField(id:'currency', columns:10, rate.toString())
button(text:'Go !', action:refresh)
}
}
frame.pack()
frame.show()
def refreshText(event) {
rate = proxy.ConversionRate(swing.from.getSelectedItem(), swing.to.getSelectedItem())
swing.currency.text = rate
}
|
결과: 