<div class="warning"> 이 문서는 eclipse를 사용한 방법입니다.

NetBeans 6.0을 이용하는 방법을 보고자 할때는 An Introduction to Building RESTful Web Services in Java Using NetBeans 6.0를 참조하십시오. </div>

<div class="warning"> 환경정보는 다음과 같다.

</div>

eclipse을 사용하여 자바로 RESTful 웹서비스 빌드하기#

REST 기반의 웹서비스는 SOAP기반의 웹서비스보다 좀더 간단하다. 그렇지 않은가.? 그런데 자바로 REST 기반의 웹서비스를 생성하는 것은 왜 어려운가.? 툴을 사용하여 REST기반의 웹서비스는 쉽지 않지만 SOAP기반의 웹서비스는 수초안에 만들수는 있다. 이 글이 도움이 될것이다.

JSR 311: JAX-RS: The Java API for RESTful Web Services 는 이렇게 RESTful 기반의 웹서비스를 만드는 절차를 단순화하기 위해 만들어졌다. Marc Hadley 와 함께 공동리더인 Paul Sandozpresentation으로 JAX-RS를 소개했다. 서블릿 API와 제안된 JAX-RS 어노테이션을 사용하여 작업하는 것을 비교했다.

Sun Web Developer Pack튜토리얼과 함께 JAX-RS의 구현체를 포함한다.

셋팅하기#

