RMI + Spring

Remoting 기능을 지원해줍니다. 스프링을 사용하면 매우 간단하게 RMI를 사용할 수 있습니다.

서비스를 제공하는 쪽

1. POJO로 서비스 인터페이스 구현체 개발
2. RmiServiceExporter 등록하기

인터페이스는 더이상 Remote 인터페이스를 확장하지 않아도 됩니다.

package chapter8.client;

public interface EchoService {

    // word를 세 번 반복한 문자열을 반환합니다.
    String say(String word);
}

구현체의 메소드들은 더이상 RemoteException을 던지지 않아도 됩니다.

package chapter8.server;

import chapter8.client.EchoService;

public class EchoServiceImpl implements EchoService {

    public String say(String word) {
        StringBuilder builder = new StringBuilder(word);
        for (int i = 0; i < 2; i++) {
            builder.append(word);
        }
        return builder.toString();
    }

}

스프링 설정 파일에 서비스 구현체와 Exporter를 설정해줍니다.

    <bean id=”echoService” class=”chapter8.server.EchoServiceImpl” />

    <bean class=”org.springframework.remoting.rmi.RmiServiceExporter”>
        <property name=”service” ref=”echoService” />
        <property name=”serviceName” value=”EchoService” />
        <property name=”serviceInterface”
            value=”chapter8.client.EchoService” />
    </bean>

RmiServiceExporter가 기본으로 로컬에 1099 포트에 RMI 레지스트리가 있는지 확인하고 있으면 서비스를 등록하고, 없으면 RMI 레지스트리를 새로 만들어 실행한 다음 서비스를 추가합니다. 이 모든일을 알아서 해주기 때문에 개발자는 할 일이 없습니다.(하고 싶다면, 레지스트리 위치 설정과 포트 설정을 할 수 있겠죠. 그 때는 registryHost 속성과 registryPort 속성에 원하는 값을 설정해 주면 됩니다.)

서비스를 사용하는 쪽

1. 마치 서비스가 로컬에 존재하는 듯이 코딩합니다.
2. 스프링 설정 파일에서 RmiProxyFactoryBean을 사용하여 원하는 서비스를 bean으로 설정합니다.

테스트 코드입니다.

package chapter8;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import chapter8.client.Keesun;

public class KeesunTest extends AbstractDependencyInjectionSpringContextTests {

    @Override
    protected String[] getConfigLocations() {
        return new String[] { “chapter8/client/springContext.xml” };
    }

    private Keesun keesun;

    public void setKeesun(Keesun keesun) {
        this.keesun = keesun;
    }

    public void testDI() throws Exception {
        assertNotNull(keesun);
    }

    public void testEcho() throws Exception {
        String echoResult = keesun.yaahoo(“Spring”);
        assertEquals(“SpringSpringSpring”, echoResult);
    }
}

Keesun 이란 클래스가 EchoService를 사용하고 있습니다.

package chapter8.client;

public class Keesun {

    private EchoService echoService;

    public void setEchoService(EchoService echoService) {
        this.echoService = echoService;
    }

    public String yaahoo(String word){
        return echoService.say(word);
    }
}

마지막으로 스프링 설정 파일에 Keesun과 EchoService를 bean으로 등록해 줍니다.

    <bean id=”keesun” class=”chapter8.client.Keesun” />

    <bean id=”echoService”
        class=”org.springframework.remoting.rmi.RmiProxyFactoryBean”>
        <property name=”serviceUrl”
            value=”rmi://localhost/EchoService” />
        <property name=”serviceInterface”
            value=”chapter8.client.EchoService” />
    </bean>

확인하기

1. Server 실행하기
2. Test 코드(Client) 실행하기.

레지스트리 서버를 동작시키려면 서비스를 제공하는 측 스프링 설정 파일을 읽어들이면서 Exporter bean을 생성하면되겠죠.

package chapter8;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EchoServiceServer {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“chapter8/server/springContext.xml”);
    }
}

다음은 위에서 작성했던 KeesunTest를 실행해 줍니다.

사용자 삽입 이미지

Profile

Maven에 있는 Profile의 주 목적은 서로 다른 빌드 환경간의 portability입니다. 개발 환경, 테스트 환경, 성능 테스트 환경, 클라이언트 환경 등 상상할 수 있는 모든 환경에 단일 프로젝트를 이식할 수 있도록 합니다.

Portability 종류

Non-Portability

