tycho 를 이용해서 eclipse plugin 들을 빌드하기 위해서는 추가적으로 다음의 프로젝트가 필요하다.

- feature 프로젝트 : ex ) bizuma.ide.feature

- update site 프로젝트 : ex) bizuma.ide.update

- root 프로젝트 : ex) bizuma.ide.headless

- root 프로젝트는 packaging type 이 pom이 maven 프로젝트이다.


root 프로젝트 pom.xml 파일 작성



1.1 모듈 추가

1
2
3
4
5
<modules>
        <module>../bizmua.ide.module_a</module>
        <module>../bizmua.ide.feature</module>
        <module>../bizmua.ide.udpate</module>
    </modules>


현재 형상관리에 프로젝트가 

root

- bizuma.ide.module_a

- bizuma.ide.feature

....

와 같이 관리 되오 있다면 module 선언부에 모듈 경로는 ../ 가 없겠지만 추가하는 기존 플러그인 프로젝트로만 구성이 되어있는 상태에서 root 프로젝트를 추가하는 경우 위와 같이 경로를 잡아준다.

즉, root 프로젝트와 다른 플러그인 프로젝트는 같은 레벨에 존재 하게 될것이다.

1.2 repository 추가

1
2
3
4
5
6
7
<repositories>
        <repository>
            <id>kepler</id>
            <url>http://download.eclipse.org/releases/kepler</url>
            <layout>p2</layout>
        </repository>
    </repositories>


1.3 tycho 관련 maven 플러그인 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.eclipse.tycho</groupId>
                    <artifactId>tycho-versions-plugin</artifactId>
                    <version>${tycho.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>tycho-maven-plugin</artifactId>
                <version>${tycho.version}</version>
                <extensions>true</extensions>
            </plugin>
            <plugin>
                <groupId>org.eclipse.tycho</groupId>
                <artifactId>target-platform-configuration</artifactId>
                <version>${tycho.version}</version>
                <configuration>
                    <environments>
                        <environment>
                            <os>linux</os>
                            <ws>gtk</ws>
                            <arch>x86</arch>
                        </environment>
                        <environment>
                            <os>linux</os>
                            <ws>gtk</ws>
                            <arch>x86_64</arch>
                        </environment>
                        <environment>
                            <os>win32</os>
                            <ws>win32</ws>
                            <arch>x86</arch>
                        </environment>
                        <environment>
                            <os>win32</os>
                            <ws>win32</ws>
                            <arch>x86_64</arch>
                        </environment>
                        <environment>
                            <os>macosx</os>
                            <ws>cocoa</ws>
                            <arch>x86_64</arch>
                        </environment>
                    </environments>
                </configuration>
            </plugin>
        </plugins>
 
    </build>


각 플러그인 모듈에 pom.xml 파일 추가



root 프로젝트의 모듈에 추가되는 플러그인 프로젝트들(feature, udpate 프로젝트 포함)에 pom.xml 파일을 추가한다.

- 일반 플러그인 프로젝트 : 일반 플러그인 프로젝트의 packaging은 eclipse-plugin 이다.

1
2
3
4
5
6
7
8
<parent>
        <groupId>bizuma.ide</groupId>
        <artifactId>bizuma.ide.headless</artifactId>
        <version>1.0.0</version>
    </parent>
    
    <artifactId>bizuma.ide.module_a</artifactId>
    <packaging>eclipse-plugin</packaging>


- feature 프로젝트 : 위와 동일한 형식으로 작성하고 feature 프로젝트의 packaging은 eclipse-feature 이다.

- update 프로젝트 : 위와 동일한 형식으로 작성하고 udpate 프로젝트의 packaging은 eclipse-repository이다.


update 프로젝트 추가작업



- udpate 프로젝트를 eclipse IDE 에서 생성할경우 category.xml 파일을 생성되지 않는다. site.xml파일만 생성된다. udpate 프로젝트에 category.xml 파일을 생성해서 feature를 추가해준다.

- category.xml 파일 수정 : feature id에 버전을 0.0.0으로 수정한다. 추후 tycho 에서 수정 할지 모르겠지만 tycho를 이용해서 플러그인 버전을 변경할시에 pom.xml과 MANIFEST.MF, feature.xml 의 버전은 모두 동기화되지만 category.xml파일에 선언한 feature 버전은 업데이트 되지 않는 문제가 발생한다. 버전이 업그래이드 되지 않아서 feature를 찾을수 없는 문제가 발생하며 빌드 자채를 할수 없게된다. 버전을 0.0.0으로 변경해서 버전에 상관없이 빌드를 진행 할 수 있도록 한다.


feature 프로젝트 추가작업



- 빌드한 플러그인 모듈들을 추가한다.


eclipse plugin 빌드



root 프로젝트(bizuma.ide.headless)로 이동한다.

- 1) mvn -N versions:update-child-modules clean install

- 모듈들을 빌드 하기 전에 parent 가 빌드가 되어 있지 않을경우 먼저 parent 를 install 하기 위함이다.

