Spring Support

Apache CXF의 큰 장점 중 하나가 바로 Spring 어플리케이션 개발 지원을 손쉽게 해준다는 것이다. Spring을 사용하여 Web Services 구현 및 호출이 가능하다.
JAX-WS Frontend와 Simple Frontend 모두 Spring Configuration 파일 설정을 통한 Web Services 구현 및 호출을 지원한다. 왼쪽 메뉴에서 JAX-WS FrontendSimple Frontend 매뉴얼 내용에 Spring Configuration 파일 설정 방법 및 사용방법에 대해서 설명하고 있으므로 참고한다.
여기서는 Simple Frontend를 예제로 사용 방법을 보여주고 있다.

다음은 Simple Frontend 를 통해 Spring 지원 기능을 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.

Web Services 작성

Web Services로 노출시킬 서비스를 작성하는데, 일반 서비스 빈 개발 방식과 완벽히 동일하다. Simple Frontend 사용 시에는, JAX-WS Frontend와 다르게 인터페이스 클래스에 어떠한 Annotation도 설정할 필요가 없다.

Samples

다음은 Web Service로 노출시킬 Movie Service에 대한 예제이다. 서비스는 일반 Spring Bean 개발과 동일하게 인터페이스 클래스, 구현 클래스, DAO(Data Access Object) 클래스, VO(Value Object)들로 구성되어 있다.
  • Interface Class
  • 다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다.
    public interface MovieService {
    
        Log LOGGER = LogFactory.getLog(MovieService.class.getName());
    
        public List<Movie> findMovieListAll() throws Exception;
    
        public Map<String, Movie> findMovieMapAll() throws Exception;
    
        public List<Movie> findMovieList(Country country, Category category)
                throws Exception;
    
        public Movie findMovie(String movieId) throws Exception;
    
        public void createMovie(Movie movie) throws Exception;
    
        public void updateMovie(Movie movie) throws Exception;
    
        public void removeMovie(Movie movie) throws Exception;
    ...중략
  • Implementation Class
  • Interface Class를 구현한 구현 클래스로 Web Service 구현과 관련된 부분 없이 작성한다. 다음은 Movie Service의 인터페이스 클래스를 구현한 MovieServiceImpl.java 의 일부이다. 내부적인 MovieDAO 를 사용하여 Movie 정보를 관리하고 있다.
    public class MovieServiceImpl implements MovieService {
    
        private MovieDAO movieDAO = null;
    
        public void setMovieDAO(MovieDAO movieDAO) {
            this.movieDAO = movieDAO;
        }
    
        public List<Movie> findMovieListAll() throws Exception {
            return this.movieDAO.findMovieListAll();
        }
    
        public Map<String, Movie> findMovieMapAll() throws Exception {
            return this.movieDAO.findMovieMapAll();
        }
    
        public List<Movie> findMovieList(Country country, Category category)
                throws Exception {
            return this.movieDAO.findMovieList(country, category);
        }
    
        public Movie findMovie(String movieId) throws Exception {
            return this.movieDAO.fineMovie(movieId);
        }
    
        public void createMovie(Movie movie) throws Exception {
            this.movieDAO.createMovie(movie);
        }
            중략...

Spring Configuration XML - simple:server tag 사용

작성된 서비스를 Web Services로 노출시키는 서버를 구동하기 위해서 2가지 방식이 지원된다. 이중 Spring Configuration XML - <simple:server/> tag를 사용하여 서버를 구동시켜보도록 한다.
<simple:server/> tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 Attribute 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은 Simple Frontend Spring Configuration 을 참고하도록 한다.
Property Name
Description
Required
Default Value
id spring bean id를 작성한다.
Y
N/A
serviceBean 구현 클래스를 작성한다. 클래스명 대신에 spring bean id로 대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다.
Y
N/A
serviceClass 서비스의 인터페이스 클래스를 작성한다.
Y
N/A
address 서비스가 동작할 주소를 상대 경로로 작성한다.
Y
N/A
[하위 element] <simple:dataBinding> Simple Frontend는 디폴트 databinding인 JAXB를 사용하지 않고 AegisDatabinding을 사용해야 하므로 <bean tag의 class 속성 값에 "org.apache.cxf.aegis.databinding.AegisDatabinding"를 설정해야 한다.
Y
N/A

Samples

다음은 Spring Configuration XML - <simple:server/> tag를 사용하여 Movie Service를 Web Service로 노출시키는 서버를 구동하는 예제이다.
  • Configuration
  • 다음은 서버 사이드의 서비스를 Web Services로 노출시키는 <simple:server/> tag 속성을 정의한 context-movie-server.xml 의 일부이다.
    <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" />
    
    <!-- MovieService -->
    <bean id="anyframe.sample.movie.MovieService"
    	class="anyframe.sample.movie.impl.MovieServiceImpl">
    	<property name="movieDAO">
    		<ref bean="movieDAO" />
    	</property>		
    </bean>
    
    <bean id="movieDAO" class="anyframe.sample.movie.impl.MovieDAODefaultImpl" />	
    
    <!-- Simple Frontend to expose MovieService with Aegis Databinding -->	
    <simple:server id="movieService" serviceBean="#anyframe.sample.movie.MovieService" 
           serviceClass="anyframe.sample.movie.MovieService" address="/Movie">
           <simple:dataBinding>
          		<bean class="org.apache.cxf.aegis.databinding.AegisDatabinding" />
       	</simple:dataBinding>
    </simple:server>
    
    Jetty 서버를 이용하여 웹 어플리케이션을 구동하여 서버 사이드의 서비스를 Web Services로 노출시키게 되는데, 이때 web.xml 파일에 Spring Configuration XML 파일을 org.springframework.web.context.ContextLoaderListener를 이용하여 등록시켜 줘야 한다. 다음은 CXFServlet과 ContextLoaderListener를 정의한 web.xml 의 일부이다.
    <web-app>
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>WEB-INF/context-movie-server.xml</param-value>
    	</context-param>
    
    	<listener>
    		<listener-class>
    			org.springframework.web.context.ContextLoaderListener
    		</listener-class>
    	</listener>
    
    	<servlet>
    		<servlet-name>CXFServlet</servlet-name>
    		<display-name>CXF Servlet</display-name>
    		<servlet-class>
    			org.apache.cxf.transport.servlet.CXFServlet
    		</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<servlet-mapping>
    		<servlet-name>CXFServlet</servlet-name>
    		<url-pattern>/*</url-pattern>
    	</servlet-mapping>
    </web-app>
  • Test case
  • 다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드를 작성한 SimpleFrontendSpringSupportSimpleTest.java 의 일부이다. setUp() 메소드 내에서 JettyServer 를 생성시킨 후, 서버의 정보로 Port 번호와 WEB-INF 폴더 경로 정보를 설정해준다.
    상위 테스트케이스 클래스인 RemotingSpringTestCase 의 setUp() 메소드에서 Server 의 start() 메소드가 호출되면서 실제로 구동된다.
    public class SimpleFrontendSpringSupportSimpleTest extends RemotingSpringTestCase {
    
        // ==============================================================
        // ====== TestCase 수행에 필요한 사전 작업 정의 ====================
        // ==============================================================
    
        public void onSetUp() throws Exception {
            this.setServer((new JettyServer());
            ServerInfo serverInfo = new ServerInfo();
            serverInfo.setPort(9002);
            serverInfo
                .setWarpath("src/test/resources/webservices/springsupport/server/webapp");
            this.getServer().setServerInfo(serverInfo);
            super.onSetUp();
        }
        ...중략

Spring Configuration XML - simple:client tag 사용

Spring Configuration 파일 설정을 통해 Web Services에 접근하는 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 Spring Configuration XML - <simple:client/> tag를 사용하여 클라이언트를 작성하여 Web Services에 접근해보도록 한다.
<simple:client/> tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 Attribute 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은 Simple Frontend Spring Configuration 을 참고하도록 한다.
Property Name
Description
Required
Default Value
id spring bean id를 작성한다.
Y
N/A
serviceClass 서비스의 인터페이스 클래스를 작성한다.
Y
N/A
address 서비스 접근 URL Address를 절대 경로로 작성한다.
Y
N/A
[하위 element] <simple:dataBinding> Simple Frontend는 디폴트 databinding인 JAXB를 사용하지 않고 AegisDatabinding을 사용해야 하므로 <bean tag의 class 속성 값에 "org.apache.cxf.aegis.databinding.AegisDatabinding"를 설정해야 한다.
Y
N/A

Samples

다음은 Spring Configuration XML - <simple:client/> tag를 사용하여 Movie Service에 접근하는 예제이다.
  • Configuration
  • 다음은 Web Services로 노출된 Movie Service에 접근하는 <simple:client/> tag 속성을 정의한 context-movie-client-simple.xml 의 일부이다.
    <!-- using Simple Client Bean -->
    <simple:client id="movieServiceSimple" serviceClass="anyframe.sample.movie.MovieService" 
        address="http://localhost:9002/Movie">
    	<simple:dataBinding>
    		<bean class="org.apache.cxf.aegis.databinding.AegisDatabinding" />
    	</simple:dataBinding>
    </simple:client>
  • Test case
  • 다음은 앞서 정의한 속성 설정 파일들을 기반으로 하여 Web Services로 노출된 Movie Service에 접근하는 TestCase인 SimpleFrontendSpringSupportSimpleTest.java 의 일부이다. getConfigLocations() 메소드 내에 클라이언트 Spring Configuration XML(context-movie-client-simple.xml)을 정의함으로써 테스트 케이스 내에서 MovieService에 접근할 수 있도록 한다.
    상위 테스트케이스 클래스인 RemotingSpringTestCase 은 Spring TestCase를 상속받아 구성된 것으로 Setter Injection을 통해 MovieService를 설정하여 해당 테스트 케이스 내에서 호출하여 테스트할 수 있게 한다.
    public class SimpleFrontendSpringSupportSimpleTest extends RemotingSpringTestCase {
    
        // ==============================================================
        // ====== TestCase 수행에 필요한 사전 작업 정의 ====================
        // ==============================================================
        
        private MovieService movieServiceSimple = null;
    
        public void setMovieServiceSimple(MovieService movieService) {
            this.movieServiceSimple = movieService;
        }
    
        protected String[] getConfigLocations() {
            return new String[] {
            "classpath*:/webservices/springsupport/client/context-movie-client-simple.xml" };
        }
        
        // ==============================================================
        // ====== TestCase methods ======================================
        // ==============================================================    
    
        /**
         * [Flow #-3] Positive Case : Movie Id가 "001"인 Movie를 조회한다.
         * @throws Exception
         *         throws exception which is from service
         */        
        public void testFindMovie() throws Exception {
            // 1. find movie
            Movie movie = movieServiceSimple.findMovie("001");
    
            // 2. check the movie information
            assertEquals("The Sound Of Music", movie.getTitle());
            assertEquals("Robert Wise", movie.getDirector());
        }
        ...중략

Spring Configuration XML - ClientProxyFactoryBean 사용

Spring Configuration 파일 설정을 통해 Web Services에 접근하는 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 Spring Configuration XML 파일에 ClientProxyFactoryBean 클래스를 설정하여 Web Services에 접근해보도록 한다.
org.apache.cxf.frontend.ClientProxyFactoryBean의 속성값에 대한 설명은 다음 표와 같다.
Property Name
Description
Required
Default Value
serviceClass 서비스의 인터페이스 클래스를 작성한다.
Y
N/A
address 서비스 접근 URL Address를 절대 경로로 작성한다.
Y
N/A
dataBinding Simple Frontend는 디폴트 databinding인 JAXB를 사용하지 않고 AegisDatabinding을 사용해야 하므로 ref attribute 값에 aegisBean id를 작성한다. Spring bean id가 aegisBean이고 class attribute 값이 "org.apache.cxf.aegis.databinding.AegisDatabinding"인 Bean도 함께 설정한다.
Y
N/A

Samples

다음은 Spring Configuration XML에 ClientProxyFactoryBean 클래스를 설정하여 Movie Service에 접근하는 예제이다.
  • Configuration
  • 다음은 Web Services로 노출된 Movie Service에 접근하는 ClientProxyFactoryBean 속성을 정의한 context-movie-client-factory.xml 의 일부이다.
    <!-- using ClientProxyFactoryBean -->
    <bean id="movieServiceFactory" class="anyframe.sample.movie.MovieService" 
         factory-bean="clientFactory" factory-method="create"/>
       
    <bean id="clientFactory" class="org.apache.cxf.frontend.ClientProxyFactoryBean">
      <property name="serviceClass" value="anyframe.sample.movie.MovieService"/>
      <property name="address" value="http://localhost:9002/Movie"/>
      <property name="dataBinding" ref="aegisBean"/>
    </bean>
    
    <bean id="aegisBean" class="org.apache.cxf.aegis.databinding.AegisDatabinding" />
    
  • Test case
  • 다음은 앞서 정의한 속성 설정 파일들을 기반으로 하여 Web Services로 노출된 Movie Service에 접근하는 TestCase인 SimpleFrontendSpringSupportFactoryTest.java 의 일부이다. getConfigLocations() 메소드 내에 클라이언트 Spring Configuration XML(context-movie-client-factory.xml)을 정의함으로써 테스트 케이스 내에서 MovieService에 접근할 수 있도록 한다.
    상위 테스트케이스 클래스인 RemotingSpringTestCase 은 Spring TestCase를 상속받아 구성된 것으로 Setter Injection을 통해 MovieService를 설정하여 해당 테스트 케이스 내에서 호출하여 테스트할 수 있게 한다.
    public class SimpleFrontendSpringSupportFactoryTest extends RemotingSpringTestCase {
    
        // ==============================================================
        // ====== TestCase 수행에 필요한 사전 작업 정의 ====================
        // ==============================================================
        
        private MovieService movieServiceFactory = null;
    
        public void setMovieServiceFactory(MovieService movieService) {
            this.movieServiceFactory = movieService;
        }
    
        protected String[] getConfigLocations() {
            return new String[] {
                "classpath*:/webservices/springsupport/client/context-movie-client-factory.xml" };
        }
    
        // ==============================================================
        // ====== TestCase methods ======================================
        // ==============================================================
    
        /**
         * [Flow #-3] Positive Case : Movie Id가 "001"인 Movie를 조회한다.
         * @throws Exception
         *         throws exception which is from service
         */      
        public void testFindMovie() throws Exception {
            // 1. find movie
            Movie movie = movieServiceFactory.findMovie("001");
    
            // 2. check the movie information
            assertEquals("The Sound Of Music", movie.getTitle());
            assertEquals("Robert Wise", movie.getDirector());
        }
        ...중략

Resources

  • 다운로드
  • 샘플 테스트 코드를 포함하고 있는 anyframe-remotingtest-src.zip 파일을 다운받은 후, 테스트 환경 설정 을 참조하여 위에서 제시한 예제 코드를 실행해 볼 수 있다. 이때 해당 프로젝트 내의 src/test/java 소스폴더 하위의 anyframe.core.remoting.webservices.springsupport 패키지 하위의 테스트케이스 클래스를 JUnit Test Framework을 이용하여 수행시키도록 한다.
    Name
    Download
    anyframe-remotingtest-src.zip
    Download

  • 참고자료