<div class="information"> 원문 : http://blog.naver.com/puresprout77/60035416570

이 문서는 Axis2 1.1.1을 기준으로 작성되었음을 알려드립니다. </div>

Axis2 Integration With The Spring Framework#

이 문서는 Axis2가 어떻게 스프링 프레임웍을 사용하는지 그 방법을 안내한다.

목차#

  • 소개[1]
  • Axis2가 Spring을 인식하도록 설정하기[2]
  • 프로그래밍 모델[3]
  • 간단한 스프링 환경설정 예제[4]
  • ServletContent를 가지고[5]
  • ServletContent없이[6]
  • 그것에다 모든것을 같이 넣기[7]
  • AAR 파일안에서의 스프링[8]
    • AAR layout 내부의 스프링[9]
    • AAR init class 내부의 스프링[10]
    • AAR 내부에서 스프링을 실행할때의 알려진 문제점[11]

소개[#1]#

Axis2와 스프링의 통합은 Axis2가 단순히 스프링을 통해 미리 로드된 빈을 AAR 파일의 services.xml 파일에서 정의된 Axis2 Message Receiver에게 공급하는 것이 필요해서이다. Axis2는 전형적으로 메시지 수신자(Message Receiver)가 사용하는 services.xml에 정의된 ServiceClass를 인스턴스하기 위해서 리플렉션을 사용하는 반면, 대체적으로 그것은 객체를 공급하는 ServiceObjectSupplier를 정의할수 있다. 이 문서는 Axis2 표준 배포판의 일부인 두 개의 개별적인 ServiceObjectSupplier를 어떻게 사용하는지 보여줄 것이다. ServletContext를 가진것과 그렇치 않은 것. 일단 환경이 설정되면, 웹 서비스는 스스로 어떤 다른 스프링 wired 빈처럼 동작한다. 이 스프링 빈들은 Axis2가 스프링과의 환경설정 의존성이 없기 때문에 어떤 원하는 방식으로 로드될 수 있다. Spring 버전은 1.2.6, 1.2.8, 2.0이 테스트되었고, 아마도 다른 버전들은 단지 핵심 기능만이 작동될 것이다. 이 문서는 Axis2에 대한 약간의 기초 지식이 필요로 한다. 더 자세한 건 User's Guide를 보아라.

Axis2가 Spring을 인식하도록 환경설정하기[#2]#

프로그래밍 모델[#3]#

두 개의 hook이 AAR services.xml 파일에 넣어져야 한다. Axis2와 스프링을 같이 hook하는 ServiceObjectSupplier와 Axis2가 서비스로서 사용하는 스프링 빈의 이름. org.apache.axis2.receivers.AbstractmessageReceiver를 확장하는 어떤 메시지 수신자라면 모든 메시지 수신자는 현재 지원된다.

간단한 스프링 환경설정 예제[#4]#

이 예제의 목적을 위해, 또한 단순함외에 다른 목적이 없이, 우리는 스피링을 WAR 파일의 web.xml 파이을 통해서 환경설정할 것이다. context-param과 리스너를 추가하자

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

다음 우리는 web.xml 리스너에서 참조하는 스프링의 /WEB-INF/applicationContext.xml의 두개의 예제를 볼 것이다. 하는는 ServletContext를 사용해서, 다른 하나는 사용하지 않고

ServletContext를 사용해서[#5]#

이 예제의 applicationContext.xml은 스프링 유저에게 친숙해야만 한다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies -->
  <bean id="springAwareService" class="spring.SpringAwareService">
    <property name="myBean" ref="myBean"/>
  </bean>

  <!-- just another bean / interface with a wired implementation, that's injected by Spring
          into the Web Service -->
   <bean id="myBean" class="spring.MyBeanImpl">
     <property name="val" value="Spring, emerge thyself" />
  </bean>
</beans>

만일 서비스가 서블릿 컨테이너에서 돌아간다면 즉, Axis2가 ServletContext를 얻을수 있다면, 이 예제를 위한 services.xml은 다음처럼 SpringServletContextObjectSupplier를 사용할 것이다.

<service name="SpringAwareService">
    <description>
        simple spring example
    </description>
    <parameter name="ServiceObjectSupplier" locked="false">
  org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier
</parameter>
    <parameter name="SpringBeanName" locked="false">springAwareService</parameter>
    <operation name="getValue">
        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>
</service>

위의 예제에서는 메시지 수신자로서 RawXMLINOutMessageReceiver를 사용하지만, 모든 메시지 수신자가 org.apache.axis2.receivers.AbstractMessageReceiver를 확장했기 때문에 지원된다.

ServletContext없이[#6]#

Axis2가 ServletContext를 얻을수 없을 때, 예를 들어 다른 전송계층이나 AAR내부에서 실행될때, 당신은 Axis2에게 어플리케이션 컨텍스트를 제공하기 위해 스프링의 내부 기능을 갖고있는 빈을 정의하는 옵션을 'applicationContext' 빈 참조로서 가질수 있다.(ApplicationContextAware 인터페이스)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <!-- Configure spring to give a hook to axis2 without a ServletContext -->
  <bean id="applicationContext"
    class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />

  <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies -->
  <bean id="springAwareService"
        class="spring.SpringAwareService">
    <property name="myBean" ref="myBean" />
  </bean>

  <!-- just another bean with a wired implementation, that's injected by Spring
          into the Web Service -->
   <bean id="myBean"
        class="spring.MyBeanImpl">
     <property name="val" value="Spring, emerge thyself" />
  </bean>
</beans>

만일 서비스가 서블릿 컨테이너에서 실행되지 않는다면, 즉 Axis2는 ServletContext를 갖지 못할 것이다. 예제를 위한 services.xml은 다음과 같이 SpringAppContextAwareObjectSupplier를 사용할 것이다.

<service name="SpringAwareService">
    <description>
        simple spring example
    </description>
    <parameter name="ServiceObjectSupplier" locked="false">
  org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
    </parameter>
    <parameter name="SpringBeanName" locked="false">springAwareService</parameter>
    <operation name="getValue">
        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
    </operation>
</service>

위의 예제에서는 메시지 수신자로서 RawXMLINOutMessageReceiver를 사용하지만, 모든 메시지 수신자가 org.apache.axis2.receivers.AbstractMessageReceiver를 확장했기 때문에 지원된다.

ServletContext가 없는 환경에서, 당신이 applicationContext.xml 파일을 로드할 수 있는 한가지 방법이 여기에 있다.

import org.springframework.context.support.ClassPathXmlApplicationContext;

public void createSpringAppCtx(ClassLoader cl)
            throws Exception {

    ClassPathXmlApplicationContext ctx = new
      ClassPathXmlApplicationContext(new String[] {Constants.MY_PATH +
      "spring/applicationContext.xml"}false);
           ctx.setClassLoader(cl);
           ctx.refresh();

Putting It All Together[#7]#

이제, 서비스는 스프링 wiring 능력을 가진다. SpringServletContextObjectSupplier를 사용하나 SpringAppContextAwareObjectSupplier를 사용하나 구현은 같다. 서비스는 아래와 같다.

package spring;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMText;

public class SpringAwareService {

    private MyBean myBean = null;

    //spring 'injects' this implementation
    public void setMyBean(MyBean myBean) {
            this.myBean = myBean;
    }

    // The web service
    public OMElement getValue(OMElement ignore) {
            OMFactory factory=
                OMAbstractFactory.getOMFactory();
            OMNamespace payloadNs= factory.createOMNamespace(
                "http://springExample.org/example1""example1");
            OMElement payload =
                factory.createOMElement("string", payloadNs);
            OMText response = factory.createOMText(this.myBean.emerge());
            payload.addChild(response);
            return payload;
    }
}

스프링이 처음인 사람을 위해 개념중 하나는 당신이 인터페이스를 프로그램하고, 구현은 pluggable 될 수 있다. 이 개념이 스프링 환경설정 파일에서 참조된다. 아래는 인테페이스이다.

package spring;

/** Interface for Spring aware Bean */
public interface MyBean {
         String emerge();
}

아래는 구현이다.

/** Spring wired implementation */
public class MyBeanImpl implements MyBean {

    String str = null;
    // spring 'injects' this value
    public void setVal(String s) {
        str = s;
    }
    // web service gets this value
    public String emerge() {
        return str;
    }
}

마지막으로 클라이언트를 만들자. 이 예제를 위해 필요로하기 보다는 완전성을 위해서다.

package client;

import java.io.StringWriter;

import javax.xml.stream.XMLOutputFactory;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;

public class TestClient {
    private static EndpointReference targetEPR =
        new EndpointReference(
               "http://localhost:8080/axis2/services/SpringAwareService");

    /**
     * Simple axis2 client.
     *
     @param args Main
     */
    public static void main(String[] args) {
        try {
            OMFactory factory = OMAbstractFactory.getOMFactory();
            OMNamespace omNs = factory.createOMNamespace(
                        "http://springExample.org/example1""example1");

            OMElement method = factory.createOMElement("getValue", omNs);
            OMElement value = factory.createOMElement("Text", omNs);
            value.addChild(factory.createOMText(value, "Some String "));
            method.addChild(value);

            ServiceClient serviceClient = new ServiceClient();

            Options options = new Options();
            serviceClient.setOptions(options);
            options.setTo(targetEPR);

            //Blocking invocation
            OMElement result = serviceClient.sendReceive(method);

            StringWriter writer = new StringWriter();
            result.serialize(XMLOutputFactory.newInstance()
                    .createXMLStreamWriter(writer));
            writer.flush();

            System.out.println("Response: " + writer.toString());
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

이 예제는 스프링 프레임웍 jar과 axis2-spring-*.jar가 WEB-INF/lib에 둘다 있다는 것을 가정한다. 이러한 경우에 이 가이드에서 보여진 클래스들은 WEB-INF/lib에 하나의 JAR 파일에 놓일 필요가 있다.

./mySpring.jar
./META-INF
./META-INF/MANIFEST.MF
./spring
./spring/MyBean.class
./spring/MyBeanImpl.class
./spring/SpringAwareService.class

모든 사용자 클래스들이 mySpring.jar에 있기 때문에 AAR 파일은 services.xml 파일만 포함하면 된다.

./springExample.aar
./META-INF
./META-INF/MANIFEST.MF
./META-INF/services.xml

이 예제를 실행하기 위해서, 당신은 axis2-std-*-bin 배포판에 포함된 axis2-spring*.jar 파일이 서버측의 WEB-INF/lib에 있는지 확인하라. 뿐만 아니라 적절한 스프링 jar도. 대부분은 full spring.jar를 쓰겠지만, 최소의 요구는 spring-core, spring-beans, spring-context와 spring-web이다. 클라이언트를 실행하면 다음의 출력을 볼수 있다.

Response: <example1:string xmlns:example1="http://springExample.org/example1"
  xmlns:tns="http://ws.apache.org/axis2">Spring, emerge thyself</example1:string>

Add new attachment

Only authorized users are allowed to upload new attachments.
« This page (revision-2) was last changed on 03-Aug-2007 17:36 by DongGukLee