- 2) mvn clean verify


위의 과정이 성공적으로 끝나면 udpate  프로젝트(bizuma.ide.update) 의 target 폴더 하위로 빌드가 되어 있음을 확인 할 수 있다.


빌드가 완료 되었다면 jenkins에 연동하는일은 기본이니 빌드 자동화를 하도록 하자. 


eclipse plugin version upgrade



릴리즈 혹은 패치를 해서 버전을 업그레이드를 해야 할 경우 eclipse plugin 을 빌드 하기 전에 pom.xml, feature.xml, MANIFEST.MF 파일들의 버전을 업그레이드 해야 한다. 이를 위해서는 root 프로젝트에서 다음의 명령으로 maven을 실행한다.

- mvn org.eclipse.tycho:tycho-versions-plugin:set-version -DnewVersion=x.x.x

성공적으로 완료될경우 pom.xml, feature.xml, MANIFEST.MF 파일들의 버전이 newVersion으로 변경되었음을 확인 할 수 있다.

version이 업그레이드 되면 다시 새로운 버전으로 eclipse build를 진행한다.





블로그 이미지

비추마

,

Java Generic Types

Java 2013. 11. 22. 12:39

참조 : http://docs.oracle.com/javase/tutorial/java/generics/types.html

Generic 을 쓰지 않는 간단한 클래스


Colored By Color Scripter

1
2
3
4
5
6
7
8
9
10
11
12
13
package generic;
 
public class Box {
    private Object object;
    public void set(Object object) {
        this.object = object;
    }
    public Object get() {
        return this.object;
    }
    
}
 


위의 Box 클래스는 non-generic 클래스이다. 이 클래스는 object를 받아들이고 리턴하므로 원하는 모든 타입을 세팅 할 수 있다 하지만 위와 같이 하면 컴파일시에 클래스가 어떻게 사용되는지에 대한 검증을 할 수 없다. Box를 사용하는 클라이언트가 set 메소드에 Integer를 사용하고 get 메소드에서 String으로 사용한다면 런타임시에 오류를 발생하게 된다.

Generic Type을 사용하도록 변경



generic class 는 다음 포맷으로 정의된다.

 Colored By Color Scripter

1
2
3
class name<T1,T2,...,Tn> {
    /* ... */
}


위의 Box 클래스를 generic type으로 변경하기 위해 코드를 다음과 같이 변경하다. 다음에 소개된 type variable 'T' 는 클래스 내부의 어느곳에서든 사용가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
package generic;
 
public class GenericBox<T> {
    private T t;
    public void set(T t) {
        this.t = t;
    }
    public T get() {
        return this.t;
    }
}
 


type variable 은 모든 클래스, 인터페이스, array 타입 등 어느 타입이라도 될수 있다. 해당 기술 기반으로 generic interface를 만드는 것도 가능하다.


Type Parameter Naming Conventions



가장 많이 사용되는 type paramenter names

  • E - element (Java Collection 에서 가장많이 사용)
  • K - key
  • N - Number
  • T - type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types


Generic Type 호출(Invoking)과 인스턴스화(Instantiating)



예제의 generic Box 클래스를 참조하기 위해서는 다음과 같이 변수를 선언한다. T를 Integer 와 같은 concrete value로 대체해야 한다.

1
Box<Integer> integerBox;


You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing a type argument.

[직역 : method invocation과 유사하다고 생각할수 있지만 메소드는 인수를 전달하는 대신 generic은 type 인수를 전달한다.]

* Type Parameter 오 Type Argument 용어 : 대부분 개발자는 type parameter와 type argument를 혼용해서 사용하지만 이 용어들은 똑같은 의미가 아니다. 코딩시에 parameterized type을 생성하기 위해 type arguments를 제공한다. 그러므로 Foo<T> 에서의 T는 type parameter이고 Foo<String> 의 String은 type argument이다. 

다른 변수 선언과 마찬가지로 위의 코드는 실제로 Box를 생성하지 않는다. 단순히 변수를 선언한 것이다. generic type 호출(invocation)은 일반적으로 parameterized type으로 알려저 있다. 이 클래스를 인스턴스와 하기 위해 new를 사용해야 한다.

 Colored By Color Scripter

1
Box<Integer> integerBox = new Box<Integer>();

The Diamond



Java SE 7 이후 부터 비어있는 type arguments를 지원한다. 

1
Box<Integer> integerBox = new Box<>();

<>는 일반적으로 Diamond라고 불린다.


Multiple Type Parameters




전에 언급했듯이 generic 클래스는 여러개의 type paramter들을 가질 수 있다. 예를 들어 Pair인터페이스를 구현하는 OrderPair generic 클래스는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package generic;
 
public class OrderPair<K, V> implements Pair<K, V> {
 
    private K key;
    private V value;
 
    public OrderPair(K key, V value) {
        this.key = key;
        this.value = value;
    }
 
    @Override
    public K getKey() {
        return this.key;
    }
 
    @Override
    public V getValue() {
        return this.value;
    }
 
}
 

