Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

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파일이 웹서비스를 작성한 것이다.

  1. MathService.groovy
    Code Block
    java
    java
    public class MathService {
        double add(double arg0, double arg1) {
          return (arg0 + arg1)
        }
        double square(double arg0) {
          return (arg0 * arg0)
        }
    }
    
  2. Groovy어디서나 사용할 수 있다.
    Code Block
    java
    java
    double add(double arg0, double arg1) {
      return (arg0 + arg1)
    }
    double square(double arg0) {
      return (arg0 * arg0)
    }
    
  3. 쉬운부분이라 코멘트를 필요없다.
    Code Block
    java
    java
    import groovy.net.soap.SoapServer
    
    def server = new SoapServer("localhost", 6980)
    
    server.setNode("MathService")
    
    server.start()
    
    That's all !

The Client

  1. Oh ... 두줄 정도면 테스트가 가능하다.
    Code Block
    java
    java
    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)
    
  2. 더없다..끝이다!!

Custom Data Types

이 예제는 Groovy SOAP으로 사용자 정의 데이터 타잎을 어떻게 사용하는지를 보여준다. 이코드는 here에서 다운로드 받을 수 있다.

The Server

PersonService.groovy script는 서비스의 구현과 사용자 정의 데이터 타잎(Person)을 포함하고 있다.

Code Block
titlePersonService.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
titleServer.groovy
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
xml
titlePerson.aegis.xml
<?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
titleClient.groovy
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

More Information

Current limitations (and workaround)

  1. 인증(authentication)이 없다. (see JIRA issue 1457)
  2. Proxy를 지원하지 않는다 (see JIRA issue 1458)
  3. Numeric values는 사용자 정의 데이터 타잎과 array에서는 String으로 의미되어진다.
  4.  사용자 정의 데이터 타잎은 현재 groovy-1.0 release에서 Grooby SOAP모듈을 사용하는 클라이언트 사이드에서 사용할 수 없다.
  5. 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
java
java
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
java
java
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
java
java
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
}

결과: