Spark 컨테이너의 레이아웃은 기본적으로 제공되는 5개의 Layout 클래스가 담당하게 됩니다.

- BasicLayout
- VerticalLayout
- HorizontalLayout
- TileLayout
- ButtonBarHorizontalLayout

이 중에서도 수평, 수직, 타일 레이아웃은 Flex3에서와 마찬가지로 
verticalAlign, horizontalAlign 속성을 제공합니다만
이글의 제목에서 소개한 두개의 설정 가능한 값이 추가 되었습니다.

비슷한 두개의 설정 값이 서로 어떻게 다른지 설명과 예제를 통해 알아보겠습니다.
(컨테이너의 높이는 100, 가장 큰 버튼의 높이는 150)

justify
 - 부모 컨테이너의 높이(또는 넓이)로 자식의 높이(또는 넓이)를 맞춘다.

contentJustify
 - 가장 큰 자식의 높이(또는 넓이)로 다른 자식의 높이(또는 넓이)를 맞춘다.


신고
Posted by 째코
UIComponent 클래스에 getLayoutBounds~() 메소드가 추가 되었는데
긴 말 필요없이 이 그림이 모든걸 설명해 줍니다. ㅋ


신고
Posted by 째코
Flex4 sdk를 예전에 처음 봤을 때, 
"이거 나중에 문제 생기겠는데..." 생각했던 코드를 봤었는데 결국 오늘 문제가 생겼습니다.

먼저 예제를 보겠습니다.

소스보기(두개의 결과물을 같은 소스로 컴파일)


Flex3 예제



Flex4 예제



예제설명
버튼 컴포넌트에서 마우스롤오버 같은 시각적인 변화가 일어나면 랜더링후 update_complete 이벤트가 송출 됩니다. 이때 캔버스에서 update_complete 이벤트를 캡쳐링 단계에서 리스닝하여 이벤트 정보를 Alert으로 띄우는 예제 입니다.


문제점
위 두개의 예제의 버튼에 마우스를 올려보면 Flex3에서정상적으로 캔버스에서 캡춰가 되지만 Flex4에서는 캡춰가 되지 않습니다. Flex4 sdk의 UIComponent 와 LayoutManager 소스를 보면 다음과 같이 되어 있습니다.

UIComponent 소스의 일부
if (hasEventListener(FlexEvent.ENTER_STATE))
   dispatchEvent(new FlexEvent(FlexEvent.ENTER_STATE)); 

LayoutManager 소스의 일부
if (obj.hasEventListener(FlexEvent.UPDATE_COMPLETE))
   obj.dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));

Flex3 에서는 dispatchEvnet() 전에 hasEventListner()로 리스너가 있는지 검사하지 않지만, 
Flex4 에서는 해당 리스너가 있을 경우만 이벤트를 송출하기 때문에 문제가 발생한 것이었습니다.
(각 컨트롤의 자체적인 이벤트는 제외)
따라서, Flex4 예제에서 캔버스가 캡춰단계에서 리스닝하기 위해서는 버튼이 이벤트를 송출할 수 있도록 버튼자체에 update_complete 리스너가 등록되어 있어야 합니다.


그렇다면...
부모 컨테이너에서 자식의 화면이 갱신되는걸 알려면 어떻게 해야 할까요...
Flex3에서는 update_complete로 캡춰를 통해 알 수 있었지만, Flex4에서는 불가능합니다.
HSlider를 예를들면, 크게 track과 thumb으로 구성되어 있는데 각각의 track과 thumb자체에 update_complete 리스너가 장착되어 있지 않기 때문에, 송출 자체가 되지 않습니다.
자식에 리스너가 없고 부모에서 자식의 이벤트를 캡춰하는 경우가 빈번한건 아니지만 분명 그런 상황이 있습니다.
이 문제를 어떻게 해결해야 할까요?
신고
Posted by 째코
참고 : http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/index.html

선행조건



1. Remoting Service 설정하기
BlazeDS는 전통적으로 리모팅서비스를 remoting-config.xml 파일에 설정하고, services-config.xml 에 포함해 왔습니다. remoting-config.xml 파일에 설정되는 것들은 adapters, default-channels, destinations 가 있습니다. Spring BlazeDS Integration(이하 SBI)를 사용하면, 리모팅서비스 설정을 스프링에서 하기 때문에
remoting-config.xml 파일은 완벽하게 안중오브아웃 할 수 있습니다. 따라서, remoting-config.xml 파일이 필요 없어짐에 따라 services-config.xml 파일에 포함시키지 않아도 됩니다. 만약 레거시 destinations가 정의된 remoting-config.xml 파일이 있다면, SBI의 RemotingDestinationExporter에 의해 스프링에서 관리되는 destinations와 레거시 destinations의 통합을 이룰 것 입니다.

remoting-service 태그와 두개의 속성 default-channels, default-adapter-id를 설정할 수 있습니다.
<flex:message-broker>
    <flex:remoting-service default-channels="amf, secure-amf" />
</flex:message-broker>
default-channels 속성이 생략될 경우 services-config.xml에 정의된 첫번째 AMFEndpoint 채널이 설정 됩니다.
default-adapter-id 속성이 생략될 경우 JavaAdapter 가 설정 됩니다.
remoting-service 태그가 생략될 경우 두 가지 속성 모두 디폴트로 설정 됩니다.

만약 services-config.xml 파일에서 포함하는 remoting-config.xml 파일이 존재한다면, 스프링에서
remoting-service 태그의 역할은 무시 됩니다.

만약 services-config.xml 파일에서 포함하는 remoting-config.xml 파일이 존재하지 않는다면, Flex 프로젝트를 J2EE 서버모드로 설정했을 경우 컴파일 타임에 services-config.xml 파일과 포함되는 서비스 설정파일의 destinations과 그 것이 사용하는 channels을 바라보기 때문에, 채널 설정없이 단순히 <mx:RemoteObject /> 태그만 사용할 경우 채널을 찾을 수 없다는 예외가 발생 합니다. 따라서 리모팅 서비스의 설정을 SBI에서 한다면, Flex 프로젝트는 채널을 명시해야 할 것 입니다.

간혹, 웹 문서(다른 분들의 블로그)에 services-config.xml 파일에 default-channels을 설정하라는 내용이 있습니다. 그렇게 설정 했을 경우, Flex 프로젝트에서는 application level의 기본 채널을 바라볼 수 있기 때문에 별도의 채널설정 없이 사용가능 합니다. 하지만 SBI에서 리모팅 서비스를 설정하고, services-config.xml 파일에 default-channels이 설정 되었다면 이것은 설정의 이원화를 가져올 뿐만 아니라 SBI에서 관리되는 리모팅 객체들(채널이 명시되지 않은)에 설정되는 기본 채널은 SBI에서 설정(또는 기본값)되는 default-channels 입니다. 한마디로 services-config.xml 파일에 설정되는 default-channels은 가비지설정값 입니다. 단지 Flex 프로젝트에 힌트를 주는 용도로 사용될 뿐이고, 자칫 잘못하면 설정 이원화로 실제로 서비스 되는 리모팅 객체들의 채널과 맞지 않아서 에러를 유발할 수 있습니다.



2. remoting-destination tag
이제 스프링의 빈을 리모팅 객체로 노출시킬 차례 입니다.
먼저 서비스할 빈이 필요하고 remoting-destination 태그를 이용해 리모팅 객체로 만들 수 있습니다.
<bean id="productService" class="flex.samples.product.ProductServiceImpl" />

<flex:remoting-destination ref="productService" />

다음 설정은 위의 것과 동일 합니다.
<bean id="productService" class="flex.samples.product.ProductServiceImpl" >
    <flex:remoting-destination />
</bean>

remoting-destination 태그의 속성들은 다음과 같습니다.
ref
- 서비스할 스프링 빈의 id 입니다.