다음 코드는 OrderPair 클래스를 생성하는 코드이다.

1
2
Pair<String, Integer> p1 = new OrderPair<String, Integer>("Evne", 8);
Pair<StringString> p2 = new OrderPair<StringString>("hello""World");


Parameterized Types




type parameter를 parameterized type 으로 대체 할 수 있다 .다음과 같이 사용이 가능하다.

1
2
3
4
5
6
GenericBox<Integer> genericBox = new GenericBox<Integer>();
genericBox.set(3);
Pair<String, GenericBox<Integer>> p = 
      new OrderPair<String, GenericBox<Integer>>("primes", genericBox);
p.getKey(); // primes
p.getValue(); // 3


Row Types




row type은 type argument들이 없는 제네릭 클래스 혹은 제네렉 인터페이스의 이름이다. 위의 Box 클래스를 생성할때 다음과 같이 타입이 없이 생성 할 수 있다. Box rowBox = new Box(); 이때 Box는 generic type Box<T> 의 row type이다. 그러나 non-generic 클래스 혹은 인터페이스타입은 raw 타입이 아니다.

Raw 타입들은  legacy 코드에서 많이 보여진다. 왜냐하면 수많은 API 클래스들(Collection 클스들과 같음)은 JDK 5.0 이전에는 generic 타입이 아니었기 때문이다. row 타입들을 사용할 때, Box 클래스의 get메소드는  object를 리턴할 것이다. 하위버전과의 일치성을 위해 parameterized type을 row type으로 할당하는 것은 허용된다.

1
2
Box<String> stringBox = new Box<>();
Box rowBox = stringBox; // OK


그러나 row type을 parameterized type으로 할당하는 것은 warning 이다.

1
2
Box rowBox = new Box(); // rowBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;  // warning : unchecked conversion


다음과 같이 row 타입에서 generic type 으로 정의되어 있는 generic 메소드를 호출하는 것 또한 warning이다.

1
2
3
Box<String> stringBox = new Box<>();
Box rowBox = stringBox; // OK
rowBox.set(8) // warning : unchecked invocation to set(T)


row 타입사용은 안전하지 않기 때문에 사용을 피해야 한다.


Unchecked Error Messages



언급했듯이 legacy 코드와 generic 코드가 섞여 있들때 다음과 같은 경고 메세지를 볼 수있다. 

Note : Example.java uses unchecked or unsafe operations.

Note : Recompile with -Xlint:unchecked for details.

다음과 같은 코드가 있을때 위의 에러가 발생한다.

1
2
3
4
5
6
7
8
9
10
public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }
 
    static Box createBox(){
        return new Box();
    }
}

unckecked 의 의미는 컴파일러가 type safety의 모장에 대한 모든 타입 체크에 대해 충분한 타입 정보를 가지고 있지 않다는 것이다. "unchecked" 경고는 기본으로 비활성화 되어 있다. 모든 "unchecked"에 대한 경고를 보기 위해서 컴파일시에 다음과 같은 옵션을 준다. "-Xlint:unchecked".

위의 클래스에 Xlint:unchecked 옵션을 주고 컴파일을 하면 다음과 같은 경고 메세지를 볼 수 있다.

WarningDemo.java:4: warining : [unchecked] unchecked conversion

found : Box

required: Box<java.lang.Integer>

bi = createBox();

1 warning; 




블로그 이미지

비추마

,

빈설정에서 annotation 과 component-scan의 base-package를 선언해주고 autowire="byType"(선언을 안할경우 default byType) 으로 설정하면 인스턴스명으로 특정 클래스에 Injection 을 하지 않고 타입을 찾아서 하게 된다.

예를 들어

CustomerManager 가 CustomerService에 대해 Dependency를 가지고 있을경우 다음과 같이 선언했다고 해보자.

CustomerManager.java

public class CustomerManager {

@Autowired

private CustomerService customerService;

.....

}

CustomerService.java

@Component

public class CustomerService {

}


xml 파일 설정

<bean name="customerManager"

class="com.bizuma.test.customer.CustomerManager"

autowire="byType" />


<bean name="customerXX" class="com.bizuma.test.customer. CustomerService" />


클라이언트 테스트클래스를 하나 만들어서 해당 빈을 로드하게 되면 문제없이 Injjection이 성공하게 된다. 하지만 CustomerManager 의 CustomerService인스턴스인 customerService인스턴스 명을 customerServices 라고 선언할경우 다음과 같은 오류가 발생한다.


 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.bizuma.test.customer. CustomerService] is defined: expected single matching bean but found 2: customerServices, customerXX

문제는 bean 설정파일에서 bean name을 customerXX로 해서 문제가 발생하는 것이 아니라 CustomerService의 인스터스명끝에 "s"를 하나 더 붙여서 나는 것이다. 

내가 알지 못하는 무언가가 있는것인가 아니면 byType이어도 인스턴스 명명규칙은 지켜줘야 하는것인가.

블로그 이미지

비추마

,