blazeDS RemoteClass
하려는것
1) Flex 에서 RemoteObject 를 이용해 blazeds 서버의 메서드를 호출하고,
2) 서버는 RemoteClass 로 등록되어있는 객체를 반환하면
3) Flex 가 이를 받아 View 에서 볼 수 있도록 바인딩 한다.
예제1) 간단한 모델
Java
1: public class Config
2: {
3: private String text;
4:
5: public String getText()
6: {
7: return text;
8: }
9:
10: public void setText(s:String)
11: {
12: text = s;
13: }
14: }
1: package com.myapp.model.config
2: {
3: [RemoteClass(alias="com.myapp.model.Config")]
4:
5: [Bindable]
6: public class Config
7: {
8: private var _text:String;
9:
10: public function get text():String
11: {
12: return _text;
13: }
14:
15: public function set text(s:String):void
16: {
17: _text = s;
18: }
19: }
20: }
예제1은 특별히 설명할게 없다. 저렇게 하면 알아서 리모트 클래스로 처리되어 속성을 참조 할 수 있다.
플렉스에서 리모트 클래스로 등록한 Config객체는 text 가 속성으로 되어 있는데
RemoteObject 로 가져올때 자바객체의 getText(), setText() 메서드를 알아서 불러와 text에 집어 넣어준다.
예제2) 복잡한 모델
Java
1: package com.myapp.model;
2:
3: import com.myapp.model.BaseDataModel;
4:
5: public class Config extends BaseDataModel
6: {
7: private int seq;
8:
9: public int getSeq()
10: {
11: return seq;
12: }
13:
14: public void setSeq(int i)
15: {
16: this.seq = i;
17: }
18:
19: public int getInterval()
20: {
21: return getInt("interval", 60);
22: }
23:
24: public void setInterval(int i)
25: {
26: setInt("interval", i);
27: }
28: }
1: import java.util.HashMap;
2:
3: public abstract class BaseDataModel
4: {
5: /**
6: * "key1=value1&key2=value2& ... " 와 같은 문자열을 key&value 쌍으로 저장하고 있는 멤버
7: */
8: private HashMap<String, String> dataHashMap = new HashMap<String, String>();
9:
10: /**
11: * @return
12: * dataHashMap의 요소를 "key=value& ... " 형식 문자열로 만들어 반환한다.
13: * 이 메서드는 오버라이드 할 수 없다.
14: */
15: public final String getData()
16: {
17: return DataUtil.getDataString(dataHashMap);
18: }
19:
20: /**
21: * "key=value& ... " 형식 문자열을 파싱하여 dataHashMap 에 저장한다.
22: * 문자열 전달인자는 파싱되기 전 멤버변수인 data 에 저장된다.
23: * 이 메서드는 오버라이드 할 수 없다.
24: * @param data
25: */
26: public final void setData(String data)
27: {
28: dataHashMap = DataUtil.getDataHashMap(data);
29: }
30:
31: /**
32: * int 타입의 값을 문자열로 변환해 dataHashMap 에 저장한다.
33: * @param key
34: * @param value
35: */
36: protected void setInt(String key, int value)
37: {
38: dataHashMap.put(key, Integer.toString(value));
39: }
40:
41: /**
42: * dataHashMap 에서 key 에 해당하는 값을 참조해 int 형으로 반환한다.
43: * 참조한 값이 null 이면 0을 반환한다.
44: * @param key
45: * @return
46: */
47: protected int getInt(String key)
48: {
49: return Integer.getInteger(dataHashMap.get(key), 0);
50: }
51: }
Flex
1: package com.myapp.model
2: {
3: [RemoteClass(alias="com.myapp.model.Config")]
4:
5: [Bindable]
6: public class Config
7: {
8: private var _seq:int;
9: private var _interval:int;
10: private var _data:String;
11:
12: // ---------------------------------------------------
13: // Properties
14: // ---------------------------------------------------
15: public function get seq():int
16: {
17: return _seq;
18: }
19:
20: public function set seq(i:int):void
21: {
22: _seq = i;
23: }
24:
25: public function get interval():int
26: {
27: return _interval;
28: }
29:
30: public function set interval(i:int):void
31: {
32: _interval = i;
33: }
34:
35: public function get data():String
36: {
37: return _data;
38: }
39:
40: public function set data(s:String):void
41: {
42: _data = s;
43: }
44: }
45: }
예제2의 경우를 동작시키기 위해 한 12시간은 쓴거 같다. 플렉스의 객체는 예제1과 동일한 형식이지만 속성이 2개 더 있다. 새로 생긴 2개의 속성은 자바단에서 구현이 예제 1과 다르다.
자바 객체는 다음 특징을 가진다.
1) BaseDataModel을 상속
2) seq는 예제1의 경우와 동일하며 public getter & setter 메서드가 seq 라는 private 변수를 단순 참조하는 전형적인 형태.
3) data 는 부모객체의 구현이며 public getter & setter 메서드가 dataHashMap 이라는 private 변수에 복잡한 연산을 통해 참조하는 형태
4) interval 은 public getter & setter 메서드가 부모객체의 메서드를 이용해 dataHashMap 을 참조하는 형태
이러한 상황을 구현하면서 매핑할 자바 클래스가 부모가 있는 클래스라고 해서 Flex 의 클래스 상속구조가 동일 할 필요는 없다는 사실을 확인했고, interval 과 data 와 같이 전형적인 구조가 아닌 속성을 매핑할때도 어렵게 생각 할 필요가 없었다.
시간을 12시간이나 소모시킨 주범은 다름아닌 데이터형이었다. 자바단에서 getInterval 의 리턴타입이 처음엔 Integer 로 되어 있었는데, 자바단에선 틀림없이 올바른 값이 저장되어 있었지만 플렉스로 넘어오면 무조건 0으로 바뀌는 것이다. 처음엔 리모트 클래스가 이런 유형, 즉, 상속된 객체라던지, getter & setter 에 해당하는 private 변수가 없는 경우를 지원하지 않는 줄 알고 별 방법을 다 동원해보았지만 해결되지 않았다. 모든 방법을 다 시도해봤다고 생각했을 무렵 설마 하고 Interger 로 정의되어 있던 리턴타입을 int 로 바꿨더니 거짓말 처럼 값이 넘어오더라--
새벽까지 이 코드 붙들고 하도 고생을 해서 나중에 잊어 먹고 성질 내지 않도록 남겨 놓는다.ㅎㅎ