Spring RMI 사용해보기 위해 간단한 클래스들을 작성해 보았다..

일단, 서비스를 제공하는 측의 Service 클래스를 만들어보자..

RMISearchService.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public interface RMISearchService {
 Log logger = LogFactory.getLog(RMISearchService.class);
 
 String search(String keyword);
}

   

RMISearchServiceImpl.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class RMISearchServiceImpl implements RMISearchService {
 Log logger = LogFactory.getLog(RMISearchServiceImpl.class);

 @Override
 public String search(String keyword) {

  logger.debug("call service keyword : " + keyword);
  
  return keyword;
 }
}


단순히 keyword 받아서 keyword 리턴하는 서비스 클래스이다. 이렇게 작성을 xml 설정을 해주어야 한다.

applicationContext.xml
 
<bean id="rmiSearchService"
  class="gseshop.u2search.service.RMISearchServiceImpl">
 </bean>
 
 <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
  <property name="service" ref="rmiSearchService" />
  <property name="serviceName" value="SearchService"></property>
  <property name="serviceInterface" value="gseshop.u2search.service.RMISearchService"></property>
 </bean>


service
실제로 서비스를 구현한 클래스의 id 되고
serviceName
클라이언트측에서 호출 서비스의 이름이 된다.
serviceInterface
서비스를 구현한 클래스가 implements 하고 있는 인터페이스가 되고
인터페이스는 client측에 제공되어야 한다.

외에도 registryPort servicePort 지정해 있다.

이정도면 서비스 제공측에서는 준비가 끝났다

이제 클라이언트측을 작성해 보자..

RMICallService.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public interface RMICallService {
 Log logger = LogFactory.getLog(RMICallService.class);
 
 String call(String keyword);
}

 

   

   

RmiCallServiceImpl.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class RmiCallServiceImpl implements RMICallService {
 Log logger = LogFactory.getLog(RmiCallServiceImpl.class);
 
 RMISearchService rmiSearchService;
 
 public void setRmiSearchService(RMISearchService rmiSearchService) {
  this.rmiSearchService = rmiSearchService;
 }
 
 public String call(String keyword) {
  return rmiSearchService.search(keyword);
 }
}

 

   

   

마찬가지로 RMI 통해 원격의 서비스를 호출하고 결과를 리턴하는 간단한 서비스 객체이다.
위에 굵게 표시된 부분을 보면, RMI 통해 원격 호출을 하기 위해 서비스 제공측의 인터페이스를
가지고 있는 것을 알게 된다. 위에서 얘기한 서비스 제공측의 인터페이스가 제공되어야 하는 이유이다.

그리고 웹에서의 사용을 위해 클라이언트측 서비스를 호출 컨트롤러를 작성해보자..

   

RemoteCallController.java

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import gseshop.u2si.service.RMICallService;

@Controller
public class RemoteCallController {
 Log logger = LogFactory.getLog(RemoteCallController.class);
 
 RMICallService rmiCallService;
 
 @Autowired
 public void setRMICallService(RMICallService rmiCallService) {
  this.rmiCallService = rmiCallService;
 }
 
 @RequestMapping("/rmicall.gs")
 public String search(HttpServletRequest request, HttpServletResponse response) {
  logger.debug("controll.....");
  
  String keyWord = request.getParameter("keyword");
  String result = rmiCallService.call(keyWord);
  
  ModelAndView mv = new ModelAndView();
  mv.setViewName("result");
  
  return result;
 }
}

 


어노테이션을 사용했지만 사실 어노테이션을 사용하면 (심지어 서비스 객체도 @Service 사용하면 XML 정의가 필요 없다) 코딩은 많이 편한데... 나중에 관리 차원에서는.. 어렵지 않을까 싶기도 하다.. 일단 그래도 어노테이션으로...

그럼 controller 테스트 테스트 객체를 만들자..

RmiCallServiceImplTest.java


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

public class RmiCallServiceImplTest extends AbstractDependencyInjectionSpringContextTests {
 Log logger = LogFactory.getLog(RmiCallServiceImplTest.class);
 
 @Override
 protected String[] getConfigLocations() {
  return new String[] {"classpath:actions/action-config.xml","classpath:services/serviceContext-sample.xml"};
 }
 
 private RemoteCallController rcc;
 
 public void setRemoteCallController(RemoteCallController rcc) {
  this.rcc = rcc;
 }
 
 public void testCall() throws Exception {
  MockHttpServletRequest request = new MockHttpServletRequest();
  MockHttpServletResponse response = new MockHttpServletResponse();
  
  request.setParameter("keyword", "
나이키");
  String result = rcc.search(request, response);
  assertEquals("
나이키",result);
 }
}

 

   

AbstractDependencyInjectionSpringContextTests 상속받아서 구현해 보았다.
앞선 포스트에도 작성했지만 getConfigLocations()  메서드를 통해서 자동적으로 설정되어 있는 bean들을
바인딩 해온다

Controller
가지고 있는 Service 객체들 까지..

이제 클라이언트측 XML 설정을 해보면..

applicationContext.xml 

<bean id="rmiCall" class="gseshop.u2si.service.RmiCallServiceImpl" >
  <property name="rmiSearchService" ref="rmiSearchService1" />
 </bean>

 <bean id="rmiSearchService1"
  class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
  <property name="serviceUrl"
   value="rmi://localhost/SearchService" />
  <property name="serviceInterface"
   value="gseshop.u2si.service.RMISearchService" />
 </bean>



rmiCall
클라이언트측에서 RMI 호출을 객체이다. 이녀석이 실제로 서비스 제공측의 인터페이스를 가지고 있으므로 그녀석을 Injection 시키기 위해서 property 지정되어 있다. (rmiSearchService1)

rmiSearchService1

아래에 설정이 되어 있는데 설정을 통해서 RMI 통해 원격에 있는 RMISearchService 메서드를 호출 있게 된다.

테스트를 해보고 실제 서버를 띄워서 해보자..

~~

이참에 봐도봐도 까먹는 자바 RMI 한번 읽어봐야겠다.. 메멘토 머리통..

Posted by wychoi
,