<div class="information"> [#1] 톰캣의 경우 C:\was\apache-tomcat-6.0.13에 설치하였고 SWDP또한 디폴트 위치인 C:\Sun\swdp 에 설치하였다. 톰캣과 SWDP를 통합하기 위해서는 C:\Sun\swdp\bin 로 이동해서 다음과 같은 명령을 실행해야 한다.

set tomcat=C:/was/apache-tomcat-6.0.13
set swdp=C:/Sun/swdp
ant -f setup-tomcat.xml -Dcatalina.home=%tomcat% -Dswdp.home=%swdp%

다른 was와의 통합을 위해서는 여기를 참조하길 바란다. </div>

resthello 애플리케이션 만들기#

1. eclipse를 실행한 뒤 resthello 라는 이름의 Dynamic Web Project 생성한다.

1.png

2.png

2. SWDP가 설치되었는지 확인하기 위해 Libraries에서 Apache Tomcat v6.0에서 관련 jar 파일이 존재하는지 확인한다.

6.png ............... 7.png

rest 라이브러리가 보이지 않는다면 톰캣과 SWDP를 통합하는 과정[1]이 정상적으로 이루어지지 않은 것이다. 다시 확인하도록 한다.

3. Hello 라는 새로운 자바 클래스를 생성하라. rest를 사용한다면 Hello는 URI에 의해 구분되는 "resource class(자원 클래스)"가 될것이다.

4.png

5.png

4. 자원을 URI에 결합시키기 위해 다음처럼 UriTemplate 어노테이션을 사용한다. @UriTemplate(value = "/hello") 와 같은 형식으로 표시해도 된다. 그리고나서 요청을 다루기 위한 메소드를 정의하고 HTTP 요청 타입을 표시하기 위해 HttpMethod 어노테이션을 사용한다. 여기서 사용되는 HTTP 요청 타입은 GET, POST, PUT 또는 DELETE가 있다. 마지막으로, 클라이언트에 반환되는 타입이 무엇인지 지정하기 위해 ProduceMime 어노테이션을 사용하라. 그러면 소스코드가 다음과 같은 형태가 될것이다.

package kr.or.openframework;

import com.sun.ws.rest.api.HttpMethod;
import com.sun.ws.rest.api.ProduceMime;
import com.sun.ws.rest.api.UriTemplate;

@UriTemplate("/hello")
public class Hello {
  @HttpMethod("GET")
  @ProduceMime("text/plain")
  public String sayHello() {
    return new String("Hello there.");
  }
}

여기서 사용되는 어노테이션 관련 클래스는 restbeans-api.jar에 포함되어 있고 패키지명은 com.sun.ws.rest.api 아래에 있다.

hello 애플리케이션 빌드하기#

1. 애플리케이션을 디플로이하기 전에 자원 클래스를 로드할 클래스를 생성할 필요가 있다. JAX-RS는 이 클래스를 생성할 어노테이션 처리자를 가진다. 그리고 eclipse는 어노테이션 처리자를 호출할 필요가 있는 Ant 태스크를 가진다. Ant작업을 위해 build.xml파일을 생성한다. 그리고 다음과 같은 내용으로 파일을 채운다. 여기서 rest를 위한 클래스는 restsrc 디렉토리밑에 생성된다. 여기서 web.xml에 등록해야 할 web.xml파일또한 같은 위치에 생성된다. 필자의 환경과 같은 환경으로 간다면 톰캣 설치 디렉토리 경로정도만 바꾸면 된다.

<?xml version="1.0" encoding="UTF-8"?>
<project name="resthello" default="generate-rest" basedir=".">
  <property name="source" value="src" />
  <!-- 자동 생성되는 REST관련 파일 위치 -->
  <property name="restsrc" value="restsrc" />
  <!-- 톰캣 디렉토리 -->
  <property name="tomcat_home" value="C:/was/apache-tomcat-6.0.13" />

  <taskdef name="restapt" classname="com.sun.ws.rest.tools.ant.RestBeansProcessorTask">
    <classpath>
      <path location="${tomcat_home}/lib/restbeans-impl.jar" />
    </classpath>
  </taskdef>
  <target name="clean">
    <delete dir="${restsrc}/rest-gen" />
  </target>
  <target name="generate-rest" depends="clean">
    <mkdir dir="${restsrc}/rest-gen" />
    <restapt destdir="${restsrc}/rest-gen" fork="true" nocompile="true" sourcePath="${source}" sourcedestdir="${restsrc}/rest-gen" xEndorsed="true">
      <classpath>
        <path location="${tomcat_home}/lib/jsr173_api.jar" />
        <path location="${tomcat_home}/lib/restbeans-api.jar" />
        <path location="${tomcat_home}/lib/restbeans-impl.jar" />
        <path location="${tomcat_home}/lib/jaxb-xjc.jar" />
        <path location="${tomcat_home}/lib/jaxws-api.jar" />
        <path location="${tomcat_home}/lib/annotations-api.jar" />
        <path location="${tomcat_home}/lib/wadl2java.jar" />
      </classpath>
      <option key="restbeansdestdir" value="." />
      <option key="restbeanpkg" value="kr.or.openframework.rest.resources" />
      <!--
      <option key="noservlet" />
      -->
      <source dir="${source}">
        <include name="**/*.java" />
      </source>
    </restapt>
  </target>
</project>

2. Ant 빌드를 실행한다. 여기서 필자는 실행시 eclipse가 정상적으로 처리하지 못하고 강제로 죽는 현상을 계속 경험했다. 그럴경우 Run As 로 Ant실행 설정창을 띄운 뒤 JRE탭에서 Runtime JRE를 Run in the same JRE as the workspace를 선택한뒤 실행한다. 그러면 다음과 같은 실행결과가 남을것이다.

8.png

9.png

여기서 web.xml 파일에 에러표시가 나는것은 기본적으로 web-app 버전이 2.4로 생성되는데 반해 톰캣은 2.5로 생성하여 버전이 맞지 않아 발생하는 것이다. 하지만 여기서 restsrc\WEB-INF\web.xml 파일을 사용하지 않고 내용만을 가져올것이기 때문에 무시하도록 한다. restsrc\WEB-INF\web.xml파일의 내용은 다음과 같다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>RESTBeans Application</servlet-name>
    <servlet-class>com.sun.ws.rest.impl.container.servlet.ServletAdaptor</servlet-class>
    <init-param>
      <param-name>resourcebean</param-name>
      <param-value>kr.or.openframework.rest.resources.RESTBeansResources</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTBeans Application</servlet-name>
    <url-pattern>/restbean/*</url-pattern>
  </servlet-mapping>
</web-app>

여기서 servlet과 servlet-mapping 요소를 복사해서 WebContent/WEB-INF/web.xml 파일에 복사해 넣는다. WebContent/WEB-INF/web.xml 파일내용은 다음과 같이 될것이다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <servlet>
    <servlet-name>RESTBeans Application</servlet-name>
    <servlet-class>
      com.sun.ws.rest.impl.container.servlet.ServletAdaptor
    </servlet-class>
    <init-param>
      <param-name>resourcebean</param-name>
      <param-value>
        kr.or.openframework.rest.resources.RESTBeansResources
      </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTBeans Application</servlet-name>
    <url-pattern>/restbean/*</url-pattern>
  </servlet-mapping>
  <display-name>resthello</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

여기서 주의할 점은 자동 생성된 rest관련 자바소스도 정상적으로 컴파일이 되어서 WEB-INF/classes 밑에 들어가야 하기 때문에 eclipse에서 Java Build Path에 등록을 해주어야 한다. 하지만 함께 생성된 WEB-INF/web.xml 파일은 컴파일 경로에 들어가지 말아야 하기 때문에 Excluded 에 추가해주어야 한다.

10.png

애플리케이션 실행하기#

1. 프로젝트를 선택하고 Run As에서 Run On Server를 선택하여 해당 프로젝트를 톰캣에서 실행하도록 한다.

11.png

작동하는 방법#

작동하는 방법에 대해서는 아래의 참고자료에서 상세히 설명된다. RESTful Web Services tutorialGetting Started With RESTful Web Services Development가 특히 더 도움이 된다고 생각한다. 어쨌든 요약해보면 애플리케이션의 흐름이 다음처럼 작동한다고 볼 수 있다.

ServletAdapter => RESTBeansResources => Hello

ServletAdapter 는 JAX-RS 런타임이 제공하고 생성된 RESTBeansResources 클래스를 로드한다. 그리고 애플리케이션 Hello의 REST 자원을 순서대로 제공한다. URL인 /hello/restbean/hello는 다음처럼 분리해서 볼 수 있다.

/resthello - web.xml에 설정된 컨텍스트 root
/restbean - web.xml에 설정된 ServletAdapter 에 대한 매핑
/hello - Hello 자원 자체에 @UriTemplate 어노테이션을 사용하여 설정된 Hello 자원에 대한 매핑

웹브라우저에서 http://localhost:8080/resthello/restbean/hello 접속해보면 Hello there. 라는 문자열을 찍어주면 정상적으로 처리가 된것이다. 하지만 실제 애플리케이션에서 이렇게 아무값도 받지 않고 단순히 값만 찍어주는 형태의 애플리케이션은 거의 존재하지 않는다. 사용자가 값을 입력할때 그 값을 기반으로 문자열을 찍어주도록 변경해보자.

아까 만들었던 Hello.java 를 다음처럼 변경해보자.

package kr.or.openframework;

import com.sun.ws.rest.api.HttpMethod;
import com.sun.ws.rest.api.ProduceMime;
import com.sun.ws.rest.api.UriParam;
import com.sun.ws.rest.api.UriTemplate;

@UriTemplate("/hello/{id}")
public class Hello {
  @HttpMethod("GET")
  @ProduceMime("text/plain")
  public String sayHello(@UriParam("id"String msg) {
    return new String("Hello there."+msg);
  }
}

그리고 나서 다시 Ant빌드 파일을 빌드하고 다시 실행해보면 다음과 같은 결과를 볼수 있다.

12.png

참고자료#

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
png
1.png 18.2 kB 1 22-Jul-2007 13:58 DongGukLee
png
10.png 33.9 kB 1 22-Jul-2007 13:59 DongGukLee
png
11.png 54.1 kB 1 22-Jul-2007 13:59 DongGukLee
png
12.png 40.9 kB 1 22-Jul-2007 14:12 DongGukLee
png
2.png 28.4 kB 1 22-Jul-2007 13:58 DongGukLee
png
3.png 7.1 kB 1 22-Jul-2007 13:58 DongGukLee
png
4.png 13.2 kB 1 22-Jul-2007 13:59 DongGukLee
png
5.png 27.1 kB 1 22-Jul-2007 13:59 DongGukLee
png
6.png 9.9 kB 1 22-Jul-2007 13:59 DongGukLee
png
7.png 2.6 kB 3 22-Jul-2007 14:02 DongGukLee
png
8.png 18.0 kB 1 22-Jul-2007 13:59 DongGukLee
png
9.png 20.2 kB 1 22-Jul-2007 13:59 DongGukLee
« This page (revision-3) was last changed on 22-Jul-2007 14:12 by DongGukLee