JAX-WS Frontend
Web Services 표준 API인 JAX-WS를 사용하여 Annotation 설정을 통해 Web Services를 구현할 수 있게 해주는 Frontend 모델이다.
JAX-WS(Java API for XML Web Services)는 웹 서비스를 작성하는 자바 API로써, Java EE의 일부이다.
다른 Java EE의 자바 API와 같이, JAX-WS는 Java SE 5에서 도입된 어노테이션(Annotation)을 사용하여
웹 서비스 클라이언트 및 서버 모듈의 개발 및 배포를 쉽게 하고 있다.
JAX-WS는 JAX-RPC 표준을 발전 시킨 개념으로 XML의 바인딩을 위한 JAXB 표준과 표준 스트리밍 파서를 위한 SAX 표준,
기능이 향상된 새로운 SAAJ 표준을 기반으로 통합, 발전된 웹 서비스 기술 표준이다.
JAX-WS의 특징을 살펴보면 다음과 같다.
- JAX-RPC에 비해 Web Service 작성 편리
JAX-RPC와 비교해보았을때 Web Service 작성이 매우 편리해진 장점을 갖고 있다.
Annotation 설정을 통해 Web Service Endpoint 작성 및 자바 타입과 WSDL 간의 매핑 등을 명시적으로 수행할 수 있다. 기존의 JAX-RPC 환경에서 Web Service를 생성하기 위해 작성해야만 했던 Web Service 배치 서술자 등을 모두 Annotation으로 대체 가능함으로써 Web Service 작성의 어려움을 크게 없애준다.
- Annotation을 통해 하는 작업
자바와 WSDL의 매핑 및 자바 타입과 WSDL에서 참조하는 메시지의 Schema 타입으로의 매핑을 담당한다. 실제 Web Service 메시지를 처리하는 Runtime Process 중에 필요한 정보를 제공하며 Web Service 호출에 응답하는데 사용된다.
- Annotation 관련 Spec.
JAX-WS 2.0에서 사용하게 되는 Annotation은 Web Services Metadata(JSR-181) Spec.과 JAX-WS 2.0 Spec.에 분리 정의되어 있다. 이외의 메시지 타입 매핑을 위해 사용되는 Annotation은 JAXB 2.0 Spec.에 정의되어 있다.
Web Services Metadata(JSR-181) Spec.에 정의된 대표적인 Annotation으로는 다음과 같은 것들이 있다.(javax.jws.WebService, javax.jws.WebMethod, javax.jws.WebParam, javax.jws.WebResult, javax.jws.soap.SOAPBinding)
JAX-WS의 프로세스를 그림으로 살펴보면 다음과 같다.

