2010년 4월 4일 일요일

restful 서비스 클라이언트

JAX-RS는 RESTful 클라이언트에 대한 표준적인 방식을 제공하지 않는다.
CXF 프레임워크는 클라이언트 생성을 위한 두 가지 접근방식을 제공한다.
두 방식 모두 Spring을 이용하여 설정할 수 있다.

Proxy-based API


Proxy-based API는 RESTful서비스를 구현한 인터페이스가 있는 경우에 사용할 수 있다.
Proxy는 HTTP 요청을 생성하는 데 필요한 정보를 서비스 인터페이스를 이용한다.
org.apache.cxf.jaxrs.client.JAXRSClientFactory 클래스를 사용하며, proxy를 생성하기 위해 RESTful서비스 인터페이스를 입력값으로 전달해야 한다.
proxy가 생성되고 나면 RESTful서비스의 모든 메서드가 proxy에도 동일하게 존재하며, proxy의 메서드를 호출하면 RESTful 서비스에 메서드가 원격으로 호출된다.

HTTP centric clients


HTTP centric clients는 RESTful 서비스를 호출하기 위해 org.apache.cxf.jaxrs.client.WebClient 인스턴스를 이용한다. HTTP centric clients는 RESTful서비스 인터페이스를 알지 못해도 RESTful 서비스를 호출할 수 있지만 메서드의 I/O로 전달되는 도메인객체(model, VO)에 대한 정보는 알고 있어야 한다. 도메인 객체를 알지 못해도 처리는 가능하지만 XML을 파싱해야 하는 경우가 발생한다.

아래의 소스 파일에 WebClient를 이용하는 GET, POST method 예제와 JAXRSClientFactory를 이용하는 예제가 포함되어 있다.
눈여겨 볼 부분은 Proxy-based API의 서비스 인터페이스는 context path와 web.xml에서 설정되는 servlet url mapping 정보를 알 수 없기 때문에 예제에서와 같이 host, port 뿐만 아니라 추가 경로(/amfws/restful)에 대한 정보도 설정해 주어야 한다.
또한 WebClient는 매 요청마다 새롭게 만들어져야 한다. 그렇지 않으면 에러가 발생한다.

또 한가지 주의할 점은 RESTful 서비스의 리턴타입이 XML이 아닌 경우(예, String, boolean, int 등) JAXRSClientFactory의 proxy를 이용하는 경우에 RESTful 서비스의 메서드의 Produces에 반드시 text/plain으로 설정되어 있어야 한다. Produces가 설정되지 않은 경우에는 HTTP Status 406 에러가 발생한다.

RESTful client 예제
package com.archnal.amf.amfws.rs.client;

import java.io.IOException;
import java.io.InputStream;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.apache.cxf.jaxrs.client.WebClient;

import com.archnal.amf.amfws.biz.SampleUserBizService;
import com.archnal.amf.amfws.biz.SampleUserBizServiceImpl;
import com.archnal.amf.amfws.model.SampleUser;
import com.archnal.amf.amfws.rs.SampleUserRs;
import com.archnal.amf.amfws.rs.SampleUserRsImpl;

public class SampleUserRsClient {

public static void main(String[] args) throws Exception {
testProxyApi();

testWebClient();
}

private static void testProxyApi() throws Exception {
long userNo = 1L;
SampleUserRs proxy = null;
proxy = JAXRSClientFactory.create("http://localhost:8080/amfws/restful", SampleUserRs.class);
SampleUser user1 = proxy.getUser(userNo);
System.out.println("user1: " + user1.getName());

SampleUser newUser = createNewSampleUser();
proxy.register(newUser);
}

private static SampleUser createNewSampleUser() {
SampleUser newUser = new SampleUser();
newUser.setUserNo(System.currentTimeMillis());
newUser.setLoginId(System.currentTimeMillis() + "");
newUser.setName("new user");

return newUser;
}

private static void testWebClient() throws Exception {
WebClient webclient = WebClient.create("http://localhost:8080");
long userNo = 1L;
String path = null;

path = "/amfws/restful/sample/user/getUser/" + userNo;


//    SampleUser sampleUser = webclient.path(path).accept("application/xml").get(SampleUser.class);
SampleUser sampleUser = webclient.path(path).accept(MediaType.APPLICATION_XML_TYPE).get(SampleUser.class);
System.out.println(sampleUser.getName());

webclient = WebClient.create("http://localhost:8080");

path = "/amfws/restful/sample/user/register";
SampleUser newUser = createNewSampleUser();
Response response = webclient.path(path).accept("application/xml").post(newUser);
Object entity = response.getEntity();
System.out.println("entity: " + entity);
InputStream in = null;
try {
in = (InputStream) entity;
byte[] buf = new byte[in.available()];
in.read(buf);
System.out.println("content: '" + new String(buf) + "'");
} catch(IOException ex) {
ex.printStackTrace();
} finally {
if(in != null) {
in.close();
}
}

webclient = WebClient.create("http://localhost:8080");
//String value = webclient.path(path).accept("application/xml").post(newUser, String.class);
boolean value = webclient.path(path).post(newUser, Boolean.class);
System.out.println("value: " + value);
}
}



RESTful 인터페이스 예제
package com.archnal.amf.amfws.rs;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import com.archnal.amf.amfws.model.SampleUser;
@javax.ws.rs.Path("/sample/user")
@javax.ws.rs.Produces({"application/json", "application/xml", "text/plain"})

public interface SampleUserRs {
@POST
@Path("/register")
@Consumes({"application/xml"})
@Produces("text/plain")
boolean register(SampleUser user);

@javax.ws.rs.GET
@javax.ws.rs.Path("/getUser/{userNo}")
@Produces({"application/xml"})
SampleUser getUser(@PathParam("userNo") long userNo);


javax.ws.rs.core.Response login(String loginId, String loginPassword);
List searchByName(String userName);


SampleUser getUser(String loginId);
}

댓글 없음:

댓글 쓰기