destination-id
- 서비스될 id 입니다.
- 생략할 경우 빈의 이름으로 설정됩니다.

include-methods, exclude-methods
- 각각 서비스할 메소드와 제외시킬 메소드 입니다.
- 둘다 생략시 모든 메소드를 서비스 합니다.
- include-methods 속성만 설정할 경우, 나머지 메소드는 자동으로 제외 됩니다.
- exclude-methods 속성만 설정할 경우, 나머지 메소드는 자동으로 서비스 됩니다.

channels
- 서비스할 채널 입니다.
- 생략할 경우 기본채널이 설정 됩니다.

message-broker
- MessageBroker의 id 입니다.
- 생략할 경우 _messageBroker로 설정 됩니다.



3. @RemotingDestination
이 애노테이션 하나로 remoting-destination 태그를 대체할 수 있습니다. 이 애노테이션을 해석할 RemotingAnnotationPostProcessor 빈은 message-broker 태그에 의해 자동으로 등록 됩니다.
스프링의 컴포넌트 스캔과 함께 사용하면 더욱 편리합니다.

@Service("productService")
@RemotingDestination
public class ProductServiceImpl implements ProductService {

    @RemotingInclude
    public Product read(String id) {
        ...
    }
   
    @RemotingExclude
    public Product create(Product product){
        ...
    }
   
    @RemotingInclude
    public Product update(Product product){
        ...
    }
   
    @RemotingExclude
    public void delete(Product product) {
        ...
    }
}

@RemotingDestination에 설정할 수 있는 속성은 다음 세 가지가 있는데(사실은 네 가지...)
value, channels ,messageBroker 이 중에서 value는 destination의 id이고 생략할 경우 빈의 이름으로 설정 됩니다. 나머지 속성들은 remoting-destination 태그의 속성들과 동일 합니다. 그리고 서비스하거나 제외시킬 메소드를 결정하기 위해 두 개의 애노테이션이 있는데, 이 또한 remoting-destination 태그의 속성과 동일한 기능을 합니다.




신고
Posted by 째코
참고 : http://static.springsource.org/spring-flex/docs/1.0.x/reference/html/index.html

선행조건
- BlazeDS
- Spring-core
- Spring-mvc
- Spring-lifecycle
- Spring-FactoryBean
- Spring-BeanFactoryPostProcessor
위 선행조건을 만족하면 어렵지 않게 이해하고 사용할 수 있습니다. 만약 위 선행조건을 만족하지 못할경우 따라하기 식으로 작동은 시킬수 있을지 모르지만, 운이 좋지 못하여 사소한 에러가 발생했을 경우 쉽게 그 원인을 찾지 못할 수도 있습니다.


소개
Spring BlazeDS Integration은 말 그대로 BlazeDS를 스프링에 통합시켜 주는 모듈 입니다. 스프링의 설정파일(applicationContext.xml)에서 BlazeDS의 모든 것(100%는 아니지만...)을 스프링의 친숙한 설정방식으로 관리할 수 있습니다. 통합시 스프링에서 할 수 있는 것들은 다음과 같습니다.
- 리모팅 서비스
- 메세징 서비스
- MessageBroker 커스터마이징
- Custom Exception Translators
- Custom Message Interceptors
- Spring Security와 통합
(현재 1.0 버전에서 프록시 서비스는 스프링이 따로 통합을 해주지 않습니다.)


1. Spring DispatcherServlet 설정하기
BlazeDS에서는 MessageBrokerServlet을 프론트 컨트롤러로 사용하여 flex client의 요청을 처리했습니다.
여기서는 Spring MVC의 DispatcherServlet이 flex client의 요청을 받아들입니다. 요청을 받아들인 이후의 시나리오는 당연히 url을 판별하여 MessageBroker로 요청을 위임하는 것 입니다.

web.xml
<servlet>
    <servlet-name>flex</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/web-application-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>flex</servlet-name>
    <url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>