다음은 JAX-WS Frontend를 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.
JAX-WS Frontend는 크게 JAX-WS Frontend API를 사용하여 서버와 클라이언트를 작성하는 방식과 Spring Configuration을 이용하는 방식으로 구분하여 사용될 수 있다.
Web Service 작성
Web Service로 노출시킬 서비스를 작성하는데, 일반 서비스 Bean 개발 방식과 거의 동일하다. 단, 인터페이스 클래스에 @WebService Annotation이 설정되어야 함에
유의하도록 한다.
Samples
다음은 Web Service로 노출시킬 Movie Service에 대한 예제이다. 서비스는 일반 Spring Bean 개발과 동일하게 인터페이스 클래스, 구현 클래스, DAO(Data Access Object) 클래스, VO(Value Object)들로
구성되어 있다.
Interface Class
다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java
의 일부이다.
인터페이스 클래스 상단에 @WebService Annotation을 작성해줘야 한다. @WebService Annotation의 속성 값들도 다양하게 존재하고, 각 메소드와 파라미터 별로 정의할 수 있는 Annotation의 종류도
여러가지가 있으나 필수 사항으로 필요한 Annotation은 @WebService뿐이다. 다른 종류의 Annotation에 대해서 추가 작성하는 방법에 대해서는 [참고] Web Services 작성 시 Annotation 설정 방법
을 참고하도록 한다.
import javax.jws.WebService;
@WebService
public interface MovieService {
public List<Movie> findMovieListAll() 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 정보를 관리하고 있다.
구현 클래스 상단에 @WebService Annotation을 추가 작성해줄 수도 있다. 이미 인터페이스 클래스 상단에 @WebService Annotation을 작성해주었으므로 여기서는 생략시켰다.
Annotation 설정 방법에 대해서는 [참고] Web Services 작성 시 Annotation 설정 방법
을 참고하도록 한다.
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 Movie findMovie(String movieId) throws Exception {
return this.movieDAO.fineMovie(movieId);
}
public void createMovie(Movie movie) throws Exception {
this.movieDAO.createMovie(movie);
}중략...
Server: JAX-WS Frontend API 사용
작성된 서비스를 Web Service로 노출시키는 서버를 구동하기 위해서 3가지 방식이 지원된다. 이중 JAX-WS Frontend API 코드를 직접 작성하여 서버를 구동시켜보도록 한다.
Apache CXF에서 제공하는 JAX-WS Frontend API를 직접 호출하여 작성하는 것도 가능하지만, Anyframe에서 제공하는 API인
JaxWsServer
를 사용하면
더욱 간편하고 편리하게 사용할 수 있다.(JaxWsServer 내부적으로 JAX-WS Frontend API를 호출하고 있다.)
Samples
다음은 Anyframe에서 제공하는 JaxWsServer 혹은 Apache CXF에서 제공하는 JaxWsServerFactoryBean을 직접 이용하여 Movie Service를 Web Service로 노출시키는 서버를 구동하는 예제이다.
Anyframe JaxWsServer 사용한 서버 구동
다음은 비즈니스 레이어의 서비스를 Web Service로 노출시키는 서버를 구동하는 코드를 작성한 JaxWsFrontendServerFactoryTest.java
의 일부이다.
setUp() 메소드 내에서 JaxWsServer
를 생성시킨 후, 서버의 정보로 인터페이스 클래스, 구현 클래스의 인스턴스, Web Service 주소를 설정해준다.
상위 테스트케이스 클래스인 RemotingTestCase
의 setUp() 메소드에서 Server
의 start() 메소드가 호출되면서 실제로 구동된다.
public class JaxWsFrontendServerFactoryTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase 수행에 필요한 사전 작업 정의 ====================
// ==============================================================
public void setUp() throws Exception {
this.setServer(new JaxWsServer());
this.getServer().setServerInfo(new ServerInfo(
MovieService.class, new MovieServiceImpl(), "http://localhost:9002/Movie", false));
super.setUp();
}
...중략
Apache CXF JaxWsServerFactoryBean을 사용한 서버 구동
다음은 비즈니스 레이어의 서비스를 Web Service로 노출시키는 서버를 구동하는 코드 작성 예이다.
MovieServiceImpl implementor = new MovieServiceImpl();
JaxWsServerFactoryBean svrFactory=new JaxWsServerFactoryBean();
svrFactory.setServiceClass(MovieService.class);
svrFactory.setAddress("http://localhost:9002/Movie");
svrFactory.setServiceBean(implementor);
svrFactory.create();
Spring Configuration XML - jaxws:endpoint tag 사용
작성된 서비스를 Web Service로 노출시키는 서버를 구동하기 위해서 3가지 방식이 지원된다. 이중 Spring Configuration XML - <jaxws:endpoint/> tag를 사용하여 서버를 구동시켜보도록 한다.
<jaxws:endpoint/> tag의 각 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로
작성해야 하는 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성값들에 대한 설명은
JAX-WS Spring Configuration
을 참고하도록 한다.
| Property Name
|
Description
|
Required
|
Default Value
|
| id |
spring bean id를 작성한다. |
Y |
N/A |
| implementor |
구현 클래스를 작성한다. 클래스명 대신에 spring bean id로 대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다. |
Y |
N/A |
| address |
서비스가 동작할 주소를 상대 경로로 작성한다. |
Y |
N/A |
Samples
다음은 Spring Configuration XML - <jaxws:endpoint/> tag를 사용하여 Movie Service를 Web Service로 노출시키는 서버를 구동하는 예제이다.
Configuration
다음은 비즈니스 레이어의 서비스를 Web Service로 노출시키는 <jaxws:endpoint/> tag 속성을 정의한 context-movie-server-endpoint.xml
의 일부이다.
<!-- Load CXF modules from cxf.jar -->
<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" />
<!-- Enable message logging using the CXF logging feature -->
<cxf:bus>
<cxf:features>
<cxf:logging />
</cxf:features>
</cxf:bus>
<!-- MovieService -->
<bean id="anyframe.sample.movie.jaxws.MovieService"
class="anyframe.sample.movie.jaxws.impl.MovieServiceImpl">
<property name="movieDAO">
<ref bean="movieDAO" />
</property>
</bean>
<bean id="movieDAO" class="anyframe.sample.movie.jaxws.impl.MovieDAODefaultImpl" />
<!-- JAX-WS Frontend to expose movieService using endpoint tag -->
<jaxws:endpoint id="movieService" implementor="#anyframe.sample.movie.jaxws.MovieService"
address="/Movie"/>
Jetty 서버를 이용하여 웹 어플리케이션을 구동하고 비즈니스 레이어의 서비스를 Web Service로 노출시키게 되는데, 이때 web.xml 파일에 Spring 속성 정의 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-endpoint.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 Service로 노출시키는 서버를 구동하는 코드를 작성한 JaxWsFrontendSpringServerEndpointTest.java
의 일부이다.
setUp() 메소드 내에서 JettyServer
를 생성시킨 후, 서버의 정보로 Port 번호와 WEB-INF 폴더 경로 정보를 설정해준다.
상위 테스트케이스 클래스인 RemotingTestCase
의 setUp() 메소드에서 Server
의 start() 메소드가 호출되면서 실제로 구동된다.
public class JaxWsFrontendSpringServerEndpointTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase 수행에 필요한 사전 작업 정의 ====================
// ==============================================================
public void setUp() throws Exception {
this.setServer((new JettyServer());
ServerInfo serverInfo = new ServerInfo();
serverInfo.setPort(9002);
serverInfo.setWarpath("src/test/resources/webservices/jaxws/server/endpoint/webapp");
this.getServer().setServerInfo(serverInfo);
super.setUp();
}
...중략
Spring Configuration XML - jaxws:server tag 사용
작성된 서비스를 Web Service로 노출시키는 서버를 구동하기 위해서 3가지 방식이 지원된다. 이중 Spring Configuration XML - <jaxws:server/> tag를 사용하여 서버를 구동시켜보도록 한다.
<jaxws:server/> tag의 각 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로
작성해야 하는 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성값들에 대한 설명은
JAX-WS Spring Configuration
을 참고하도록 한다.
| Property Name
|
Description
|
Required
|
Default Value
|
| id |
spring bean id를 작성한다. |
Y |
N/A |
| serviceBean |
구현 클래스를 작성한다. 클래스명 대신에 spring bean id로 대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다. |
Y |
N/A |
| address |
서비스가 동작할 주소를 상대 경로로 작성한다. |
Y |
N/A |
Samples
다음은 Spring Configuration XML - <jaxws:server/> tag를 사용하여 Movie Service를 Web Service로 노출시키는 서버를 구동하는 예제이다.
Configuration
다음은 서버 사이드의 서비스를 Web Services로 노출시키는 <jaxws:server/> tag 속성을 정의한 context-movie-server.xml
의 일부이다.
<!-- Load CXF modules from cxf.jar -->
<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" />
<!-- Enable message logging using the CXF logging feature -->
<cxf:bus>
<cxf:features>
<cxf:logging />
</cxf:features>
</cxf:bus>
<!-- MovieService -->
<bean id="anyframe.sample.movie.jaxws.MovieService"
class="anyframe.sample.movie.jaxws.impl.MovieServiceImpl">
<property name="movieDAO">
<ref bean="movieDAO" />
</property>
</bean>
<bean id="movieDAO" class="anyframe.sample.movie.jaxws.impl.MovieDAODefaultImpl" />
<!-- JAX-WS Frontend to expose movieService using server tag -->
<jaxws:server id="movieService" serviceBean="#anyframe.sample.movie.jaxws.MovieService"
address="/Movie"/>
Jetty 서버를 이용하여 웹 어플리케이션을 구동하고, 비즈니스 레이어의 서비스를 Web Service로 노출시키게 되는데, 이때 web.xml 파일에 Spring 속성 정의 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 Service로 노출시키는 서버를 구동하는 코드를 작성한 JaxWsFrontendSpringServerTest.java
의 일부이다.
setUp() 메소드 내에서 JettyServer
를 생성시킨 후, 서버의 정보로 Port 번호와 Web Context Root 폴더 경로 정보를 설정해준다.
상위 테스트케이스 클래스인 RemotingTestCase
의 setUp() 메소드에서 Server
의 start() 메소드가 호출되면서 실제로 구동된다.
public class JaxWsFrontendSpringServerTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase 수행에 필요한 사전 작업 정의 ====================
// ==============================================================
public void setUp() throws Exception {
this.setServer((new JettyServer());
ServerInfo serverInfo = new ServerInfo();
serverInfo.setPort(9002);
serverInfo.setWarpath("src/test/resources/webservices/jaxws/server/webapp");
this.getServer().setServerInfo(serverInfo);
super.setUp();
}
...중략
Client: JAX-WS Frontend API 사용
Web Service에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 JAX-WS Frontend API를 직접 이용한 클라이언트를 작성하여
Web Service에 접근해보도록 한다.
Apache CXF에서 제공하는 JAX-WS Frontend API를 직접 호출하여 작성하는 것도 가능하지만, Anyframe에서 제공하는 API인
JaxWsClient
를 사용하면
더욱 간편하고 편리하게 사용할 수 있다.(JaxWsClient 내부적으로 JAX-WS Frontend API를 호출하고 있다.)
Samples
다음은 Anyframe에서 제공하는 JaxWsClient 혹은 Apache CXF에서 제공하는 JaxWsProxyFactoryBean를 직접 이용하여 Web Services로 노출된 Movie Service에 접근하는 예제이다.
Anyframe JaxWsClient 사용한 클라이언트
다음은 Anyframe에서 제공하는 JaxWsClient 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 클라이언트 코드를 작성한 JaxWsFrontendServerFactoryTest.java
의 일부이다.
testXXX() 메소드 내에서 JaxWsClient
를 생성시킨 후, 클라이언트의 정보로 인터페이스 클래스와 접근하고자 하는 Web Services 주소를 이용하여
Movie Service를 얻어낸다. Movie Service를 얻은 후에는 Movie Service에서 Web Service 메소드로 노출된 메소드를 호출하여 동작이 올바른지 테스트해본다.
public class JaxWsFrontendServerFactoryTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase methods ======================================
// ==============================================================
/**
* [Flow #-3] Positive Case : Movie Id가 "001"인 Movie를 조회한다.
* @throws Exception
* throws exception which is from service
*/
public void testFindMovie() throws Exception {
Client client = new JaxWsClient();)
MovieService movieService = (MovieService) client.getClient(
new ClientInfo(MovieService.class, "http://localhost:9002/Movie", false)));
// 1. find movie
Movie movie = movieService.findMovie("001");
// 2. check the movie information
assertEquals("The Sound Of Music", movie.getTitle());
assertEquals("Robert Wise", movie.getDirector());
}
...중략
Apache CXF JaxWsProxyFactoryBean 사용한 클라이언트
다음은 Apache CXF에서 제공하는 JaxWsProxyFactoryBean 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 코드 작성 예이다.
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(MovieService.class);
factory.setAddress("http://localhost:9002/Movie");
MovieService movieService = (MovieService) factory.create();
Movie movie=movieService.findMovie("001");
Spring Configuration XML - jaxws:client tag 사용
Web Services에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 Spring Configuration XML - <jaxws:client/> tag를 사용하여 클라이언트를 작성하여
Web Services에 접근해보도록 한다.
<jaxws:client/> tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로
작성해야 하는 Attribute 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은
JAX-WS 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 |
Samples
다음은 Spring Configuration XML - <jaxws:client/> tag를 사용하여 Movie Service에 접근하는 예제이다.
Configuration
다음은 Web Services로 노출된 Movie Service에 접근하는 <jaxws:client/> tag 속성을 정의한 context-movie-client.xml
의 일부이다.
<!-- using JAX-WS Client Bean -->
<jaxws:client id="movieService" serviceClass="anyframe.sample.movie.jaxws.MovieService"
address="http://localhost:9002/Movie"/>
Test case
다음은 앞서 정의한 속성 설정 파일들을 기반으로 하여 Web Services로 노출된 Movie Service에 접근하는 TestCase인 JaxWsFrontendSpringClientTest.java
의 일부이다.
getConfigLocations() 메소드 내에 클라이언트 Spring Configuration XML(context-movie-client.xml)을 정의함으로써
테스트 케이스 내에서 MovieService에 접근할 수 있도록 한다.
상위 테스트케이스 클래스인 RemotingSpringTestCase
은 Spring TestCase를 상속받아 구성된 것으로
Setter Injection을 통해 MovieService를 설정하여 해당 테스트 케이스 내에서 호출하여 테스트할 수 있게 한다.
public class JaxWsFrontendSpringClientTest extends RemotingSpringTestCase {
// ==============================================================
// ====== TestCase 수행에 필요한 사전 작업 정의 ====================
// ==============================================================
private MovieService movieService = null;
public void setMovieService(MovieService movieService) {
this.movieService = movieService;
}
protected String[] getConfigLocations() {
중략...
return new String[] {
"classpath*:/webservices/jaxws/client/context-movie-client.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 = movieService.findMovie("001");
// 2. check the movie information
assertEquals("The Sound Of Music", movie.getTitle());
assertEquals("Robert Wise", movie.getDirector());
}
...중략
Annotation 작성
@WebService()만 필수 사항이고 대부분 annotation의 경우 디폴트 값이 제공되므로 작성이 불필요 하다.
@WebService (javax.jws.WebService)
Annotation을 포함하고 있는 자바 클래스가 Web Service Endpoint 인터페이스 클래스 혹은 구현 클래스임을 명시할 때 사용하
SEI와 구현 클래스에 설정한다.(필수 사항)
모든 Property의 값을 작성할 필요는 없으나 되도록 많은 정보를 작성하는 것을 권장한다.
SEI에 더 많은 Annotation 정보를 작성할 수록 잘 정의된 WSDL을 생성시킬 수 있기 때문이다.
Property에 대한 세부 내용은 다음 표와 같다.
| Property |
Type |
필수 |
WSDL Mapping |
Default |
설명 |
| name |
String |
X |
wsdl:portType |
클래스명 |
웹 서비스 명으로 wsdl:portType으로 매핑됨, 기본값은 인터페이스클래스 혹은 구현 클래스의 패키지를 제외한 명 |
| targetNamespace |
String |
X |
N/A |
패키지 명 |
웹 서비스로부터 생성된 XML element와 WSDL에 사용될 XML namespace |
| serviceName |
String |
X |
wsdl:service |
클래스명+"Service" |
SEI에 설정 불가
, 서비스 명으로 wsdl:service 로 매핑됨, 기본값은 인터페이스클래스 혹은 구현 클래스의 패키지명을 제외한 명+"Service" |
| wsdlLocation |
String |
X |
N/A |
서비스 디플로이 URI |
미리 정의된 WSDL의 위치로 WSDL에 정의된 portType, binding은 서비스 구현 클래스에 작성된 값들과 일치해야 함 |
| endpointInterface |
String |
X |
N/A |
SEI의 패키지명을 포함한 클래스명 |
SEI에 설정 불가
, 구현 클래스의 SEI 명 |
| portName |
String |
X |
wsdl:port |
구현 클래스 명+"Port" |
SEI에 설정 불가
, wsdl:port로 매핑됨, 기본값은 구현클래스명+"Port" |
@WebService annotation 설정이 적용된 클래스 내의 메소드 규칙
- 구현 클래스의 @WebService annotation이 SEI를 참조하는 경우 구현 클래스에 @WebMethod annotation은 없어야 한다.
- SEI의 모든 공용 메소드는 @WebMethod annotation 설정 여부와 관계 없이 Web Service로 노출된 메소드로 간주된다.
- SEI를 참조하지 않는 구현 클래스의 경우 @WebMethod annotation이 exclude=true 값으로 지정되면 해당 메소드가 Web Service로 노출되지 않는다.
@WebParam (javax.jws.WebParam)
Web Service의 자바 메소드의 입력 파라미터와 WSDL 파일에서 파라미터를 표현하는 XML element 간의 매핑을 설정하며
Property에 대한 세부 내용은 다음 표와 같다.
| Property |
Type |
필수 |
설명 |
| name |
String |
X |
파라미터명으로 RPC style의 Web Service의 경우 파라미터를 나타내는 wsdl:part으로 매핑되고, Document style의 Web Service의 경우 파라미터를 나타내는 XML element의 로컬 네임이 됨.
기본값은 메소드의 파라미터명
|
| targetNamespace |
String |
X |
파라미터의 XML namespace로 파라미터가 XML element로 대응되는 Document style의 Web Service에서만 사용됨.
기본값은 Web Service의 targetNamespace |
| mode |
Enum |
X |
파라미터가 전달되는 방향으로 IN, OUT 혹은 INOUT 중 하나 선택.
기본값은 IN |
| header |
Boolean |
X |
true로 설정되면 파라미터를 SOAP 메시지 BODY가 아닌 SOAP 메시지 헤더로부터 가져옴.
기본값은 false |
| partName |
String |
X |
RPC 혹은 Document style의 매개변수 양식이 BARE인 경우에만 사용됨 |
@WebMethod (javax.jws.WebMethod)
Web Service 메소드로 공개되는 메소드를 설정할 때 사용하며
@WebMethod annotation은 @WebService annotation 설정이 된 클래스에서만 지원된다.
Property에 대한 세부 내용은 다음 표와 같다.
| Property |
Type |
필수 |
설명 |
| operationName |
String |
X |
공개되는 메소드 명으로 wsdl:operation으로 매핑됨. 기본값은 자바 메소드 명 |
| action |
String |
X |
메소드에 적용되는 action 속성으로 SOAPBinding의 경우 SOAP 메시지에서 SOAPAction 헤더의 값을 결정 |
| exclude |
Boolean |
X |
Web Service에서 메소드를 제외시킬지 여부 지정함. 기본값은 false |
@OneWay (javax.jws.OneWay)
입력 값은 있으나 리턴 값이 없는 단방향 메소드를 정의할 때 사용한다. @WebMethod annotation과 함께 사용되며 별도의 속성 정의가 필요없다.
@WebResult (javax.jws.WebResult)
Web Service 메소드로 공개되는 메소드의 리턴 값과 WSDL의 리턴 값을 표현하는 XML 요소 간의 매핑을 설정할 때 사용한다.
Property에 대한 세부 내용은 다음 표와 같다.
| Property |
Type |
필수 |
설명 |
| name |
String |
X |
WSDL에서 리턴 값을 나타내는 element 명
RPC style의 Web Service에서는 리턴 값을 나타내는 wsdl:part 에 매핑되며, Document style의 Web Service에서는 리턴 값을 나타내는 XML element의 로컬 |
| targetNamespace |
String |
X |
리턴값의 XML namespace로 RPC style의 Web Service 혹은 Document style의 매개변수 양식이 BARE인 Web Service에서만 사용됨.
기본값은 Web Service의 targetNamespace값 |
| header |
String |
X |
결과를 헤더에서 수행하는지 여부 지정. 기본값은 false
|
| partName |
String |
X |
RPC 혹은 Document style의 매개변수 양식이 BARE인 경우에만 사용됨 |
Samples
다음은 Movie Service의 인터페이스 클래스에 여러 가지 Annotation을 설정해 본 예제이다.
Interface Class
다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java
의 일부이다.
인터페이스 클래스 상단에 @WebService Annotation 작성은 필수 사항이다.
이외에 @WebMethod, @Oneway, @WebParam Annotation을 설정해보고 어떻게 동작하는지 살펴보도록 한다.
import javax.jws.WebService;
@WebService
public interface MovieService {
// ================= method for Annotation tests
@WebMethod(exclude = true)
public void testAnnotationMethodExclude();
@WebMethod(operationName = "testAnnotationMethodInclude")
public void testAnnotationMethod();
@Oneway
public String testAnnotationOneWay();
public String testAnnotationWebParam(
@WebParam(name = "movieAnnotationWebParam") String input);
...중략
Implementation Class는 위 Web Services 작성
에서 한 것과 동일하게 작성한다.
서버 구동
서버 구동하는 방식 3가지 중 어떠한 구동 방식을 사용해도 무방하다.
여기서는 Anyframe에서 제공하는 JaxWsServer를 이용하여 서버를 구동시키는 예제를 보여주고 있다.
다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드를 작성한 JaxWsFrontendServerFactoryAnnotationTest.java
의 일부이다.
setUp() 메소드 내에서 JaxWsServer
를 생성시킨 후, 서버의 정보로 인터페이스 클래스, 구현 클래스의 인스턴스, Web Services 주소를 설정해준다.
상위 테스트케이스 클래스인 RemotingTestCase
의 setUp() 메소드에서 Server
의 start() 메소드가 호출되면서 실제로 구동된다.
public class JaxWsFrontendServerFactoryAnnotationTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase 수행에 필요한 사전 작업 정의 ====================
// ==============================================================
public void setUp() throws Exception {
this.setServer(new JaxWsServer());
this.getServer().setServerInfo(new ServerInfo(
MovieService.class, new MovieServiceImpl(), "http://localhost:9002/Movie", false));
super.setUp();
...중략
클라이언트
클라이언트 작성 방식 2가지 중 어떠한 방식을 사용해도 무방하다.
다음은 Anyframe에서 제공하는 JaxWsClient 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 클라이언트 코드를 작성한 JaxWsFrontendServerFactoryAnnotationTest.java
의 일부이다.
testXXX() 메소드 내에서 JaxWsClient
를 생성시킨 후, 클라이언트의 정보로 인터페이스 클래스와 접근하고자 하는 Web Services 주소를 이용하여
Movie Service를 얻어낸다. Movie Service를 얻은 후에는 Movie Service에서 Web Service 메소드로 노출된 메소드를 호출하여 동작이 올바른지 테스트해본다.
이때 각각의 Annotation 설정 별로 어떻게 동작하는지 아래 TestCase 내 주석 내용을 참고하여 살펴보도록 한다.
public class JaxWsFrontendServerFactoryAnnotationTest extends RemotingTestCase {
// ==============================================================
// ====== TestCase methods ======================================
// ==============================================================
/**
* [Flow #-1] Positive Case : @WebMethod annotation을 이용하여
* 특정 method를 Web Service method로 노출되지 않도록 한다.
* @WebMethod의 속성 값 중 exclude 값을 true로 설정한다.
* (ex. @WebMethod(exclude=true) )
*/
public void testAnnotationMethodExclude() {
Client client = new JaxWsClient();
MovieService movieService =
(MovieService) client.getClient(new ClientInfo(MovieService.class,
"http://localhost:9002/Movie", false));
try {
movieService.testAnnotationMethodExclude();
fail();
} catch (Exception e) {
// Exception should be occurred.
if (!(e instanceof WebServiceException))
fail();
}
}
/**
* [Flow #-2] Positive Case : @WebMethod annotation을 이용하여
* 특정 method name을 다른 name으로 변경하여 호출가능하도록 한다.
* @WebMethod의 속성 값 중 operationName 값을
* 다른 name으로 설정한다.
* (ex. @WebMethod(operationName=
* "testAnnotationMethodInclude") )
*
* 실제 SEI에서 제공하는 method는 testAnnotationMethod 뿐이고,
* @WebMethod 속성 값 중 operationName값을
* testAnnotationMethodInclude로 설정해놓았으므로,
* Client에서 Web Service method를 호출할 때에는
* testAnnotationMethodInclude method를 갖는
* Service Interface class를 재정의해서 호출하여 사용하도록 한다.
*/
public void testAnnotationMethodInclude() {
Client client = new JaxWsClient();
anyframe.sample.movie.jaxws.extend.MovieService movieService =
(anyframe.sample.movie.jaxws.extend.MovieService) client
.getClient(new ClientInfo(
anyframe.sample.movie.jaxws.extend.MovieService.class,
"http://localhost:9002/Movie", false));
try {
movieService.testAnnotationMethodInclude();
} catch (Exception e) {
// It should not be failed.
fail();
}
}
/**
* [Flow #-3] Positive Case : @OneWay annotation을 이용하여
* 특정 method의 입력값은 있을 수 있으나 리턴 값이 없는 단방향 method를
* 정의하여 사용하도록 한다.
* @OneWay의 다른 속성값 설정은 필요 없다.
* (ex. @OneWay )
*/
public void testAnnotationOneWay() {
Client client = new JaxWsClient();
MovieService movieService =
(MovieService) client.getClient(new ClientInfo(MovieService.class,
"http://localhost:9002/Movie", false));
try {
movieService.testAnnotationOneWay().trim();
fail();
} catch (Exception e) {
// Exception should be occurred.
if (!(e instanceof NullPointerException)) {
fail();
}
}
}
/**
* [Flow #-4] Positive Case : @WebParam annotation을 이용하여 WSDL 파일에서
* 입력 파라미터를 표현하는 XML element 명을 원하는 name으로
* 변경시키도록 한다.
* (ex. public String testAnnotationWebParam(
* @WebParam(name="movieAnnotationWebParam")
* String input); )
*
* @WebParam 속성 값 중 name을 원하는 name으로 변경시키지 않는다면,
* default로 arg0으로 parameter name이 설정된다.
* @throws Exception
* throws exception which is from service
*/
public void testAnnotationWebParam() throws Exception {
Client client = new JaxWsClient();
MovieService movieService =
(MovieService) client.getClient(new ClientInfo(MovieService.class,
"http://localhost:9002/Movie", false));
assertEquals("testAnnotationWebParam", movieService.testAnnotationWebParam("input"));
TestUtilities testUtilities = new TestUtilities(getClass());
testUtilities.addDefaultNamespaces();
testUtilities.setBus(((JaxWsServer) this.getServer()).getSvrFactory().getBus());
Server s = testUtilities.getServerForAddress("http://localhost:9002/Movie");
Document wsdl = testUtilities.getWSDLDocument(s);
assertNotNull(wsdl);
testUtilities.assertValid(
"//xsd:complexType[@name='testAnnotationWebParam']"
+ "/xsd:sequence/xsd:element[@name='movieAnnotationWebParam']",
wsdl);
}
...중략
Resources
다운로드
샘플 테스트 코드를 포함하고 있는 anyframe-remotingtest-src.zip 파일을 다운받은 후, 테스트 환경 설정
을 참조하여
위에서 제시한 예제 코드를 실행해 볼 수 있다. 이때 해당 프로젝트 내의 src/test/java 소스폴더 하위의 anyframe.core.remoting.webservices.jaxws 패키지 하위의 테스트케이스 클래스를
JUnit Test Framework을 이용하여 수행시키도록 한다.
| Name
|
Download
|
| anyframe-remotingtest-src.zip |
Download
|
참고자료