이런 프로젝트는 오직 특정한 환경에서만 빌드를 할 수 있습니다. 프로젝트를 다른 환경으로 이식할 계획이 없다면 그냥 이렇게 사용해도 상관없습니다.

Environmental Protability

테스트 환경에서는 테스트 데이터베에스를 참조하고, 배고 환경에서는 배포용 데이터베이스를 참조할 수 있는 프로젝트입니다. 하지만 프로파일이 만들어져이지 않은 환경으로 이식한다면, 해당 프로젝트는 동작하지 않을 것입니다. 따라서 오직 정의되어 있는 환경으로만 이식할 수 있습니다.

In-House Portability

특정한 도구나 연결 접근이 필요한 프로젝트를 말합니다.

Wide Portability

Maven에서는 wide portability 프로젝트 소스를 누구나 다운받을 수 있습니다. 프로젝트를 빌드하려는 사람이 어떠한 추가작업도 필요로하지 않을때 Wide Portablilty 프롤젝트라고 합니다. 예를 들어, MySQL을 사용한다면, 해당 프로젝트를 빌드 할 때 MySQL이 없는 사람은 설치를 해야합니다. 이런 프로젝트는 Wide Protability를 가졌다고 할 수 없습니다. 반면에, HSQLDB를 사용한다면, hsql.jar 종속성을 추가하면 되기떄문에 widely protable합니다.

가능하면 프로젝트를 최대한 이식성이 좋도록하는 것이 목적입니다. 이식성이 넓어질 수록 빌드 작업을 하는 사람의 수고를 덜 수 있습니다. Maven의 Profile은 특정 환경의 기본 값이 설정 값들을 대체할 수 있습니다. Maven을 사용하면, Non-portable 프로젝트를 Environmentally portable 프로젝트로 변경시킬 수 있습니다.

POM Profiles

project 엘리먼트 내부에 profiles 엘리먼트 안에 모든 가용한 설정들을 합니다. 그 안에서 설정할 수 있는 엘리먼트들은 project 엘리먼트 레벨에서 사용할 수 있는 것들과 동일합니다.

<project>
  …
  <profiles>
    <profile>
      …
      <reporting>…</reporting>
      <modules>…</modules>
      <dependencies>…</dependencies>
      <dependencyManagement>…</dependencyManagement>
      <distributionManagement>…</distributionManagement>
      <repositories>…</repositories>
      <pluginRepositories>…</pluginRepositories>
      <properties>…</properties>
    </profile>
  </profiles>
</project>

Activation

activation 엘리먼트는 오직 profile 엘리먼트 내부에서만 사용할 수 있으며, 이 엘리먼트에 정의한 환경과 실행 환경이 일치하면 profile에 설정한 값들이 project에 설정한 값들을 대체합니다.

<project>
  …
  <profiles>
    <profile>
      <id>dev</id>
      <activation>
        <activeByDefault>false</activeByDefault>
        <jdk>1.5</jdk>
        <os>
          <name>Windows XP</name>
          <family>Windows</family>
          <arch>x86</arch>
          <version>5.1.2600</version>
        </os>
        <property>
          <name>mavenVersion</name>
          <value>2.0.5</value>
        </property>
        <file>
          <exists>file2.properties</exists>
          <missing>file1.properties</missing>
        </file>
      </activation>
      …
    </profile>
  </profiles>
</project>

Build

profile의 build 엘리먼트는 POM의 build 엘리먼트의 서브셋에 해당하는 정보를 가지고 있습니다.