2. MessageBroker로 요청 위임하기
web.xml 파일의 설정에 의해 flex client의 요청은 DispatcherServlet이 담당하게 될 것이고, 이제 그 요청을 MessageBroker로 위임해야 합니다. MessageBroker로 위임하기 위해서 필요한 것들은 다음과 같습니다.
SimpleUrlHandlerMapping
- Spring MVC의 일부분으로서, url 패턴에 의해 요청을 처리할 컨트롤러를 매핑 합니다. Context가 flex-client 전용이라는 가정하에 /* 패턴의 url을 MessageBroker로 매핑할 것입니다.

MessageBrokerFactoryBean
- 스프링의 FactoryBean 로직에 의해 MessageBroker를 생성 합니다. 기본적으로
/WEB-INF/flex/services-config.xml 파일을 참조합니다. 만약 이 설정파일 다른 곳에 위치해 있다면 servicesConfigPath 프로퍼티를 통해 변경할 수 있습니다.

MessageBrokerhandlerAdapter
- MessageBroker는 Spring MVC의 컨트롤러가 아닙니다. 따라서 HandlerAdapter의 구현체인 이 클래스를 이용해서 컨트롤러가 아닌 MessageBroker가 요청을 처리할 수 있도록 도와 줍니다.
위 3가지 클래스의 역할을 소개 했는데, 서론에서 언급한 선행조건을 만족한다면 간단히 이해하고 넘어갈 수 있는 부분 입니다.

위 3가지 클래스를 스프링 빈으로 설정한 것은 다음과 같습니다.
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
            /*=_messageBroker
        </value>
    </property>
</bean>

<bean id="_messageBroker" class="org.springframework.flex.core.MessageBrokerFactoryBean" />

<bean class="org.springframework.flex.servlet.MessageBrokerHandlerAdapter" />

Spring의 다른 모듈의 설정이 그랬듯이 위 3가지 빈 설정또한 하나의 네임스페이스 태그로 해결할 수 있습니다.
다음 태그는 위 3가지 빈 설정과 100% 동일합니다.
<flex:message-broker />
이 태그의 servicesConfigPath를 이용해 services-config.xml 파일의 위치를 설정할 수 있으며, 생략할 경우 기본 값은 마찬가지로 /WEB-INF/flex/services-config.xml 입니다.


3. Context에 다른 Spring MVC 어플리케이션이 존재할 경우
시작 하기에 앞서, SpringSource의 공식 문서에는 Spring 제작사 임에도 불구하고 제가 생각하기에 다소 이해가 가지 않은 방식으로가이드를 하고 있습니다. 따라서 공식 문서의 가이드를 무시하고, 제가 가장 깔끔하고 편리한 방향으로 가이드를 제시 하겠습니다.

지금까지의 설정은 Context가 flex-client 전용이라는 가정하에 DispatcherServlet으로 들어온 모든 요청을 MessageBroker로 위임했습니다. 하지만, 이 경우 flex-client의 요청과 일반적인 웹 요청을 분리해야 합니다.

web.xml
<servlet>
    <servlet-name>spring-mvc and flex</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/web-application-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring-mvc and flex</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
(ContextLoaderListener 설정은 현재 관심사가 아니기 때문에 생략 했습니다.)

web.xml 설정에 의해 flex-client 요청과 일반적인 웹 요청을 하나의 DispatcherServlet이 담당하게 됩니다. 따라서 url 패턴으로 요청이 분리해야 합니다.

MessageBroker 설정을 3개의 빈으로 설정할 경우SimpleUrlHandlerMapping 빈에서 url 패턴을 변경하면 되고, 또는 message-broker 태그에서 간단하게 url 매핑을 변경할 수 있습니다.
<flex:message-broker>
    <flex:mapping pattern="/messagebroker/*"/>
</flex:message-broker>
나머지 Spring MVC(현 시점에서 대부분 애노테이션 방식)는 사용하던 방식 그대로 설정하면 됩니다.


신고
Posted by 째코


티스토리 툴바