DNA 포럼 API 서비스 모음 DNA Lens

쾌속 웹서비스 개발 Spring & XFire

  • 김영희(CDO본부 검색서비스 개발팀), 2006년 10월

초록(Abstract)

  • 웹서비스 개발시 시행착오와 중복 개발, 코드의 버전 관리등 여러 가지 번거로운 문제들을 피해서 가볍게 웹서비스를 개발해 본다.
  • c/s 메시징에서 메시지의 정의와 처리는 매우 번거로운 일이다. 이번기회에 웹서비스로 변경하는 길잡이가 되길 바란다.

샘플 프로젝트 소개 #

  • 맨 아래 첨부된 프로젝트는 원격 금리를 계산해주는 웹서비스 샘플로 웹서비스 템플릿으로 사용할 수 있다.
  • 압축을 푼 디렉토리를 bank라는 context root로 등록한다.

$tomcat_home/conf/Catalina/localhost/bank.xml

<Context docBase="E:\\Work\\Java\\PrivateBank"
         privileged="true" antiResourceLocking="false" antiJARLocking="false">

  <!-- Link to the user database we will get roles from -->
  <ResourceLink name="users" global="UserDatabase"
                type="org.apache.catalina.UserDatabase"/>

</Context>

<?xml version="1.0" encoding="UTF-8" ?>
- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc11="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenc12="http://www.w3.org/2003/05/soap-encoding" xmlns:tns="http://bank.spring.study.search.daum.net" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://bank.spring.study.search.daum.net">
- <wsdl:types>
- <xsd:schema targetNamespace="http://bank.spring.study.search.daum.net" elementFormDefault="qualified" attributeFormDefault="qualified">
- <xsd:complexType name="Account">
....

제공되는 서비스 #

  • 아래 서비스들을 net.daum.search.study.spring.bank.test의 PrivateBankMainTest와 MyRemoteBankTest를 통해서 간단히 테스트 할 수 있다.
  • 아래 메서드에서 deposit, draw에서 Account를 돌려줄 필요는 없지만 객체를 리턴 받는법을 보이고자 객체로 리턴한다.

        public abstract Account deposit(Account account, long money);
        public abstract Account draw(Account account, long money);
        public abstract long calculateInterestAfter(Account account, int day);

프로젝트 구성 #

  • PrivateBank
    • src
    • WEB-INF
      • lib
      • conf : Spring beans를 위해 임시로 몇개 xml을 넣어둠
      • classes
      • privateBankContext.xml : app context
      • bank-servlet.xml : spring에서 xfire를 이용해 service를 export하는 설정을 담음
      • web.xml : spring의 dispatch servlet을 설정

Spring/XFire 시작하기 #

Spring #

  • 스프링을 사용하면 Layered Architecture를 쉽게 구성할 수 있다.
  • IoC를 통해서 객체간 의존성을 줄이며 재사용을 도와준다.
  • 좋은 은행은 10%의 좋은 단리로 이자가 붙는다.
  • 나쁜 은행은 2%의 바보 단리로 이자를 준다.
  • 수퍼 은행은 상상을 초월한 이자를 준다.
  • SimpleInterest라는 객체에 이율이라는 조건을 달리해서 좋은 은행과 나쁜 은행을 생성하는걸 볼 수 있다.
  • 복리라는 이율을 가지고 있지만 적용한 은행은 아직 없다.

http://dna.daum.net/wiki/imgs/custom/WebServicesUsingSpringXfire_1.jpg

아래는 Spring에서 주로 작성하는 applicationContext.xml로 privateBankContext.xml로 명명했다.

privateBankContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
        <bean id="goodSimpleInterest" class="net.daum.search.study.spring.bank.SimpleInterest" singleton="false">
                <property name="interestPercent"><value>10</value></property>
        </bean>
        <bean id="baboSimpleInterest" class="net.daum.search.study.spring.bank.SimpleInterest" singleton="false">
                <property name="interestPercent"><value>2</value></property>
        </bean>
        <bean id="superPowerInterest" class="net.daum.search.study.spring.bank.PowerInterest" singleton="false">
                <property name="interestPercent"><value>10</value></property>
        </bean>
        <bean id="compoundInterest" class="net.daum.search.study.spring.bank.CompoundInterest" singleton="false">
                <property name="interestPercent"><value>10</value></property>
        </bean>

        <bean id="goodBank" class="net.daum.search.study.spring.bank.PrivateBank" singleton="false">
                <property name="interest"><ref bean="goodSimpleInterest"/></property>
        </bean>
        <bean id="badBank" class="net.daum.search.study.spring.bank.PrivateBank" singleton="false">
                <property name="interest"><ref bean="baboSimpleInterest"/></property>
        </bean>
        <bean id="superBank" class="net.daum.search.study.spring.bank.PrivateBank" singleton="false">
                <property name="interest"><ref bean="superPowerInterest"/></property>
        </bean>
</beans>

Spring/XFire #

  • Spring에서 작성한 객체들을 재사용 하고 싶은데 마땅한 툴들을 찾지 못하던중 XFire를 발견했다.
  • Axis나 다른 프레임웍보다 궁합이 잘맞고 Stax기반으로 Axis에 비해 5배나 빠르다.
  • 더욱이 Axis와 같은 툴을 통해서 코드를 자동 생성하게 되면 프로젝트의 버전 관리가 어렵기 때문에 Axis는 마지막까지 선택할 수 없었다.
  • (그러나 Axis 2.0은 그럴 필요가 없다.)
  • 다음은 XFire를 통해서 서비스를 export 해주는 Spring 설정이다.

  • ServiceBean : 서비스 구현체
  • ServiceClass : 오픈할 서비스의 인터페이스
  • ServiceFactory : 서비스 팩토로 - 여기서는 XmlBeans를 이용한다.

http://dna.daum.net/wiki/imgs/custom/WebServicesUsingSpringXfire_2.jpg

bank-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- Declare a parent bean with all properties common to both services -->
    <bean name="/SimpleBankService" class="org.codehaus.xfire.spring.remoting.XFireExporter" singleton="true">
                <property name="serviceBean"><ref bean="goodBank"/></property>
        <property name="serviceClass"><value>net.daum.search.study.spring.bank.Bank</value></property>
        <property name="serviceFactory"><ref bean="xfire.xmlbeansServiceFactory"/></property>
    </bean>
</beans>

다음은 service Factory로 xmlBeans를 사용하기 위한 web.xml설정이다. context-param에 spring의 설정과 XFire설정을 아래와 같이 추가하면된다.

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
			/WEB-INF/privateBankContext.xml
			classpath:org/codehaus/xfire/spring/xfire.xml
			classpath:org/codehaus/xfire/spring/xfireXmlBeans.xml
			classpath:org/codehaus/xfire/spring/customEditors.xml
	  </param-value>
    </context-param>
...
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
	
    <servlet>
        <servlet-name>bank</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>bank</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

결론 #

  • 기존에 Spring으로 개발한 Beans를 XFire를 통해 바로 서비스로 export 할 수 있다.
  • 프로젝트 전반에 걸쳐 중복 개발 최소화(서비스와 서비스간 공통 모듈을 copy&paste가 아닌 bean ref를 통해 재사용)
  • Stax기반으로 성능 극대화
  • 스파게티 코드 생성에서 해방

첨부파일 #