<project>
  …
  <profiles>
    <profile>
      <build>
        <defaultGoal>install</defaultGoal>
        <directory>${basedir}/target</directory>
        <finalName>${artifactId}-${version}</finalName>
        <filters>
          <filter>filters/filter1.properties</filter>
        </filters>
        <resources>
          <resource>
            <targetPath>META-INF/plexus</targetPath>
            <filtering>false</filtering>
            <directory>${basedir}/src/main/plexus</directory>
            <includes>
              <include>configuration.xml</include>
            </includes>
            <excludes>
              <exclude>**/*.properties</exclude>
            </excludes>
          </resource>
        </resources>
        <testResources>
          <testResource>…</testResource>
        </testResources>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.1</version>
            <extensions>false</extensions>
            <inherited>true</inherited>
            <configuration>
              <sourceRoot>${project.build.directory}/generated-sources</sourceRoot>
            </configuration>
            <dependencies>
              <dependency>
                <groupId>ant</groupId>
                <artifactId>ant-optional</artifactId>
                <version>1.5.2</version>
              </dependency>
            </dependencies>
            <executions>
              <execution>
                <id>echodir</id>
                <goals>
                  <goal>run</goal>
                </goals>
                <phase>verify</phase>
                <inherited>false</inherited>
                <configuration>
                  <tasks>
                    <echo>Build Dir: ${project.build.directory}</echo>
                  </tasks>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
        <pluginManagement>
          <plugins>…</plugins>
        </pluginManagement>
      </build>
    </profile>
  </profiles>
</project>

External Profiles

proflie들을 POM에서 빼내고 싶을 수 있습니다. 이럴 때는 \${basedir}에 profilesxml을 생성하고 그 안에 profiles 엘리먼트를 넣어주면 됩니다.

Settings Profiles

settings.xml에서도 profile을 설정할 수 있는데, 이 것은 project의 profile과 기능은 같으나, project의 profile은 여러 시스템들 중에 특정한 설정 값을 overriding 할 때 사용하고, settings의 profile은 모든 시스템 통채를 대상으로 합니다.

activeProfiles 엘리먼트를 사용하여 모든 빌드에서 자동으로 동작시킬 profile을 지정할 수 있습니다. 물론 이때의 profile은 project의 profile이 아니라 settings의 profile입니다.

<settings>
  …
  <activeProfiles>
    <activeProfile>dev</activeProfile>
  </activeProfiles>
</settings>

어렵네요. -_-;;

If You Want Me

요즘 제가 푹 빠져버린 곡입니다. 영화 Once OST에 포함되어 있는 노래로 매우 애절한 것이 이 곡의 특징입니다. 우리나라 노래로 치면 ‘사미인곡’이나 ‘별미인곡’처럼 처량한 가사를 가지고 있습니다. 물론 저 곡들은 임금을 향한 마음을 쓴 것이지만 말이죠;;

  • mp3으로 듣기

ek8.mp3

  • 동영상으로 보기

영화도 재밌었습니다. 영화는 극장에서 얼마전까지 했었는데 요즘도 하는진 모르겠네요. 내용이 재밌는 것은 없고, 노래 부르는 거 구경하는 재미랄까요. 노래 부르는 장면이 90%인 영화입니다.

유투브 동영상 댓글 중에 이런 댓이 있는데..

her voice touches my soul. i get goose bumps every time.

미투 던지고 싶습니다. goose bumps 는 소름 돋는다는 표현입니다.

Archetype

Archetype은 한국어로 원형(prototype), 전형과 같은 뜻이라고 네이버 사전이 알려줬습니다. Maven에서도 그와 비슷하게 프로젝트의 기본 레이아웃 구조를 생성할 때 사용할 템플릿으로 사용하고 있습니다. RoR의 scaffold랑 비슷한 것 같네요.

archetype:create Goal을 실행하면 다음과 같은 구조의 기본 Archetype을 만들어 줍니다. 이것을 quickstart라고 하며, Hello World 를 출력하는 자바 코드를 가지고 있습니다.

mvn archetype:create -DgroupId=com.mycompany -DartifactId=my-proj

my-proj
|– pom.xml
`– src
    |– main
    |   `– java
    |       `– com
    |           `– mycompany
    |               `– App.java
    `– test
        `– java
            `– com
                `– mycompany
                    `– AppTest.java

이런 프로젝트 구조를 만들어 낸 기반은 META-INF/maven/archetype.xml 리소스 정의 파일과 src/main/resources/archetype-resources 디렉터리 밑에 위치한 Archetype 리소스 파일들 입니다.

maven-quickstart-archetype
|– pom.xml
`– src
    `– main
        `– resources
            |– META-INF
            |   `– maven
            |       `– archetype.xml
            `– archetype-resources
                |– pom.xml
                `– src
                    |– main
                    |   `– java
                    |       `– App.java
                    `– test
                        `– java
                            `– AppTest.java

Maven에서 가용한 Archetype들은 http://repo1.maven.org/maven2/org/apache/maven/archetypes/ 에서 확인할 수 있습니다.
사용자 삽입 이미지위에있는 Atchetype 중에서 맘에 드는 것이 없거나, 자신이 자주 사용하는 프로젝트 템플릿이 있다면 그것을 mvn install로 등록하여 사용할 수도 있습니다. 자세한 내용은 http://sonatype.com/book/archetypes.html
위 글의 후반부에는 사용자 정의 archetype 구성에 대하 나왔습니다.