'00.Flex,Flash,ActionScript/Flex'에 해당되는 글 79건

  1. 2015.03.17 http://flex.apache.org/tourdeflex/index.html
  2. 2014.07.25 [펌] flex StringUtil.substitute 사용하기
  3. 2014.06.25 flex charts link
  4. 2014.06.20 The Blogagic Flex Explorer Collection
  5. 2014.06.19 [펌] [Flex3] Error : mx.managers.IDragManager(으)로 변환할 수 없습니다 ...
  6. 2014.06.13 [펌] [Flex]TextInput 글자제한 ( restrict )
  7. 2014.06.12 [펌] DataGrid CheckBox 스크롤때 없어지는문제 해결 [출처] DataGrid CheckBox 스크롤때 없어지는문제 해결|작성자 neodijkstra
  8. 2014.06.12 [펌] 데이터그리드 스크롤 버그
  9. 2014.06.12 [펌] Flex DataGrid ItemRenderer 스크롤 버그
  10. 2014.06.10 [펌] FLEX 마우스 커서 모양 바꾸기 (시스템)
  11. 2014.06.10 [펌] flex 컴포넌트 크기 변경하기
  12. 2013.12.03 flex 843 보안정책서버 예제
  13. 2013.11.06 flex 에 jsp 페이지 삽입 iframe
  14. 2013.11.04 [펌] flex에서 font 사용하기 2
  15. 2013.11.01 [펌] Flex 줄바꿈 처리 2
  16. 2013.10.31 flex textarea 개행문자
  17. 2013.10.01 flex 개행문자 제거
  18. 2013.09.26 flex add Dynamic children to an array or arraycollection 1
  19. 2013.09.12 [펌] 세션 가져오는 법
  20. 2013.09.12 [펌] Flex Log log4j 처럼 사용하기
  21. 2013.09.12 [펌] spring+flex4+mybatis
  22. 2013.09.11 Working with States in Flex 4
  23. 2013.09.10 [펌] BlazeDS 와 스프링(Spring) 연동하기 1
  24. 2013.09.09 [펌] (Flex 4)Blazeds + Spring 설정 완료된 war 1
  25. 2013.09.05 spring blazeds integration
  26. 2013.09.04 <flex-remoting> 태그 사용시 발생하는 오류
  27. 2013.09.02 Spring BlazeDS Integration 환경 설정
  28. 2013.09.02 [펌] Spring BlazeDS Integration 1.0.0 Release(정식) 적용하기(1) - 세팅 및 Remoting적용
  29. 2013.09.02 Spring BlazeDS Integration
  30. 2013.08.13 flex style explorer
반응형

http://flex.apache.org/tourdeflex/index.html

Posted by 1010
반응형
mx.utils 에는 편하게 사용할 수 있는 api 가 담겨있다. 

ObjectUtil.toString 같은 것은 많이 사용하고 꽤나 유용하게 쓰인다. 

이 포스트에서 이야기 할 substitute 는 간단하게 이야기 하면 문자열을 치환 해주는 메서드이다.

간단히 코드를 보면 이해가 될것이다. 

1private var str:String "select * from TABLE_NAME where userid='{0}' and menuid='{1}'";
2 
3private function build():void
4{
5    var query:String = StringUtil.substitute(str,"rinn","n002");
6    trace(query);
7    //select * from TABLE_NAME where userid='rinn' and menuid='n002'
8}


위코드에서 보듯이 String 값에서 {n} 형식으로 중괄호로 묶여진 것들을 찾아서. 
거기에 파라미터로 받은 값을 넣어준다. 
n 값에 따라서 파라미터가 순서대로 들어가게 된다. 

{0} 에는 첫번째가 {1}에는 두번째가 들어가고 문자열 안에서 등장하는 순서는 상관이 없다.

1private var str2:String "select * from TABLE_NAME where userid='{0}' and menuid=(select menuno from TABLE2 where userid='{0}' and menuid='{1}')";
2 
3private function build2():void
4{
5    var query:String = StringUtil.substitute(str2,"rinn","n002");
6    trace(query);
7    //select * from TABLE_NAME where userid='rinn' and menuid=(select menuno from TABLE2 where userid='rinn' and menuid='n002')
8}


{0} 이 두번 나오면 두번다 파라미터 첫번째 값이 들어가게 되는 것이다. 

이 방법의 좋은점은 대상이 되는 문자열을 파일로 저장해놓을 수 있다는 점이다. 

기본 쿼리 같은 경우 파일로 저장해놓고 불러다가 치환해서 사용하게 되면.. 테이블 이름정도가 바뀐다거나 하는 것들은 간단하게 파일만 수정하는 것으로도 해결이 된다. 

메뉴의 링크 정보를 저장하는 경우에도 편리하다. 권한 정보 같은것에 따라 파라미터가 바뀐다거나 하는 경우에.. 기본 링크 정보를 저장해놓으면 이후에 간단한 것은 컴파일 할 필요없이 수정해 줄수 있다. 

사실 쿼리 같은 경우 iBatis 를 쓰는 것이 훨씬 간편하고 다이나믹 하게 쿼리를 생성할 수 있지만. 간단한 httpService 를 사용하는 경우에는 유용할 수 있겠다. 

substitute 함수는 간단하게 구현되어있다. 

01public static function substitute(str:String, ... rest):String
02{
03    if (str == nullreturn '';
04     
05    // Replace all of the parameters in the msg string.
06    var len:uint = rest.length;
07    var args:Array;
08    if (len == 1 && rest[0is Array)
09    {
10        args = rest[0as Array;
11        len = args.length;
12    }
13    else
14    {
15        args = rest;
16    }
17     
18    for (var i:int 0; i < len; i++)
19    {
20        str = str.replace(new RegExp("\\{"+i+"\\}""g"), args[i]);
21    }
22 
23    return str;
24}


간단하게 받아온 파라미터를 Array로 받고 for문 돌면서 정규식으로 찾아서 바꿔주는 구조이다.
사실 이런것은 필요한 경우에 그냥 만들어서 쓰게 되는데 이미 api 에서 제공하는 것을 귀찮게 만들어 쓸 필요가 있는가!!
그냥 있는 걸 쓰자.. -ㅅ-;

mx.utils 패키지 같은 경우에 간단 간단한 함수로 되어있기 때문에 api 소스를 보는 것 만으로도 초보 개발자에게는 공부가 된다. 결정적으로 그리 어렵지 않다.. 

시간날때 한번씩 뭐가 있는지 봐놓으면.. 나중에 뻔히 제공되는 메서드를 놔두고.. 개발하는 사태는 벌어지지 않을것이다.. 
우리는.. 그거 말고도 할일이 많지 않은가.. ㅠㅠ


아.. 주말도 출근 해야 하나.....

출처 : http://rinn.kr/31


Posted by 1010
반응형

Index of /asdoc/mx/charts

 Name                    Last modified      Size  Description
Parent Directory - AreaChart.html 2014-05-03 13:10 304K AxisLabel.html 2014-05-03 13:10 13K AxisRenderer.html 2014-05-03 13:10 296K BarChart.html 2014-05-03 13:10 307K BubbleChart.html 2014-05-03 13:10 305K CandlestickChart.html 2014-05-03 13:10 304K CategoryAxis.html 2014-05-03 13:10 60K ChartItem.html 2014-05-03 13:10 28K ColumnChart.html 2014-05-03 13:10 313K DateTimeAxis.html 2014-05-03 13:10 101K GridLines.html 2014-05-03 13:10 252K HLOCChart.html 2014-05-03 13:10 303K HitData.html 2014-05-03 13:10 24K Legend.html 2014-05-03 13:21 418K LegendItem.html 2014-05-03 13:21 251K LineChart.html 2014-05-03 13:21 302K LinearAxis.html 2014-05-03 13:21 54K LogAxis.html 2014-05-03 13:21 51K PieChart.html 2014-05-03 13:21 294K PlotChart.html 2014-05-03 13:21 301K chartClasses/ 2014-05-03 13:35 - class-list.html 2014-05-03 13:10 2.0K effects/ 2014-05-03 13:35 - events/ 2014-05-03 13:35 - package-detail.html 2014-05-03 13:21 8.7K renderers/ 2014-05-03 13:35 - series/ 2014-05-03 13:35 - styles/ 2014-05-03 13:35 -
Apache/2.4.9 (Unix) OpenSSL/1.0.1h Server at flex.apache.org Port 80


Posted by 1010
반응형

There are a lot of Flex Explorer applications available on line. These explorers can really help when you want to refresh your knowledge on the Flex capabilities or when you plan to fine tune specific styles or effects.

Whether you’re trying to design a good looking button or data grid, configuring a fancy glow effect, implementing a complex regular expression, configuring a BlazeDS channel or just searching for inspiration; there is probably a Flex Explorer for you.

Here is my own list of explorers, that I also gathered in my Flex Tool Box page for quick and easy reference.

Flex Component Explorer

Flex Component Explorer screen capture
The Flex Component Explorer lets you browse through the huge list of available Flex core components. For each of them, a small sample application (corresponding code is available) shows how the component is rendered and behaves. Even if you can’t change the component configuration, this remains a useful tool when you’d like to learn more of a component that you never used so far.

Tour de Flex Explorer

Tour De Flex screen capture
The Tour De Flex Explorer is available on line but can also be installed as an AIR application. It extends the Flex 3 Component Explorer by adding Flex 4 Spark components description, coding techniques examples, Flex Data Access information, Flex frameworks introduction and much more.

Flex Chart Sampler

Flex Chart Sampler screen capture
The Flex Chart Sampler (from Ely Greenfield blog) lets you interactively discover the Flex Charting components.

Flex Style Explorer

Flex Style Explorer screen capture
The Flex Style Explorer is probably the one I use the most. You can use it to style interactively any component, see how looks the result and export the result as a CSS file that you can use in your projects.

Flex Enhanced Button Skin Explorer

Flex Enhanced ButtonSkin Explorer screen capture
The Flex Enhanced Button Skin Explorer(from Daniel Wabyick blog) is an explorer dedicated to the EnhancedButtonSkin available in FlexLib.

Adobe® Kuler™ Color Themes Explorer

Kuler Color Theme Explorer screen capture
The Adobe® Kuler™ Color Themes Explorerallows experimenting quickly with color variations and browse color themes from the Kuler community (can be downloaded as an AIR application).

Flex Filter Explorer

Flex Filter Explorer screen capture
The Flex Filter Explorer (from Joe Johnston blog) lets you define your flex filter interactively and generates the corresponding MXML to include in your projects.

Flex Easing Function Explorer

Flex Easing Function Explorer screen capture
The Flex Easing Function Explorer (fromJames Ward blog) allows experimenting with ease functions that allow applying non-linear motion to effects.

Flex Distortion Effect Explorer

Flex Distortion Effect Explorer screen capture
The Flex Distortion Effect Explorer (from Alex Uhlmann blog) demonstrates fancy distortion effects such as Flip, Pop, Cube rotate, Door and much more.

Flex Reflection Explorer

Flex Reflection Explorer screen capture
The Flex Reflection Explorer (from Wietse Veenstra blog) demonstrates beautiful reflection effects using the ReflectionManager provided class.

Efflex Explorer

Efflex Explorer screen capture
The Efflex Explorer (from Efflex.org) demonstrates the effects available when using the open source Efflex library.

Flex Regular Expression Explorer

Flex Regular Expression Explorer screen capture
The Flex Regular Expression Explorer (fromRyan Swanson blog) lets you define your regular expressions from the explorer and check immediately whether they work or not by providing test data and look at the result. This explorer also provides a very good on line help that should allow you not be afraid by regular expressions anymore.

BlazeDS Channel Designer

BlazeDS Channel Designer screen capture
The BlazeDSChannel Designer isn’t really an explorer but I thought it would be useful to mention it here. It provides an easy and interactive way to configure your BlazeDS channels and outputs the services-config.xml corresponding to your options.

Rating: 5.0/5 (8 votes cast)


Posted by 1010
반응형

출처 : http://hapina.tistory.com/10


플렉스에서 하나의 어플리케이션에 모듈을 여러개 로딩하여 사이즈를 줄이는 방법으로 프로젝트가 많이 진행됩니다.

그러나 가끔 마우스 다운 이벤트 및 드래깅 시 다음과 같은 에러가 발생합니다.

TypeError: Error #1034: 유형 강제 변환에 실패했습니다. mx.managers::DragManagerImpl@a23f6f1을(를) mx.managers.IDragManager(으)로 변환할 수 없습니다.

또는 다음과 같은 에러...

ReferenceError: Error #1065: 변수 mx.managers::DragManager이(가) 정의되어 있지 않습니다.

데이터그리드를 넣은 모듈을 로드하여 폴더 열기/닫기 할 때 처음 이 에러를 만났습니다.

이 문제의 원인과 해결책에 대해 알아봅시다.

원인 및 해결책.

플렉스 프레임웤 상 DragManager 는 싱글톤으로 하나의 인스턴스만 존재해야 합니다.

App 에는 Manager DB 가 존재하여 모든 Manager 를 관리합니다.(모든 메니저의 인스턴스가 아닌 클래스)

처음 모듈을 로딩할 때 DragManager 가 해당 모듈에서 인스턴화되면..

두번째 모듈에서는 해당 인스턴스를 알아낼 방법이 없어집니다. 즉 혼란이 생긴거죠.

모듈의 Applicatoin shared code 때문에 생기는 일입니다.

따라서 처음 드래그메니저의 인스턴스를 App 에서 생성되도록하여 모든 모듈이 드래그메니저의 인스턴스를 App 에서 참조하도록 설정합니다.

해결책으로 이를 방지하기 위해 어플리케이션에서 다음과 같이 DragManager 를 import 하세요.

이는 아마도 버그일 수 있습니다. 최초 App 에서 드래그메니저의 인스턴스를 생성하면 되는데 그렇지 않고 있기 때문이죠.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 <mx:Script>
  <![CDATA[

   import mx.managers.DragManager;
   private var dummy:DragManager;
   
....
...
...

  ]]>
 </mx:Script>

이 처럼 App 에서 DragManager 의 인스턴스를 생성하게 하여 클래스를 내포시킵니다.

그럼 굿럭!~

Posted by 1010
반응형

TextInput 의 restrict property 에 대해...

<mx:TextInput id="txt" restrict="ㄱ-힣">

restrict = "ㄱ-힣"            :  한글만 입력가능.
restrict = "A-z"              :  영어만 입력가능.
restrict = "0-9"               :  숫자만 입력가능.
restrict = "0-9\-"           : 숫자와 '-'만 입력가능.
restrict = "^a-z"             : 소문자 a부터 z까지 제외한 모든문자 입력가능.
restrict = "A-z0-9\@\." : 이메일 형식만 입력가능.
restrict = "\\\"           : '\' 문자만 입력가능.
restrict = "\^"               :  '^' 문자만 입력가능.

여러가지 응용도 하실 수 있겠습니다.


출처 : http://2rang.tistory.com/15

Posted by 1010
반응형

 <mx:DataGridColumn headerText="선택" width="50">
              <mx:itemRenderer>
               <mx:Component>
                <mx:HBox horizontalAlign="center">
                 <mx:Script>
                  <![CDATA[
                               public override function set data(value:Object):void
                               {
                                   super.data = value;
                               }
                  ]]>
                 </mx:Script>
                 <mx:CheckBox id="cb1" selected="{data.chk}" change="{data.chk = cb1.selected}"/>
                </mx:HBox>
               </mx:Component>
              </mx:itemRenderer>
             </mx:DataGridColumn>


출처 : http://blog.naver.com/PostView.nhn?blogId=neodijkstra&logNo=50050005320

Posted by 1010
반응형

기본적인 개념으로.. 데이터 그리드등에 ItemRenderer를 사용하여 checkBox 나 기타 등등의 컴포넌트를 넣었을때

데이터그리드를 스크롤하게 되면 체크박스의 데이터가 뒤죽박죽이 되는 문제가 발생한다.

이는.. 보이는영역에서 사라진 컴포넌트들이 재사용(!!) 되면서 일어나는 현상으로 다음과 같은 방법으로 해결한다.

<Adobe Flex4 Help에서 발췌>

Creating a recyclable item renderer


With virtual layout disabled, the DataGroup and SkinnableDataContainer containers create one instance of the item renderer for each child. With virtual layout enabled, the container only creates enough item renderers to display its currently visible children. Virtual layout greatly reduces the overhead required to use the DataGroup and SkinnableDataContainer containers.
With virtual layout enabled, when a child is moved off the visible area of the container, its item renderer is recycled. First, the item renderer’s data property is set to null. When the item renderer is reused, its data property is set to the data item representing the new child. Therefore, if a recycled item renderer performs any actions based on the value of the data property, it must first check that the property is not null. When the item renderer is reassigned, Flex also calls the updateRenderer() method of the item renderer owner. This method must set the owner and label properties on the item renderer. Subclasses of SkinnableDataContainer, can use the updateRenderer() method to set additional properties on the item renderer. Because a container can reuse an item renderer, ensure that you fully define its state. For example, you use a CheckBox control in an item renderer to display a true (checked) or
false (unchecked) value based on the current value of the data property. A common mistake is to assume that the CheckBox control is always in its default state of unchecked and only inspect the data property for a value of true.
However, remember that the CheckBox can be recycled and had previously been checked. Therefore, inspect the data property for a value of false , and explicitly uncheck the control if it is checked, as the following example shows:

<ItemRenderer의 dataChange 이벤트를 이용하는 방법>
Prerelease - 5 October 2009
USING FLEX 4 442
Building the user interface
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleItemRendererCB.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/halo"xmlns:s="library://ns.adobe.com/flex/spark" dataChange="setMgr();">
<fx:Script>
<![CDATA[
private function setMgr():void {
// Check to see if the data property is null.
if (data == null) return;
// If the data property is not null,
// set the CheckBox control appropriately..
if (data.manager == "yes") {
mgr.selected = true;
}
else {
mgr.selected = false;
}
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="selected"/>
</s:states>
<s:HGroup verticalCenter="0" left="2" right="2" top="2" bottom="2">
<s:Label text="{data.lastName}, {data.firstName}"/>
<s:Label text="{data.companyID}"/>
<s:CheckBox id="mgr"/>
</s:HGroup>
</s:ItemRenderer>


Use the dataChange event of the ItemRenderer class to detect the change to its data property. This event is dispatched whenever the data property changes. Alternatively, you can override the data property. Alternatively, you can override the ItemRenderer.data
property itself, as the following example shows:

<data 속성을 오버라이드하는 방법>
Prerelease - 5 October 2009
USING FLEX 4 443
Building the user interface
<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\myComponents\MySimpleItemRendererCBData.mxml -->
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
// Check to see if the data property is null.
if (value== null) return;
// If the data property is not null,
// set the CheckBox control appropriately..
if (value.manager == "yes") {
mgr.selected = true;
}
else {
mgr.selected = false;
}
}
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="selected"/>
</s:states>
<s:HGroup verticalCenter="0" left="2" right="2" top="2" bottom="2">
<s:Label text="{data.lastName}, {data.firstName}"/>
<s:Label text="{data.companyID}"/>
<s:CheckBox id="mgr"/>
</s:HGroup>
</s:ItemRenderer>

상단의 두가지 방법을 이용하여 새로운 ItemRenderer를 생성한 후 다음과 같은 방법으로 사용한다.

<?xml version="1.0" encoding="utf-8"?>
<!-- containers\spark\SparkDataGroupContainerTypicalItem.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
[Bindable]
public var typicalObj:Object = {
firstName:"Long first name",
lastName:"Even longer last name",
companyID:"123456",
manager:"yes"
};
]]>
</fx:Script>
<s:Scroller>
<s:DataGroup itemRenderer="myComponents.MySimpleItemRendererCB"
height="100"
typicalItem="{typicalObj}" >
<s:layout>
<s:VerticalLayout useVirtualLayout="true"/>
</s:layout>
<mx:ArrayList>
<fx:Object firstName="Bill" lastName="Smith" companyID="11233" manager="yes"/>
<fx:Object firstName="Dave" lastName="Jones" companyID="13455" manager="no"/>
<fx:Object firstName="Mary" lastName="Davis" companyID="11543" manager="yes"/>
<fx:Object firstName="Debbie" lastName="Cooper" companyID="14266" manager="no"/>
<fx:Object firstName="Bob" lastName="Martins" companyID="11233" manager="yes"/>
<fx:Object firstName="Jack" lastName="Jones" companyID="13455" manager="no"/>
<fx:Object firstName="Sam" lastName="Johnson" companyID="11543" manager="yes"/>
<fx:Object firstName="Tom" lastName="Fitz" companyID="14266" manager="no"/>
<fx:Object firstName="Dave" lastName="Mead" companyID="11233" manager="yes"/>
<fx:Object firstName="Dave" lastName="Jones" companyID="13455" manager="no"/>
<fx:Object firstName="Mary" lastName="Davis" companyID="11543" manager="yes"/>
<fx:Object firstName="Debbie" lastName="Cooper" companyID="14266" manager="no"/>
</mx:ArrayList>
</s:DataGroup>
</s:Scroller>
</s:Application>


Posted by 1010
반응형

출처 : http://igna84.blogspot.kr/2010/03/flex-datagrid-itemrenderer-2-%EC%A0%84%EB%A9%B4%EC%A0%84.html


Flex DataGrid ItemRenderer #2 - 전면전

경력사원임에도 불구하고 나이가 어려서 그런지 신입사원 연수를 다녀오라는 지시에 지난 목요일 금요일 다녀오는 바람에 ItemRenderer 이야기가 늦어졌습니다. 기다리신 분 계신가요?? 죄송합니다. 본의아니게;;

아무튼 DataGrid ItemRenderer 라는 뜨거운 감자를 삼키기위해 어떤 모양의 ItemRenderer를 만들지 한번 생각해보도록 할까요.

 

처음이니 간단하게 CheckBox 아이템 렌더러를 만들도록 해봅시다.

 

일단 메인 어플리케이션을 만들어 놓습니다.

 

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                                     {index:1, description:"test1", toggle:"Y"},
                                     {index:2, description:"test2", toggle:"N"},
                                     {index:3, description:"test3", toggle:"N"},
                                     {index:4, description:"test4", toggle:"Y"},
                                     {index:5, description:"test5", toggle:"N"},
                                     {index:6, description:"test6", toggle:"N"},
                                     {index:7, description:"test7", toggle:"Y"},
                                     {index:8, description:"test8", toggle:"N"},
                                     {index:9, description:"test9", toggle:"N"},
                                     {index:10, description:"test10", toggle:"N"},
                                     {index:11, description:"test11", toggle:"N"},
                                     {index:12, description:"test12", toggle:"N"}
                                     ]);
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="check" dataField="toggle" />
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

 

위와같이 코딩하고 컴파일하게되면 아래와 같이 산출물이 나오게 됩니다.

 

 

그럼 우리는 ratio라고 적혀있는 곳에 ItemRenderer를 적용할겁니다.

 

CheckBox를 상속받아 작업할겁니다. 왜 "UIComponent 안쓰고!"라고 말씀하신다면

그 이유는 UIComponent를 상속받은 클래스이기도 하고 지난시간 말했던 IDataRenderer, IDropInListitemRenderer, IListItemRenderer 이렇게 세 인터페이스가 이미 구현되어있으며 우리가 원하는 아이템 렌더러는 CheckBox아이템 렌더러이기 때문이지요.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.FlexEvent;
public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
    }
}
}
[/code]

초벌로 createChildren, commitProperties, updateDisplayList도 확장해 두고 아이템 랜더러로 사용하기 위한 준비를 마쳤습니다.

그리고 메인 어플리케이션은 아래와 같이 수정하고 컴파일 합니다.

[code xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
    import mx.collections.ArrayCollection;

    [Bindable]
    private var ac:ArrayCollection = new ArrayCollection([
                                        {index:1, description:"test1", toggle:"Y"},
                                        {index:2, description:"test2", toggle:"N"},
                                        {index:3, description:"test3", toggle:"N"},
                                        {index:4, description:"test4", toggle:"Y"},
                                        {index:5, description:"test5", toggle:"N"},
                                        {index:6, description:"test6", toggle:"N"},
                                        {index:7, description:"test7", toggle:"Y"},
                                        {index:8, description:"test8", toggle:"N"},
                                        {index:9, description:"test9", toggle:"N"},
                                        {index:10, description:"test10", toggle:"N"},
                                        {index:11, description:"test11", toggle:"N"},
                                        {index:12, description:"test12", toggle:"N"}
                                        ]);
    ]]>
</mx:Script>
<mx:DataGrid dataProvider="{ac}">
    <mx:columns>
        <mx:DataGridColumn headerText="index" dataField="index" />
        <mx:DataGridColumn headerText="description" dataField="description" />
        <mx:DataGridColumn headerText="radio" dataField="toggle" itemRenderer="classes.controls.renderers.CheckBoxRenderer" />
    </mx:columns>
</mx:DataGrid>
</mx:Application>
[/code]

일단 아래와 같은 결과가 나오면 성공입니다.

 

CheckBox 가 "Y"냐 "N"이냐에 따라 selected가 처리되는 로직이 필요합니다. 그러기 위해서는 그 코드를 어디에 넣는것이 좋을지 고민해봐야하는데 아까도 말했듯 모든 속성처리는 commitProperties에서 하게 됩니다. commitProperties를 호출하기 위해서는 저번에 이야기 했었던 대로 invalidateProperties() 메서드를 호출하면 됩니다. 그렇다면 코드를 아래와 같이 수정합니다.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.events.FlexEvent;
public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;
    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;

        dataChanged = true;

        invalidateProperties();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
        if(dataChanged)
        {
            dataChanged = false;
            updateProperties();
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(listData.label == "Y")
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }
}
}
[/code]

위와 같이 코딩하게 되면 아래와 같은 산출물이 나오게 됩니다.

 

 

썩 잘나오는거 같습니다. 몇가지 마음에 안 드는 것이 있는데 일단 CheckBox가 셀의 중앙에 갔으면 좋겠고 CheckBox를 클릭하고 휠을 돌려보면 Check가 풀려버리는 버그가 있다는 것이지요.

 

CheckBox를 중앙에 놓으려면 CheckBox의 너비를 알아야하는데 그것은 CheckBox는 기본적으로 14픽셀의 넓이를 갖습니다. 그것을 어떻게 아냐구요?

measuredWidth를 trace 해보면 간단하게 알 수 있습니다. 아, measuredWidth는 컨포넌트 객체의 기본 너비를 이야기 합니다.

 

위의 두가지 문제점을 해결하기 위해 아래와 같이 코드를 수정합니다.

 

[code as3]
package classes.controls.renderers
{
//-----------------------------------------------------------------------------
//
//  Import
//
//-----------------------------------------------------------------------------
import flash.events.MouseEvent;

import mx.core.IDataRenderer;
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.mx_internal;
import mx.events.FlexEvent;

use namespace mx_internal;

public class CheckBoxRenderer extends CheckBox
{
    //-----------------------------------------------------------------------------
    //
    //  Constructor
    //
    //-----------------------------------------------------------------------------
    /**
     *  Constructor.
     */
    public function CheckBoxRenderer()
    {
        super();
    }

    //-----------------------------------------------------------------------------
    //
    //  Variables
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  데이터 변경 확인 플래그
     */
    private var dataChanged:Boolean = false;

    //-----------------------------------------------------------------------------
    //
    //  Override Properties
    //
    //-----------------------------------------------------------------------------
    override public function set data(value:Object):void
    {
        super.data = value;

        dataChanged = true;

        invalidateProperties();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();
        if(dataChanged)
        {
            dataChanged = false;

            updateProperties();
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        currentIcon.x = (unscaledWidth - currentIcon.width) / 2;
    }

    //-----------------------------------------------------------------------------
    //
    //  Methods
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     *  CheckBox의 속성을 변경
     */
    private function updateProperties():void
    {
        if(listData.label == "Y")
        {
            selected = true;
        }
        else
        {
            selected = false;
        }

        invalidateDisplayList();
    }

    //-----------------------------------------------------------------------------
    //
    //  Override EventHandler
    //
    //-----------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function clickHandler(event:MouseEvent):void
    {
        super.clickHandler(event);

        //data[DataGridListData(listData).dataField] = selected ? "Y" : "N";

        if(selected)
        {
            data[DataGridListData(listData).dataField] = "Y";
        }
        else
        {
            data[DataGridListData(listData).dataField] = "N";
        }
    }
}
}
[/code]

 

currentIcon이라는 생소한 속성을 위에서 보실 수 있습니다. 그것은 체크박스에서 체크되는 아이콘을 지칭합니다. 그 currentIcon이란 녀석은 mx_internal이라는 접근자를 이용하고 있고 LanguageReference에는 표시되지 않고 있어서 그 존재를 모르는 사람이 많습니다.

예전에 저도 그것을 몰라서 HBox에다가 넣고 horizontalAlign="center"를 주는 바보같은 짓을 일삼았는데 이 사실을 알고 난뒤에 Container를 사용하지 않고 좀더 가볍게 itemRenderer를 만들어 낼 수 있었지요.


그래서 updateDisplayList() 메서드에서 좌표를 잡아서 셀의 중앙에 놓고 clickHandler라는 메서드를 확장하여 변경된 값을 data에 반영하게 합니다. 그렇게 되면 아래와 같은 결과물이 나오게 되지요.

 

 

오. 그럴싸하게 작동하는 것 같습니다만 몇가지 아쉬운점이 있습니다.

 

1. "Y", "N" 값으로만 작동하게 되어있다.

2. CheckBox를 클릭하면 뭔가 다른 행동을 하고 싶을땐 어떻게 하나.

 

이렇게 두가지 사항인데요.

이 부분에 대해서는 다음시간에 알아보도록 해요~


Posted by 1010
반응형

각 컨트롤 속성에서

 

Mouse.cursor = MouseCursor.ARROW; 이렇게 주면된다.

 

AUTO : 자동

ARROW : 화살표

BUTTON : 버튼 누를때 나오는 한손꾸락

HAND : 잡아당길때 나오는 손바닥

IBEAM : 텍스트 창에서 나오는 I모양

 

예) mouseOver="Mouse.cursor = MouseCursor.BUTTON;" 이렇게 하면 된다.

출처 : http://blog.naver.com/PostView.nhn?blogId=sehwanq&logNo=50091363895

Posted by 1010
반응형


위 처럼 컨트롤 포인트를 이용하여 사이즈를 조절하는 컴포넌트를 만들려면...

1. 우선 각각의 포인트가 되는 사각형을 만듭니다.

ControlPoint.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" 
   width="9" height="9">
 
 <s:Rect width="9" height="9">
  <s:fill>
   <s:SolidColor />
  </s:fill>
 </s:Rect>
</s:Group>


2. 그 다음 위 검정색 사각형을 위치시켜 놓을 컨트롤 박스(Group)를 만들고 위 사각형을 제 위치에 놓습니다.

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   xmlns:control="org.jhl.control.*"
   width="100" height="100">
 
 <fx:Script>
  <![CDATA[
   private var _currentPointID:String;
   private var _startPointX:Number = 0;
   private var _startPointY:Number = 0;
   private var _x:Number;
   private var _y:Number;
   private var _width:Number;
   private var _height:Number;
   
   protected function mouseDownListener( event:MouseEvent ):void
   {
    _startPointX = this.parent.mouseX;
    _startPointY = this.parent.mouseY;
    _currentPointID = ControlPoint(event.target).id;
    _x = this.x;
    _y = this.y;
    _width = this.width;
    _height = this.height;
    
    this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, moveListener);
    this.systemManager.addEventListener(MouseEvent.MOUSE_UP, upListener);
   }
  
   
   protected function moveListener( event:MouseEvent ):void
   {
    var pointer:ControlPoint = event.target as ControlPoint;
    
    var dx:Number = this.parent.mouseX - _startPointX;
    var dy:Number = this.parent.mouseY - _startPointY;
    
    if( _currentPointID == "topLeft" )
    {
     this.x = _x + dx;
     this.width = _width - dx;
     this.y = _y + dy;
     this.height = _height - dy;
    }
    else if( _currentPointID == "topCenter" )
    {
     this.y = _y + dy;
     this.height = _height - dy;
    }
    else if( _currentPointID == "topRight" )
    {
     this.width = _width + dx;
     this.y = _y + dy;
     this.height = _height - dy;
    }
    else if( _currentPointID == "middleLeft" )
    {
     this.x = _x + dx;
     this.width = _width - dx;
    }
    else if( _currentPointID == "middleRight" )
    {
     this.width = _width + dx;
    }
    else if( _currentPointID == "bottomLeft" )
    {
     this.x = _x + dx;
     this.width = _width - dx;
     this.height = _height + dy;
    }
    else if( _currentPointID == "bottomCenter" )
    {
     this.height = _height + dy;
    }
    else if( _currentPointID == "bottomRight" )
    {
     this.width = _width + dx;
     this.height = _height + dy;
    }
    
    event.updateAfterEvent();
   }
   
   
   protected function upListener( event:MouseEvent ):void
   {
    this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, moveListener);
    this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, upListener);
   }


    override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
   {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    
    var g:Graphics = this.graphics;
    
    g.clear();
    g.lineStyle(1, 0x000000);
    g.drawRect(0, 0, unscaledWidth, unscaledHeight);
   }
  ]]>
 </fx:Script>
  
 <control:ControlPoint id="topLeft" left="-4" top="-4" 
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="topCenter" top="-4" horizontalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="topRight" right="-4" top="-4"
        mouseDown="mouseDownListener(event)" />
 
 <control:ControlPoint id="middleLeft" left="-4" verticalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="middleRight" right="-4" verticalCenter="0"
        mouseDown="mouseDownListener(event)"/>
 
 <control:ControlPoint id="bottomLeft" left="-4" bottom="-5"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="bottomCenter" bottom="-5" horizontalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="bottomRight" right="-4" bottom="-5"
        mouseDown="mouseDownListener(event)" />
 
</s:Group>



이 컴포넌트를 이용하여 다음과 같은 결과물을 얻을 수 있습니다.


p.s. 하양감자님의 지적부분을 수정하여 업데이트 하였습니다.

Flex 4 배포버전 : 4.0.0.14159 [2010/03/21]
Flex 4 현재버전 : 4.1.0.16076 [2010/06/10]



어제 만든 컴포넌트를 활용하여 원을 컨트롤하는 컴포넌트를 만들어 볼려고 합니다.


위 그림 처럼 외부는 컨트롤하는 외곽선과 컨트롤 점들로 그리고 내부는 원, 여기서 원이 사각형 또는 다각형의 모양일 수도 있구요

이렇게 구성하기 위해 먼저 원을 그리면..

Circle.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   width="100" height="100">
 
 <fx:Script>
  <![CDATA[
   override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
   {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    
    var g:Graphics = this.graphics;
    
    g.clear();
    g.lineStyle(1, 0x000000);
    g.beginFill(0xEEEEEE);
    g.drawEllipse(0, 0, unscaledWidth, unscaledHeight);
    g.endFill();
   }
  ]]>
 </fx:Script>
  
</s:Group>

그리고 어제 만든 컴포넌트를 원 컴포넌트에 추가하면...
(원 컴포넌트를 컨트롤 하기 위해 컨트롤 컴포넌트에 target 이라는 속성을 둬서 원 컴포넌트를 컨트롤 하게 합니다.)

Circle.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   xmlns:control="org.jhl.control.*"
   width="100" height="100">
 
 <fx:Script>
  <![CDATA[
   override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
   {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    
    var g:Graphics = this.graphics;
    
    g.clear();
    g.lineStyle(1, 0x000000);
    g.beginFill(0xEEEEEE);
    g.drawEllipse(0, 0, unscaledWidth, unscaledHeight);
    g.endFill();
   }
  ]]>
 </fx:Script>

 <control:ControlBox target="{this}" width="{this.width}" height="{this.height}"/>

</s:Group>

그리고 아래는 수정된 컨트롤 컴포넌트...

ControlBox.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   xmlns:control="org.jhl.control.*"
   width="100" height="100" >
 
 <fx:Script>
  <![CDATA[
   import mx.core.UIComponent;
   private var _currentPointID:String;
   private var _startPointX:Number = 0;
   private var _startPointY:Number = 0;
   private var _x:Number;
   private var _y:Number;
   private var _width:Number;
   private var _height:Number;
   private var _target:UIComponent = null;
   
   
   public function set target( value:UIComponent ):void
   {
    _target = value;
   }


   protected function mouseDownListener( event:MouseEvent ):void
   {
    _startPointX = _target.parent.mouseX;
    _startPointY = _target.parent.mouseY;
    _currentPointID = ControlPoint(event.target).id;
    _x = _target.x;
    _y = _target.y;
    _width = _target.width;
    _height = _target.height;
    
    this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, moveListener);
    this.systemManager.addEventListener(MouseEvent.MOUSE_UP, upListener);
   }
  
   
   protected function moveListener( event:MouseEvent ):void
   {
    var dx:Number = _target.parent.mouseX - _startPointX;
    var dy:Number = _target.parent.mouseY - _startPointY;
    
    if( _currentPointID == "topLeft" )
    {
     _target.x = _x + dx;
     _target.width = _width - dx;
     _target.y = _y + dy;
     _target.height = _height - dy;
    }
    else if( _currentPointID == "topCenter" )
    {
     _target.y = _y + dy;
     _target.height = _height - dy;
    }
    else if( _currentPointID == "topRight" )
    {
     _target.width = _width + dx;
     _target.y = _y + dy;
     _target.height = _height - dy;
    }
    else if( _currentPointID == "middleLeft" )
    {
     _target.x = _x + dx;
     _target.width = _width - dx;
    }
    else if( _currentPointID == "middleRight" )
    {
     _target.width = _width + dx;
    }
    else if( _currentPointID == "bottomLeft" )
    {
     _target.x = _x + dx;
     _target.width = _width - dx;
     _target.height = _height + dy;
    }
    else if( _currentPointID == "bottomCenter" )
    {
     _target.height = _height + dy;
    }
    else if( _currentPointID == "bottomRight" )
    {
     _target.width = _width + dx;
     _target.height = _height + dy;
    }
    
    event.updateAfterEvent();
   }
   
   
   protected function upListener( event:MouseEvent ):void
   {
    this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, moveListener);
    this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, upListener);
   }
   
   
   override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
   {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    
    var g:Graphics = this.graphics;
    
    g.clear();
    g.lineStyle(1, 0x000000);
    g.drawRect(0, 0, unscaledWidth, unscaledHeight);
   }
  ]]>
 </fx:Script>
  
 <control:ControlPoint id="topLeft" left="-4" top="-4" 
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="topCenter" top="-4" horizontalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="topRight" right="-4" top="-4"
        mouseDown="mouseDownListener(event)" />
 
 <control:ControlPoint id="middleLeft" left="-4" verticalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="middleRight" right="-4" verticalCenter="0"
        mouseDown="mouseDownListener(event)"/>
 
 <control:ControlPoint id="bottomLeft" left="-4" bottom="-5"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="bottomCenter" bottom="-5" horizontalCenter="0"
        mouseDown="mouseDownListener(event)" />
 <control:ControlPoint id="bottomRight" right="-4" bottom="-5"
        mouseDown="mouseDownListener(event)" />
 
</s:Group>

아래는 위 코드의 결과물입니다.


Flex 4 배포버전 : 4.0.0.14159 [2010/03/21]
Flex 4 현재버전 : 4.1.0.16076 [2010/06/10]


컨트롤 포인트를 이용해서 그림을 컨트롤 할 수 있는 소스입니다.

Image.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   xmlns:control="org.jhl.control.*"
   width="64" height="64">
 
 <fx:Script>
  <![CDATA[
   override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
   {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    
    img.width = unscaledWidth;
    img.height = unscaledHeight;
   }
  ]]>
 </fx:Script>
 
 <s:BitmapImage id="img" source="@Embed('assets/rss.png')" />
 
 <control:ControlBox target="{this}" width="{this.width}" height="{this.height}"/>
 
</s:Group>

 




ControlBox 는 전에 올린 내용을 참고하시면 됩니다.



Posted by 1010
반응형

import java.io.*;
import java.net.*;

/* 843포트에서 대기하는 서버소켓은 클라이언트가 접속하여 정책파일을 요청하면 정책파일의 내용을
 * 출력스트림으로 전송해 주고, 소켓을 닫는다.
 * 액션스크립트 클라이언트(Flex)에서 서버(채팅서버 등)에 접속하기 위해서는 서버가 실행중인 호스트에
 * 이 정책파일서버가 먼저 실행되고 있어야 한다.
 */
public class PolicyServerServlet {

 public static void main(String[] args) throws Exception {
  ServerSocket ss = new ServerSocket(843);
  Socket client = null;
  PrintWriter toClient = null;
  System.out.println("정책파일서버실행....");
  while (true) {
   client = ss.accept();
   InputStreamReader isr = new InputStreamReader(
     client.getInputStream());
   char[] buf = new char[1024];
   int read = isr.read(buf);
   String request = new String(buf, 0, read);
   if (request.equals("<policy-file-request/>\0")) {
    System.out.println("정책파일요청접수됨");
   } else {
    System.out.println("정책파일요청아님");
    continue;
   }
   // System.out.println("정책파일서버요청문자열:"+request);
   toClient = new PrintWriter(client.getOutputStream());
   String policy = "<?xml version='1.0'?>";
   policy += "<cross-domain-policy>";
   policy += "<site-control permitted-cross-domain-policies='*'/>";
   policy += "<allow-access-from domain='*' to-ports='*' />";
   policy += "</cross-domain-policy>";
   toClient.println(policy);
   toClient.flush();
   client.close();
   System.out.println("정책파일 전송완료");
  }
 }
}

 

Posted by 1010
반응형

https://github.com/flex-users/flex-iframe/downloads

 

1. flexiframe.swc를 lib폴더에 삽입 

2. xmlns:code="http://code.google.com/p/flex-iframe/"

3. <code:IFrame source="http://www.naver.com" width="100%" height="100%"/>

 

Posted by 1010
반응형

출처 : http://distress.tistory.com/18

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"
 verticalScrollPolicy="off" horizontalScrollPolicy="off"
 fontSize="12" width="420" height="600">
<mx:Script>
 <![CDATA[
  import mx.collections.ArrayCollection;
  private var fontListAc:ArrayCollection;
  //Flex 에서 적용되는 폰트의 종류를 알아보도록 하자.
  //리스트에 나오는 폰트는 현재 시스템에 설치된 폰트일뿐...모두 사용가능한것은 아니다.
  //바뀌는것도 있고 아닌것도 있고....이걸 구별해서 적용 가능한 폰트만 쓸수있으면 좋겠는데....
  private function init():void{
   var allFonts:Array = Font.enumerateFonts(true);
   var text:String;

   fontListAc = new ArrayCollection();
   
   allFonts.sortOn('fontName', Array.CASEINSENSITIVE);
   for each(var font:Font in allFonts){
    fontListAc.addItem(font.fontName);
    //이 함수가 test_str 이 정상적으로 표시가능한지 아닌지 구별해 준다고는 나와있는데..
    //뭐 해봐도 항상 false 만 뱉어낸다. 사용을 잘못한건지....음....
    //font.hasGlyphs(test_str);
   }
   fontList.dataProvider = fontListAc;
  }
 ]]>
</mx:Script>
 <mx:TextArea id="sampleText" x="10" y="10" width="400" height="320">
  <mx:text>이 문장은 번역기일 뿐입니다.
  This statement is only a translation date.
  該聲明只是一個翻譯日期.
  この文は翻訳機である場合のみです.
  ★☆●◎◆□▲▽→♤♧⊙◈▤☎☜
  </mx:text>
 </mx:TextArea>
 <mx:Text x="339" y="340" text="fontSize:" width="70" textAlign="center" fontSize="13"/>
 <mx:NumericStepper id="fontSize" minimum="5" maximum="100" value="25"
  change="sampleText.setStyle('fontSize', fontSize.value);" creationComplete="sampleText.setStyle('fontSize', fontSize.value);"
  x="339" y="370" width="70" textAlign="center"/>
 <mx:List id="fontList" x="10" y="338" width="321" height="250"
  change="sampleText.setStyle('fontFamily', fontListAc.getItemAt(fontList.selectedIndex))"/>
</mx:Application>

 

Posted by 1010
반응형
줄바꿈을 처리할 때, 캐리지리턴이나 라인피드 문자로 처리하게 되는데,
이는 문자열을 다루는 프로그램마다 각기 방식이 다르다.

캐리지리턴 : \r
라인피드 : \n

일반적으로 \r\n 은 DOS/Windows 에서 줄바꿈을 처리할 때 사용하는 방식이고,
\n 은 Unix, C, Perl 등에서 줄바꿈에 사용하는 개행문자이다.

Flex에서 TextArea는 특이하게도 \r만으로도 개행을 시행하는데, 물론 \n만으로도 개행이 가능하다.
\r\n 은 두 줄을 띄워버린다.

따라서, Dos/Windows 프로그램으로 작성한 글을 받아서 TextArea에 출력할 때, 한 줄 개행이 두 줄로 개행되어 버리는 증상이 발생한다.

이때는 아래와 같이 처리하여 정상적인 출력을 가능하게 할 수 있다.


var rawString:String;
textArea.text = rawString.replace(/\r\n/g, "\r");

replace 첫번째 인자는 정규표현식이다. double qoute를 넣지 말자.
두번째 인자는 바꿀 String이다.

 

Posted by 1010
반응형

TextInput 으로 사용자에게 어떤 입력을 받게 되는 경우가 있습니다.

이때에 보다 많은 내용(예를 들어 사용자의 자기소개 같은 값)을 입력 받아야 하는 경우가 생기는데, 이때 사용하면 좋은 컴포넌트가 TextArea 입니다. TextArea 컴포넌트로 여러줄로 입력을 받게되면 사용자는 필연적으로 엔터키를 눌러 개행(줄바꿈)을 하게 되는데 오늘 이야기해보고자 하는 것은 이 개행에 대한 처리입니다.

문자열에 엔터를 처리하기 위해서 이스케이프 문자인 백슬래시(\)를 사용하여 처리를 하게 되는데, 보통 흔히 알고 있기로는 엔터를 처리하기 위해 \r\n 을 문자열에 포함시키면 된다고 아실 겁니다. 저도 학교에서 C수업을 들을때 그렇게 배웠습니다.

\r   : 캐리지리턴(carriage return) -  커서를 해당 줄의 처음으로 옮김
\n   : 라인피드(linefeed) - 커서를 해당 줄의 다음줄로 옮김


커서를 해당줄의 왼쪽으로 옮겨 다음줄로 내리면 엔터키를 친 것과 동일한 효과가 나오게 됩니다.
하지만 TextArea 에서는 \r 만으로 엔터키 처리를 하고 있습니다.


위와 같이 엔터키를 넣게 되면 실제로 TextArea의 text 속성에서 받는 문자열에는 "텍스트\r입력" 이라고 들어있게 되는 것이죠.

사용자에게 입력받은 해당 데이터를 서버에 저장하고 불러와 다시 TextArea 에 넣어줄때에 아무런 처리를 하지 않아도 상관없습니다. 어짜피 넣어진대로 다시 넣는 것이니까요. 하지만 서로 다른 언어에서 같은 데이터를 사용시에는 문제가 됩니다. 언어들마다 엔터의 처리가 다르기 때문이죠.


위에서 처럼 \r\n 으로 엔터키를 처리하는 경우도 있고, \r 만으로도, \n 만으로도 처리하는 경우가 있습니다. 만약 \r\n으로 엔터를 처리하는 시스템에서 만들어 놓은 문자열을 TextArea 에 대입하면 어떻게 될까요? "텍스트\r\n입력" 이라고 TextArea의 text 속성에 넣으면 아래와 같은 현상이 발생합니다.

위에서 보시는 것 처럼 \r\n 둘다 엔터키로 인식되네요.

참고로 말씀드리자면 MXML 상에서 위의 이스케이스 문자를 인식시키실때는 아래와 같이 하시면 됩니다.

  1. <mx:TextArea text="텍스트\r\n입력" />      <!-- 백슬러시(\)를 문자열로 인식함 -->    
  2. <mx:TextArea text="{'텍스트\r\n입력'}" />      <!-- 백슬러시(\)를 특수문자로 인식함 -->   

 

아무튼, 저는 이와 같은 문제를 자바로 구성된 서버를 이용하면서 겪게 되었습니다. 해당 서버를 이용하는 또다른 쪽이 델파이로 구성되어 있는데, 델파이에서는 \r\n 으로 엔터키를 표현하는데, 플렉스에서 받아오니 엔터가 2번 입력되는 것 처럼 보이는 것은 물론 Flex 쪽에서 생성한 문자열은 델파이에서 엔터키가 없는 상태로 출력되는 것이었습니다.
물론 더 좋은 방법들이 있을꺼라 생각되지만, 저는 플렉스쪽에서 변환해서 쓰고 저장시에도 변환해서 보내기로 결정을 했습니다.
그래서 아래와 같은 코드를 구현하였습니다.

  1.   
  2. public static function getStringForFlex(value:String):String  
  3. {   
  4.     var javaReturnExp:RegExp = /\r\n/g;             // \r\n 으로 된 문자열을 모두 찾는다.   
  5.     return value.replace(javaReturnExp, "\r");      // \r 으로 변경하여 반환한다.   
  6. }   
  7.   
  8. public static function getStringForJava(value:String):String  
  9. {   
  10.     var flexReturnExp:RegExp = /\r/g;               // \r 으로 된 문자열을 모두 찾는다.   
  11.     return value.replace(flexReturnExp, "\r\n");    // \r\n 으로 변경하여 반환한다.   
  12. }  


네이밍이 좀 별로네요.. ;;
엔터키의 처리가 다르다는 것을 알아두시면 좋겠네요. ;)


ps. Flash Player 10 이 공개된 이후 FP10 이 설치된 브라우저에서 이전 포스트의 swf 파일을 로드하지 못하는 경우가 생기네요.
정확하게 이유는 모르겠습니다. 티스토리 포럼에 같은 내용의 버그신고가 이어지고 있는데, 자세히 알아봐야겠습니다.

from http://blog.flashplatform.kr/189

[출처] Flex Textarea 개행문자|작성자

Posted by 1010
반응형

var result:String = value.toXMLString();    //String으로 변환  

var pattern:RegExp = /\n */g;   //개행문자를 없앨 정규식  


 result = result.replace(pattern, "");   //개행문자를 없엔다  

Posted by 1010
반응형
var paths:Array = ['one/two/three','one/two/four','five/six'];
var pathsCollection:ArrayCollection = new ArrayCollection();

for(var i:int = 0 ; i < paths.length ; i++){
   
var folderArr:Array = paths[i].split('/');
   
var folderNum:int = folderArr.length;
   
var folderLabel:String = '';
   
for(var j:int = 0 ; j < folderNum; j++){
        trace
(folderLabel+folderArr[j]);
        pathsCollection
.addItem({label:folderLabel+folderArr[j],level:j,path:folderArr});
        folderLabel
+= '...';
   
}
}

 

Posted by 1010
반응형

출처 : http://sjp007.mireene.com/tc/entry/Tip-5?category=4

 

*세션 가져오는 법
SessionV fooAttrib = new SessionV();
Vector objList = new Vector();
try{
       fooAttrib=(SessionV)flashgateway.Gateway.getHttpRequest().getSession().getAttribute("ss_SVS");
objList.add(fooAttrib);
DataGrid
createApp => if(aReDeviceInfo == undefined || aReDeviceInfo.length<1){
                              dgDevice.rowCount = 0;
                              addRow();
                   }else{
                              dgDevice.rowCount = aReDeviceInfo.length;
                   }

funciton showDetail(event):Void{
     cidVboxSub.visible = true;
     cidVboxSub.height = "100%";
     stackNum.text = dgDevice.getItemAt(event.ItemIndex).STACK;
     cidNum.text = event.itemIndex;
     cidDeviceSLSizeX.text = dgDevice.getItemAt(event.itemIndex).SLSIZE_X;
     for(var j=0;j<3;j++){
             if(dia.getItemAt(j).LABEL == dgDevice.getIntemAt                                  (event.itemIndex.WFDIAMETER){
               dia.selectedIndex = j;
              }
      }

function addRow():Void{
  aReDeviceInfo.push({STACK:String(aReDeviceInfo.length+1),GCM_CODE:" ",......
                                MASTER_SEQ:" "
                               });
                               dgDevice.dataProvider = aReDeviceInfo;
                               crateApp();

<focusing Out 할 때마다>
private function setGridValues(compId):Void{
   if(compId == "cidDeviceSLSizeX"){
         dgDevice.getItemAt(Number(cidNum.text)).SLSIZE_X = this[compId].text;
   }

< mx:DataGrid id="dgDevice" width="766" cellpress="showDetail(event)"
  showHeaders="false" cellFocusOut="sizeChange(event)"
  <mx:DataGridColumn cellRendrer="{com.infonia.rendere.DeviceDelRenderer}"

 

Posted by 1010
반응형

출처 : http://sjp007.mireene.com/tc/entry/Flex-Log-log4j-%C3%B3%B7%B3-%BB%E7%BF%EB%C7%CF%B1%E2?category=4

 

///////////////////////////////////////////////////////////////
// LogUtil.as
///////////////////////////////////////////////////////////////

package utils
{
        import flash.utils.getQualifiedClassName;
       
        import mx.logging.ILogger;
        import mx.logging.Log;
        import mx.logging.LogEventLevel;
        import mx.logging.targets.TraceTarget;

        public class LogUtil
        {
               
                public function LogUtil()
                {
                       
                }
               
                public static function initLogging():void{
                        //create a Target
                        var logTarget:TraceTarget = new TraceTarget();
                       
                        logTarget.filters = ["none"];        //이부분을 적절히 변경해주면 된다. Ex> "comp.*"
                       
                        //Log all log levels
                        logTarget.level = LogEventLevel.DEBUG;
                       
                        //Add category, date, time, and log level to the output
                        logTarget.includeCategory = false;
                        logTarget.includeDate = true;
                        logTarget.includeTime = true;
                        logTarget.includeLevel = true;
                       
                        //Begging logging
                        Log.addTarget(logTarget);
                }
               
                public static function getLogger(c:*):ILogger{
                        var className:String = getQualifiedClassName(c).replace("::", ".");
                        return Log.getLogger(className);
                }
        }
       
}


///////////////////////////////////////////////////////////////
// Main Application
///////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                           layout="vertical"
                           xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
                           xmlns:comp="comp.*"
                           creationComplete="creationCompleteHdlr()">
       
        <fx:Declarations>
                <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
       
        <fx:Script>
                <![CDATA[
                        import utils.LogUtil;
                       
                       
                        private function creationCompleteHdlr():void{
                                LogUtil.initLogging();
                        }
                       
                ]]>
        </fx:Script>
       
        <comp:LogComp1/>
        <comp:LogComp2/>
</mx:Application>


///////////////////////////////////////////////////////////////
// LogComp1.mxml
///////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
                 xmlns:s="library://ns.adobe.com/flex/spark"
                 xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
       
        <fx:Declarations>
                <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
       
        <fx:Script>
                <![CDATA[
                        import flash.utils.getQualifiedClassName;
                       
                        import mx.logging.ILogger;
                        import mx.logging.Log;
                       
                        import utils.LogUtil;
                       
                        private var logger:ILogger = LogUtil.getLogger(this);
                       
                        private function test():void{
                                logger.debug("comp1 debug test");
                        }
                ]]>
        </fx:Script>
       
        <s:Button label="log comp1" click="test()"/>
</s:Group>


///////////////////////////////////////////////////////////////
// LogComp2.mxml
///////////////////////////////////////////////////////////////

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
                 xmlns:s="library://ns.adobe.com/flex/spark"
                 xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">
       
        <fx:Declarations>
                <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
       
        <fx:Script>
                <![CDATA[
                        import mx.logging.ILogger;
                        import mx.logging.Log;
                       
                        import utils.LogUtil;
                       
                        private var logger:ILogger = LogUtil.getLogger(this);
                       
                        private function test():void{
                                logger.debug("comp2 debug test");
                        }
                ]]>
        </fx:Script>
       
        <s:Button label="log comp2" click="test()"/>
</s:Group>

 

Posted by 1010
반응형

출처 : http://sjp007.mireene.com/tc/?page=5

 

구성

Adobe Flash Builder 4.6 Premium

Spring 3.2 FrameWork

Tomcat 7.0(Web Application Server)

MyBatis 3.2(iBatis 2.5 이후로 아파치 재단 지원력에서는 현재의 정보와 신기술을 맞춰갈 수 없다 판단하여 구글 코드 팀으로 옮겼단다.)

blazeds 4.0(데이타 서비스 통신)

spring-flex-1.5 integration(Spring 과 Flex를 통신하기 위해 직접 클래스를 만들어 써야 하는 수고가 없도록 spring project 팀들이 고맙게도 만들어 두었다. ㄱㅅㄳ~)

SLF4J(Simple logging Facade for Java) (로깅찍는거) 요즘 이거 많이쓴다.

이유는 : http://devday.tistory.com/entry/SLF4J%EC%9D%98-%EC%9E%A5%EC%A0%90 참고.

일단 플렉스를 이클립스의 플러그인으로 깔고 톰캣도 설치되있다는 전제하에 시작.

먼저 이클립스의 왼쪽 빈공간에서 마우스 오른쪽을 눌러 New > Flex Project를 선택.

사용자 삽입 이미지

Project name에 자기가 입력하고 싶은 프로젝트 이름을 입력. Next

사용자 삽입 이미지


Application Server Type은 자바를 이용할것이니 Java, Use remote object access service는 blazeds를 이용할 것이니 그곳을 선택.

 

Java source folder 는 src로 그냥 나두어도 되는데 나는 java_src(flex는 flex_src로 되있는데 자바는 src로 되있으면 이샹해서;;)로 바꿔줬다.

Output folder 역시 기본은 bin-debug나 WebContent로 바꿔 주었다.(즉 나는 컴파일된 파일을 WebContent 밑으로 바로 놓겠다는 거다)

Target runtime 옆의 New 버튼을 클릭.

사용자 삽입 이미지


Apach 폴더의 자기에 맞는(나는 7.0)버젼을 찾아 선택해 주면 아래의 항목들이 기본으로 보인다. Finish를 눌러 완료.

사용자 삽입 이미지


이제 톰캣을 설정하였으므로 Target runtime에서 콤보박스 화살표를 누르면 방금 설치한 이름의 톰캣이 보인다.

 

그걸로 바꿔주고 Next.

사용자 삽입 이미지


Output folder URL에 일단 로컬에서 돌리기때문에 톰캣의 기본설정 포트 8080으로 Context root가 TEST 이므로 TEST 위와 같이 한다. Finish.

사용자 삽입 이미지


보면 output folder를 바꿨기 때문에 bin-debug 폴더가 안보이고 WebContent 폴더밑으로 기본 파일들이 생긴걸 확인할 수 있다.

 

다음으로 Spring과 Flex를 연동 해야한다.

모든 jar파일들은 합해놓은게 http://blog.naver.com/sjp007774/150153185137 여기에 있다.

먼저 Spring을 사용하기 위하여 다운.

http://www.springsource.org/download/community

다운받은 Spring 폴더의 libs(3.2 기준)밑의 필요한 파일들(난 그냥 잘몰라서 다 복사하였다;;)을 복사.

MyBatis를 사용하기 위하여 MyBatis를 다운.

http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DMyBatis

다운 받은 MyBatis 폴더의 jar파일(mybatis-3.2.0-SNAPSHOT.jar)을 복사.

MyBatis와 Spring을 연동하기 위하여 필요한 jar파일을 다운.

http://code.google.com/p/mybatis/downloads/list?q=label:Product-Spring

다운받은 폴더의 jar파일(mybatis-spring-1.1.1.jar)을 복사.

Spring의 Aspect을 사용하기 위해(3.0 부터는 Aspectj 관련 jar파일들이 함께 있지 않다.) 다운.

http://www.eclipse.org/aspectj/downloads.php

주의 할게 내가 잘몰라 이상한걸 받았을수도 있는데 다른 파일들은 모두 zip으로 압축이 되있는반면 jar로 압축이 되있었다. 압축을 풀면 lib폴더가 보인다.
(이것때문에 엄청 고생했다. 당연히 jar파일이라서 그대로 넣으면 될줄 알았다 ㅠㅠ)

압축을 푼 lib 폴더 밑의 jar파일들(aspectjrt.jar, aspectjtools.jar, aspectjweaver.jar, org.aspectj.matcher.jar 이역시 몰라서 다 복사했다;;)을 복사.

Spring의 AOP alliance(namespace AOP를 사용할 수 있게 해줌)를 사용하기 위하여 다운.

http://sourceforge.net/projects/aopalliance/

이아이는 바로 jar파일로되있었다.

aopalliance.jar 파일을 복사.

SLF4J(log4j 같은거) 를 사용하기 위하여 다운.

http://slf4j.org/download.html

다운받은 폴더의 jar파일들(slf4j-api-1.7.2.jar, slf4j-log4j12-1.7.2.jar)을 복사.

log4jdbc(쿼리의 ?에 바로 값을 대입하여 보여줌)를 사용하기 위하여 다운.

http://code.google.com/p/log4jdbc/downloads/list

다운받은 lib폴더의 jar파일(slf4j-api-1.6.0.jar)을 복사.

log4j(로깅 찍는거)를 사용하기 위하여 다운.

log4j-1.2.16.jar 파일을 복사

지금까지 복사한 모든 파일들을 WebContent/WEB-INF/lib 폴더밑으로 다 넣는다.

사용자 삽입 이미지


다음으로 WEB-INF/web.xml 파일을 수정해야 된다.

 

[web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>TEST</display-name>

        <context-param>
                <param-name>flex.class.path</param-name>
                <param-value>/WEB-INF/flex/hotfixes,/WEB-INF/flex/jars</param-value>
        </context-param>

        <!-- Http Flex Session attribute and binding listener support
        <listener>
                <listener-class>flex.messaging.HttpFlexSession</listener-class>
        </listener>-->
       
        <listener>
         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
         </listener>

        <!-- MessageBroker Servlet
        <servlet>
                <servlet-name>MessageBrokerServlet</servlet-name>
                <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
                <init-param>
                        <param-name>services.configuration.file</param-name>
                        <param-value>/WEB-INF/flex/services-config.xml</param-value>
                </init-param>
                <init-param>
                        <param-name>flex.write.path</param-name>
                        <param-value>/WEB-INF/flex</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
        </servlet>
       
        <servlet-mapping>
                <servlet-name>MessageBrokerServlet</servlet-name>
                <url-pattern>/messagebroker/*</url-pattern>
        </servlet-mapping>-->
       
        <servlet>
         <servlet-name>MessageBrokerServlet</servlet-name>
         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <init-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>
                     /WEB-INF/configs/web-application-config.xml
                     /WEB-INF/configs/bean-remoting-destination.xml
                     /WEB-INF/configs/mybatis-config.xml
             </param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
         </servlet>

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

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

        <!-- for WebSphere deployment, please uncomment -->
        <!--
                <resource-ref>
                <description>Flex Messaging WorkManager</description>
                <res-ref-name>wm/MessagingWorkManager</res-ref-name>
                <res-type>com.ibm.websphere.asynchbeans.WorkManager</res-type>
                <res-auth>Container</res-auth>
                <res-sharing-scope>Shareable</res-sharing-scope>
        </resource-ref>
        -->
</web-app>

servlet-name을 MessageBrokerServlet으로 하였기때문에 spring에서 MessageBrokerServlet-servlet.xml을 찾으려 할것이다.

하지만 파일들을 다른걸로 할거기 때문에 ContextLoaderListener를 달아준다.

xml파일 하나에 모든걸 다 때려넣을 수도 있지만 spring에서도 권장하듯이 서비스단, 데이타단, 화면단, 보안단 등등 이렇게 분할해 놓는게 나중에 유지보수 하기에도 좋다.

나는 설정을 가지고 있는 web-application-config.xml, flex의 remote object의 destination과 해당 자바정보를 갖고 있는 bean-remoting-destination.xml, 마지막으로

MyBatis에 관련한 mybatis-config.xml 세가지 xml로 분류하여 WEB-INF/configs 라는 폴더 밑에 넣어두었다.

servlet-mapping의 url-pattern의 /messagebroker/* (flex의 AMF통신) 오는건 spring의 DispatcherServlet 클래스에서 처리하게된다.

[web-application-config.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
                          
        <!-- MessageBroker Configuration -->                      
    <bean id="widwinMessageBroker" class="org.springframework.flex.core.MessageBrokerFactoryBean"/>
 
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
            p:mappings="/*=widwinMessageBroker"/>
       
    <bean class="org.springframework.flex.servlet.MessageBrokerHandlerAdapter"/>                                            
                          
    <!-- Properties Configuration -->
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                <property name="locations">
                        <list>
                                <value>classpath*:resources/properties/**/*.properties</value>
                        </list>
                </property>
        </bean>
   
    <!-- MyBatis Configuration -->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
                <property name="configLocation">
                        <value>/WEB-INF/configs/mybatis-config.xml</value>
                </property>
                <property name="dataSource" ref="dataSource" />
                <property name="mapperLocations" value="classpath*:resources/mappers/**/*.xml" />
        </bean>
       
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> 
                <constructor-arg index="0" ref="sqlSessionFactoryBean" />
        </bean>
       
    <!-- DataSource Configuration -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="${jdbc.widwin.driverClassName}"/>
                <property name="url" value="${jdbc.widwin.url}"/>
                <property name="username" value="${jdbc.widwin.username}"/>
                <property name="password" value="${jdbc.widwin.password}"/>
        </bean>

        <!-- Transaction Configuration -->
        <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
                <property name="transactionManager">
                        <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                                <property name="dataSource" ref="dataSource"/>
                        </bean>
                </property>
                <property name="transactionAttributes">
                        <props>
                                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                                <prop key="update*">PROPAGATION_REQUIRED</prop>
                                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                        </props>
                </property>
        </bean>
       
        <!-- Common Logger Configuration -->
        <aop:aspectj-autoproxy/>
        <bean id="commonLogger" class="test.widwin.common.CommonLogger"/>
       
        <!-- <bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
       
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource">
                        <ref local="dataSource"/>
                </property>
                <property name="nativeJdbcExtractor">
                        <ref local="nativeJdbcExtractor"/>
                </property>
        </bean> -->
</beans>

properties configuration에서 반드시 classpath*를 붙여주어야한다. 상대경로로 찾기때문에 안붙여주면 찾지 못한다.

[jdbc.test.properties]

#jdbc.widwin.driverClassName= oracle.jdbc.OracleDriver
jdbc.widwin.driverClassName=net.sf.log4jdbc.DriverSpy

#jdbc.widwin.url=jdbc:oracle:thin:@xxx.xxx.x.x:1521:TEST
jdbc.widwin.url=jdbc:log4jdbc:oracle:thin:@xxx.xxx.x.x:1521:TEST
jdbc.widwin.username=TEST
jdbc.widwin.password=test

slf4j를 사용하면 driverClassName과 url에 log4jdbc를 끼어넣어야 함.(xxx 를 아이피로 바꿔주면 됨)

[bean-remoting-destination.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:flex="http://www.springframework.org/schema/flex"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd
                           http://www.springframework.org/schema/flex
                           http://www.springframework.org/schema/flex/spring-flex-1.5.xsd">
                          
        <!--         <context:annotation-config/>                            -->
        <context:component-scan base-package="test.widwin.blogics.board"/>                
        
    <bean class="test.widwin.blogics.board.BoardController">
                <flex:remoting-destination destination-id="BoardRO" message-broker="widwinMessageBroker"/>
        </bean>
 
</beans>

<context:component-scan... 이 있으면 <bean에 class를 설정하지 않아도 됨. destination에 message-broker 꼭 설정해줘야 함. remoting-config.xml 파일은 관리안함.

[mybatis-config.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
        <!-- <environments default="development">
                <environment id="development">
                        <transactionManager type="JDBC"/>
                        <dataSource type="POOLED">
                                <property name="driver" value="${driver}"/>
                                <property name="url" value="${url}"/>
                                <property name="username" value="${username}"/>
                                <property name="password" value="${password}"/>
                        </dataSource>
                </environment>
        </environments>
       
        <settings>
                <setting name="cacheEnabled" value="true"/>
                <setting name="lazyLoadingEnabled" value="true"/>
                <setting name="multipleResultSetsEnabled" value="true"/>
                <setting name="useColumnLabel" value="true"/>
                <setting name="useGeneratedKeys" value="false"/>
                <setting name="autoMappingBehavior" value="PARTIAL"/>
                <setting name="defaultExecutorType" value="SIMPLE"/>
                <setting name="defaultStatementTimeout" value="25000"/>
                <setting name="safeRowBoundsEnabled" value="false"/>
                <setting name="mapUnderscoreToCamelCase" value="false"/>
                <setting name="localCacheScope" value="SESSION"/>
                <setting name="jdbcTypeForNull" value="OTHER"/>
                <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
        </settings> -->
       
        <!-- <mappers>
                <mapper resource="resources/mappers/BoardMapper.xml"/>
        </mappers> -->
       
        <typeAliases>
                <typeAlias alias="Board" type="test.widwin.blogics.board.vo.BoardBean"/>
        </typeAliases>
       
</configuration>

<mappers>부분을 주석을 풀어서 관리해도 되나 web-application-config.xml에서 mapperLocations를 *로 잡아주었으므로

따로 관리하지 않아도 된다.

[TEST.mxml]

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                           xmlns:s="library://ns.adobe.com/flex/spark"
                           xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
       
        <fx:Script>
                <![CDATA[
                        import mx.collections.ArrayCollection;
                        import mx.controls.Alert;
                        import mx.rpc.events.FaultEvent;
                        import mx.rpc.events.ResultEvent;
                       
                        import test.widwin.modules.board.vo.BoardVO;
                        import test.widwin.utils.RemoteObjectUtil;
                       
                        private function test2():void{
                                RemoteObjectUtil.doMethod("BoardRO", "getBoardList", getBoardListRstHdlr, [1]);
                        }
                       
                        private function insertBoard():void{
                                var vo:BoardVO = new BoardVO();
                                vo.name = tiName.text;
                                vo.title = tiTitle.text;
                                vo.description = tiDescription.text;
                                vo.pass = tiPass.text;
                                RemoteObjectUtil.doMethod("BoardRO", "insertBoard", insertBoardRstHdlr, [vo]);
                        }
                       
                        private function getBoardListRstHdlr(evt:ResultEvent):void{
                                adg.dataProvider = evt.result as ArrayCollection;
                        }
                       
                        private function insertBoardRstHdlr(evt:ResultEvent):void{
                                Alert.show("등록 성공");
                        }
                       
                        private function faultHdlr(evt:FaultEvent):void{
                                Alert.show(evt.fault.message.toString());
                        }
                ]]>
        </fx:Script>
       
        <fx:Declarations>
               
        </fx:Declarations>
       
        <s:layout>
                <s:VerticalLayout/>
        </s:layout>
       
        <s:Button label="test" click="test2()"/>
       
        <mx:AdvancedDataGrid id="adg">
                <mx:columns>
                        <mx:AdvancedDataGridColumn headerText="이름" dataField="name"/>
                        <mx:AdvancedDataGridColumn headerText="제목" dataField="title"/>
                        <mx:AdvancedDataGridColumn headerText="내용" dataField="description"/>
                </mx:columns>
        </mx:AdvancedDataGrid>
       
        <s:Form id="frm" defaultButton="{btnIns}">
                <s:FormHeading label="게시판" backgroundColor="haloSilver" />
                <s:FormItem sequenceLabel="i)" label="이름:" required="true">
                        <s:TextInput id="tiName" maxChars="64" />
                </s:FormItem>
                <s:FormItem sequenceLabel="ii)" label="제목:">
                        <s:TextInput id="tiTitle" maxChars="64" />
                </s:FormItem>
                <s:FormItem sequenceLabel="iii)" label="내용:" required="true">
                        <s:TextInput id="tiDescription" maxChars="32" />
                </s:FormItem>
                <s:FormItem sequenceLabel="iv)" label="비밀번호:" required="true">
                        <s:TextInput id="tiPass" maxChars="32" displayAsPassword="true" />
                </s:FormItem>
                <s:FormItem>
                        <s:Button id="btnIns" label="등록" click="insertBoard()" />
                </s:FormItem>
        </s:Form>

</s:Application>

[BoardVO.as]

package test.widwin.modules.board.vo
{

         [RemoteClass(alias="test.widwin.blogics.board.vo.BoardBean")]        
        public class BoardVO
        {
                public var board_code:int;
                public var registration_date:String;
                public var name:String;
                public var title:String;
                public var description:String;       
                public var email:String;       
                public var homepage:String;       
                public var ip:String;        
                public var pass:String;       
                public var pos:int;       
                public var hit:int;
                public var file_yn:String;       
                public var depth:int;
                public var is_delete:String;
                public var created_timestamp:Date;
                public var creator_code:String;
                public var updated_timestamp:Date;
                public var updater_code:String;
                public var total_row:int;
                public var page:int;
        }
}

[BoardController.java]

package test.widwin.blogics.board;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import test.widwin.blogics.board.service.IBoardService;
import test.widwin.blogics.board.vo.BoardBean;

@Controller
public class BoardController {
//        final Logger logger = LoggerFactory.getLogger(BoardController.class);
       
        @Autowired
        private IBoardService iBoardService;
       
        public List<BoardBean> getBoardList(int pageView){
                return iBoardService.getBoardList(pageView);
        }
       
        public int insertBoard(BoardBean boardBean){
                return iBoardService.insertBoard(boardBean);
        }
       
}

[IBoardService.java]

package test.widwin.blogics.board.service;

import java.util.List;

import test.widwin.blogics.board.vo.BoardBean;

public interface IBoardService {
        public List<BoardBean> getBoardList(int pageView);
       
        public int insertBoard(BoardBean boardBean);

}

[BoardServiceImpl.java]

package test.widwin.blogics.board.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import test.widwin.blogics.board.dao.BoardDao;
import test.widwin.blogics.board.vo.BoardBean;

@Service("iBoardService")
public class BoardServiceImpl implements IBoardService {
       
        @Autowired
        private BoardDao boardDao;
       
        @Override
        public List<BoardBean> getBoardList(int pageView) {
                return boardDao.getBoardList(pageView);
        }

        @Override
        public int insertBoard(BoardBean boardBean) {
                return boardDao.insertBoard(boardBean);
        }
       
}

[BoardDao.java]

package test.widwin.blogics.board.dao;

import java.util.List;

import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.stereotype.Repository;

import test.widwin.blogics.board.vo.BoardBean;


@Repository("boardDao")
public class BoardDao extends SqlSessionDaoSupport{
//        @Resource(name="sqlSessionTemplate")
//        private SqlSession sessionTemplate;
       
        public List<BoardBean> getBoardList(int pageView){
//                IBoardMapper iBoardMapper = sessionTemplate.getMapper(IBoardMapper.class);
//                return iBoardMapper.getBoardList(pageView);
                return getSqlSession().selectList("test.widwin.blogics.board.dao.IBoardMapper.getBoardList", pageView);
        }
       
        public int insertBoard(BoardBean boardBean){
                return getSqlSession().insert("test.widwin.blogics.board.dao.IBoardMapper.insertBoard", boardBean);
        }
       
}

신기한게 내부적으로 구현이 되있는진 몰라도 패키지 인터페이스명.메소드 이름하고 BoardMapper.xml 에서 같은 인터페이스이름으로 namespace를 정의하면 된다.

[IBoardMapper.java]

package test.widwin.blogics.board.dao;

import java.util.List;

import test.widwin.blogics.board.vo.BoardBean;

public interface IBoardMapper {
        public List<BoardBean> getBoardList(int pageView);

        public int insertBoard(BoardBean boardBean);
       
}

[BoardMapper.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="test.widwin.blogics.board.dao.IBoardMapper">
        <select id="getBoardList" parameterType="int" resultType="Board">
                SELECT *
            FROM (SELECT BOARD.* ,ROWNUM AS RNUM ,FLOOR(((ROWNUM-1)/15)+1) AS PAGE
                     ,COUNT(*) OVER() AS TOTAL_ROW
                FROM (SELECT *
                      FROM BOARD
                      ORDER BY BOARD_CODE DESC) BOARD)                                    
            WHERE PAGE = #{pageView}
            ORDER BY POS ASC      
        </select>
       
        <insert id="insertBoard" parameterType="Board">
                INSERT INTO BOARD(BOARD_CODE, REGISTRATION_DATE, NAME, TITLE, DESCRIPTION, PASS, IP)
                VALUES((SELECT TRIM(NVL(MAX(BOARD_CODE + 1),1)) FROM BOARD), '201212', #{name}, #{title}, #{description}, #{pass}, '192.168.0.9')
        </insert>
</mapper>

namespace가 인터페이스랑 같아야한다.

[log4j.xml] log4j.properties로 관리해도 됨(log4j.xml이 가독성도 좋고 관리가 용이함)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<!-- An example log4j configuration xml file for log4jdbc -->
<!-- Logging levels are:                                  -->
<!-- DEBUG < INFO < WARN < ERROR < FATAL                  -->

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <appender name="stdout-appender" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %c{1}: %m%n"/>
    </layout>
  </appender>

  <appender name="sql-appender" class="org.apache.log4j.FileAppender">
    <param name="File" value="./logs/sql.log"/>
    <param name="Append" value="false"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="-----&gt; %d{yyyy-MM-dd HH:mm:ss.SSS} &lt;%t&gt; %m%n%n"/>
    </layout>
  </appender>

  <appender name="sql-timing-appender" class="org.apache.log4j.FileAppender">
    <param name="File" value="./logs/sqltiming.log"/>
    <param name="Append" value="false"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="-----&gt; %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n"/>
    </layout>
  </appender>

  <appender name="jdbc-appender" class="org.apache.log4j.FileAppender">
    <param name="File" value="./logs/jdbc.log"/>
    <param name="Append" value="false"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
    </layout>
  </appender>

  <appender name="jdbc-connection" class="org.apache.log4j.FileAppender">
    <param name="File" value="./logs/connection.log"/>
    <param name="Append" value="false"/>
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
    </layout>
  </appender>

  <!--
       The Following 5 logs can be turned on and off while the server is running
       LIVE in order to trace the SQL and/or all JDBC coming out of the application.

       To turn a log on, set the level value to INFO or DEBUG (to see class name and
       line number information in the log)  The DEBUG setting is much more inefficient
       but the output is much more useful.

       To turn off JDBC logging completely, you must set all 5 logs to a level higher
       than ERROR (FATAL is suggested.)
  -->

  <!-- log SQL (pre-execution) plus exceptions caused by SQL -->
  <logger name="jdbc.sqlonly" additivity="false">
    <level value="debug"/>
    <appender-ref ref="sql-appender"/>
  </logger>

  <!-- log SQL with timing information, post execution -->
  <logger name="jdbc.sqltiming" additivity="false">
    <level value="debug"/>
    <appender-ref ref="stdout-appender"/>
<!--     <appender-ref ref="sql-timing-appender"/> -->
  </logger>

  <!-- only use the two logs below to trace ALL JDBC information,
       NOTE:  This can be very voluminous!  -->

  <!-- log all jdbc calls except ResultSet calls -->
  <logger name="jdbc.audit" additivity="false">
    <level value="fatal"/>
    <appender-ref ref="jdbc-appender"/>
  </logger>

  <!-- log the jdbc ResultSet calls -->
  <logger name="jdbc.resultset" additivity="false">
    <level value="fatal"/>
    <appender-ref ref="jdbc-appender"/>
  </logger>
 
  <!-- log connection open/close events and dump of all open connection numbers -->
  <logger name="jdbc.connection" additivity="false">
    <level value="fatal"/>
    <appender-ref ref="connection-appender"/>
  </logger>

  <!-- this log is for internal debugging of log4jdbc, itself -->
  <!-- debug logging for log4jdbc itself -->
  <logger name="log4jdbc.debug" additivity="false">
    <level value="debug"/>
    <appender-ref ref="stdout-appender"/>
  </logger>

  <!-- by default, log everything to the console with a level of WARN or higher -->
  <root>
    <level value="debug"/>
    <appender-ref ref="stdout-appender"/>
  </root>
</log4j:configuration>

[applicationContext.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:flex="http://www.springframework.org/schema/flex"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd
                           http://www.springframework.org/schema/flex
                           http://www.springframework.org/schema/flex/spring-flex-1.5.xsd">
</beans>

리스너를 따로 달아줬어도 applicationContext.xml은 WEB-INF/밑에 위치하여야 함.

[service-config.xml]

<?xml version="1.0" encoding="UTF-8"?>
<services-config>

    <services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="proxy-config.xml" />
        <service-include file-path="messaging-config.xml" />    
        <default-channels>
           <channel ref="my-amf"/>
        </default-channels>       
    </services>

    <security>
        <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
        <!-- Uncomment the correct app server
        <login-command class="flex.messaging.security.TomcatLoginCommand" server="JBoss">
                <login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/>       
        <login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/>
        <login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/>
        -->

        <!--
        <security-constraint id="basic-read-access">
            <auth-method>Basic</auth-method>
            <roles>
                <role>guests</role>
                <role>accountants</role>
                <role>employees</role>
                <role>managers</role>
            </roles>
        </security-constraint>
         -->
    </security>

    <channels>

        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>

        <channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
            <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
        </channel-definition>

        <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
            <properties>
                <polling-enabled>true</polling-enabled>
                <polling-interval-seconds>4</polling-interval-seconds>
            </properties>
        </channel-definition>

        <!--
        <channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/>
        </channel-definition>

        <channel-definition id="my-secure-http" class="mx.messaging.channels.SecureHTTPChannel">
            <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/httpsecure" class="flex.messaging.endpoints.SecureHTTPEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
        </channel-definition>
        -->
    </channels>

    <logging>
        <target class="flex.messaging.log.ConsoleTarget" level="Error">
            <properties>
                <prefix>[BlazeDS] </prefix>
                <includeDate>false</includeDate>
                <includeTime>false</includeTime>
                <includeLevel>false</includeLevel>
                <includeCategory>false</includeCategory>
            </properties>
            <filters>
                <pattern>Endpoint.*</pattern>
                <pattern>Service.*</pattern>
                <pattern>Configuration</pattern>
            </filters>
        </target>
    </logging>

    <system>
        <redeploy>
            <enabled>false</enabled>
            <!--
            <watch-interval>20</watch-interval>
            <watch-file>{context.root}/WEB-INF/flex/services-config.xml</watch-file>
            <watch-file>{context.root}/WEB-INF/flex/proxy-config.xml</watch-file>
            <watch-file>{context.root}/WEB-INF/flex/remoting-config.xml</watch-file>
            <watch-file>{context.root}/WEB-INF/flex/messaging-config.xml</watch-file>
            <watch-file>{context.root}/WEB-INF/flex/data-management-config.xml</watch-file>
            <touch-file>{context.root}/WEB-INF/web.xml</touch-file>
             -->
        </redeploy>
    </system>

</services-config>

<default-channels 꼭 달아주어야 함.

BoardRO destination을 못 찾을때

[.flexProperties]

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flexProperties enableServiceManager="false" flexServerFeatures="4" flexServerType="8" flexWarLocation="C:/자료/교육시이트/blazeds-bin-4.0.0.14931/blazeds.war" serverContextRoot="/TEST" serverRoot="C:/testWorkspace/TEST/WebContent" serverRootURL="http://localhost:8080/TEST" toolCompile="true" useServerFlexSDK="false" version="2"/>

serverContextRoot가 /WebContent로 잡혀있는데 꼭 맞는 contextRoot 바꿔줘야 함(여기서는 /TEST)

flex bug report에 기재되있음 http://bugs.adobe.com/jira/browse/FB-20894

Posted by 1010
반응형

Working with States in Flex 4
by Frank Sommers
September 16, 2009

Advertisements

Summary
Flex 4's new syntax simplifies working with application states. This article provides a tutorial introduction into UI state management with Flex 4, and includes a complete example.

Stateless Web applications aim to store as little state on the server as possible. Reducing, or even eliminating, reliance on server-side state makes it easier to implement a scalable infrastructure, at least in principle.

At the same time, only the simplest Web applications can function completely without state. Dispatching a request to an online weather reporting service may work in a purely stateless fashion, but more sophisticated applications must keep track of where a user is in a complex data entry process, possible data validation errors, and so on. Data-intensive applications may also need to cache a user's frequently accessed data in order to reduce response time.

Client-Side State

Instead of storing state data on the server, rich-client applications may choose to store such information on the client. A key benefit of rich-client frameworks is that they provide APIs and programming language constructs that make it easier to work with application state on the client. In addition to client-side collections APIs and language support for data processing, rich-client frameworks typically offer high-level constructs to manage application state related to display logic as well.

Consider, for example, a sign-in component typical of many Web applications: A user is presented with text input boxes to enter a user name and a password, as well as a button to initiate the sign-in. A login box may also provide a handy way for the user to create a new account. If the user chooses to register a new account, another view is presented with text boxes for additional information, such as first and last names, and so forth:

Click on "Need to register?" to toggle between UI states. To view the source code, right-click or control-click on the application.

In a traditional, server-generated HTML user interface, the server may return an entirely newly rendered page when a user chooses to register instead of signing in. By contrast, a rich-client can affect the change in the user interface entirely on the client side, without interaction from the server.

The simplest way to code that is to write display logic that inserts and removes new labels and text boxes in the UI at runtime, for instance, by modifying the UI's DOM in the browser. More sophisticated rich-client frameworks, however, provide a much handier abstraction to accomplish the same goal: UI states.

UI States in Flex

A UI state is the set of all components and component properties in effect in a component at any given point in time. Multiple UI states can be associated with a component: Switching from one state to another causes the rich-client runtime to add, remove, or modify components based on the differences between states. The login form, for instance, could have "login" and "register" states: The register state defines additional input boxes, changes the label of the button component from "Sign in" to "Register", and also causes the button click to invoke a register() method instead of signin().

In Flex, defining and working with application states has been possible since the 2.0 version of the Flex SDK. In Flex versions 2 and 3, states were defined inside a states array in an MXML document; inside each state definition, in turn, were declarations of what should be added, removed, or modified, related to some base state. It was also possible to build one state on another.

 

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"> 

  <mx:Script>
      <![CDATA[
            private function signin():void {
                // Implementation of signin
            }

            private function register():void {
                // Implementation of register
            }
        ]]>
  </mx:Script>

  <mx:states>

    <mx:State name="Register">        

        <mx:AddChild relativeTo="{loginForm}" position="lastChild" creationPolicy="all">
            <mx:FormItem id="frmPasswordConfirm" label="Confirm:">
                <mx:TextInput id="passwordConfirm" displayAsPassword="true"/>
            </mx:FormItem>        
        </mx:AddChild>

        <mx:AddChild relativeTo="{loginForm}" position="lastChild">
            <mx:FormItem label="First name:" id="frmFirstName">
                <mx:TextInput id="firstName" width="220"/>
            </mx:FormItem>
        </mx:AddChild>

        <mx:AddChild relativeTo="{loginForm}" position="lastChild">            
            <mx:FormItem label="Last name:" id="frmLastName">
                <mx:TextInput id="lastName" width="220"/>
            </mx:FormItem>
        </mx:AddChild>

        <mx:AddChild relativeTo="{loginButton}" position="after">
            <mx:LinkButton label="Return to login" click="setCurrentUIState()"/>
        </mx:AddChild>            

        <mx:RemoveChild target="{registerLink}"/>            

        <mx:SetProperty target="{loginLabel}" name="text" value="Create a new account:"/>    
        <mx:SetProperty target="{loginButton}" name="enabled" value="false"/>
        <mx:SetProperty target="{loginButton}" name="label" value="Register"/>
            
     </mx:State>        

  </mx:states>
    
 <mx:Label text="Sign In:" 
            fontWeight="bold" paddingLeft="12" fontSize="14" 
            id="loginLabel" width="100%"/>
        
        <mx:Form id="loginForm" width="100%">

            <mx:FormItem label="Email:" id="frmEmail">
                <mx:TextInput id="email" width="220"/>
            </mx:FormItem>            

            <mx:FormItem label="Password:" id="frmPassword">
                <mx:TextInput id="password" displayAsPassword="true" width="220"/>
            </mx:FormItem>        
        </mx:Form>

        <mx:CheckBox id="rememberMe" label="Remember me on this computer"    
            paddingLeft="77" selected="true"/>

        <mx:ControlBar width="100%"    paddingLeft="84">
            <mx:Button label="Sign in" id="loginButton" click="signin()" enabled="false"/>            
            <mx:LinkButton label="Need to Register?" id="registerLink"
                click="currentState='Register'"/>            
        </mx:ControlBar>
</mx:VBox>

Listing 1: Login box with Flex 3

In the above Flex 3.0 implementation, AddChild and RemoveChild tags indicate that the runtime should add or remove child components, respectively, in the register state. The SetProperty tag, in turn, changes the button's label to "Register," and the SetEventHandler tag ensures that a register() method is invoked when the UI is the register state. Clicking on the LinkButton component toggles between the signin and register states.

While the Flex 2 and 3 state syntax works well, adding and removing components is rather cumbersome: For instance, you have to specify where new components are to be added apart from the new components' parents. UI components supporting a large number of states end up becoming unwieldy, with significant portions of related UI logic scattered across a large MXML file.

Flex 4's State Improvements

To simplify state definition, Flex 4 introduces a new states syntax. Although the various component states are still declared inside the states tag, the definition of each state is specified inline. To see how that works, consider the Flex 4 implementation of the login component. To make the Flex 4 implementation mirror the Flex 3 version as closely as possible, we didn't define separate component and skin files, a Flex 4 best practice:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/halo">
	
    <fx:Script>
        <![CDATA[
            private function signin(): void {
                 // Implementation of signin 
            }

            private function register(): void {
                // Implementation of register
            }
        ]]>
    </fx:Script>
	
    <s:states>
        <s:State name="signin"/>
        <s:State name="register"/>
    </s:states>
	
    <s:Group id="mainGroup">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
		
    <mx:Label text="Sign in:" fontWeight="bold" paddingLeft="12" fontSize="14" id="loginLabel" width="100%"/>
		
    <mx:Form id="loginForm" width="100%" paddingTop="3" paddingBottom="3">

        <mx:FormItem label="First name:" includeIn="register" id="firstNameItem" alpha="0.0">
            <s:TextInput id="firstName" width="220"/>
        </mx:FormItem>

        <mx:FormItem label="Last name:" includeIn="register" id="lastNameItem" alpha="0.0">
            <s:TextInput id="lastName" width="220"/>
        </mx:FormItem>

        <mx:FormItem label="Email:" id="emailItem">
            <s:TextInput id="email" width="220"/>			
        </mx:FormItem>

        <mx:FormItem label="Password:" id="passwordItem">
            <s:TextInput id="password" displayAsPassword="true" width="220"/>
        </mx:FormItem>

        <mx:FormItem label="Confirm:" includeIn="register" id="confirmItem" alpha="0.0">
             <s:TextInput id="passwordConfirmation" displayAsPassword="true" width="220"/>			
        </mx:FormItem>
    </mx:Form>

    <s:Group>
        <s:layout>
            <s:HorizontalLayout paddingLeft="100"/>
        </s:layout>
        <s:Button label="Sign in" label.register="Register" id="loginButton" 
            enabled="true" click.signin="signin()" click.register="register()"/>
			
        <mx:LinkButton label="Need to register?" 
            click="currentState = 'register'" includeIn="signin"/>
        <mx:LinkButton label="Return to signin"
            click="currentState = 'signin'" includeIn="register"/>
     </s:Group>
		
    <mx:CheckBox id="rememberMe" label="Remember me on this computer" paddingLeft="110"/>
 </s:Group>
</s:Application>

Listing 2: Login box with Flex 4 state syntax

Instead of AddChild and RemoveChild methods, components that should be visible in the register state only are added an includeIn="register" tag. You can specify a comma-separated list of state names for the includeIn tag. Flex 4 also provides an excludeFrom tag, if you need to declare what states a component should be removed from. This new syntax allows you to declare components in place, inside the parent.

Properties can similarly be set inline using a new dot-separated syntax. For example, the Button component's label property is defined as follows:

... label="Sign in" label.register="Register" 

This tells Flex to set the button's label property to "Register" in the register state, and to "Sign in" in other states (the default). And listeners can be declared similarly: When the component is in the register state, the register() method is invoked on a button click, otherwise the signin() method is called:

click="signin()" click.register="register()"

The new component syntax makes it much easier to define sophisticated components with relatively straightforward, declarative code. The Flex 4 component states syntax also supports state groups as well as the ability to assign a new parent to a component. It is important to note that the new syntax only impacts MXML declarations—which is what the Flex compiler uses to generate ActionScript code. States can be defined in ActionScript as well, but that syntax does not change in Flex 4.

Flex gives you convenient ways not only to define component states, but also to specify transitions between states. To make the transition between the signin and register states smoother, this example includes a transition effect between those states. A forthcoming Artima article will describe Flex 4 transitions in greater detail.

Share Your Opinion

Have an opinion on Flex 4's states syntax? Discuss this article in the Articles Forum topic, Working with States in Flex 4.

Resources

Adobe's Flash Builder 4
http://labs.adobe.com/technologies/flashbuilder4

Flex 4 SDK
http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK

Gumbo Project
http://opensource.adobe.com/wiki/display/flexsdk/Gumbo

Flex.org
http://www.flex.org

About the Authors

Frank Sommers is Editor-in-Chief of Artima.

Posted by 1010
반응형

 

 

BlazeDS 와 스프링(Spring) 연동하기

 

출처 : http://youthgonewild.co.kr/category/FLEX

 

blazeds-spring-beta1.jar



BlazeDS를 이용하여 Remote Object Service를 이용할 때 스프링과 연동할 수는 없을까 라는 의문을 가지고
자료를 찾아보았습니다. 역시 이미 연동해서 사용하는 방법이 있더군요

다음의 remoting-config.xml 파일을 봅시다.

 <!-- 스프링 프레임워크를 이용한 remote object -->
<destination id="simpleLoadService">
 <properties>
  <factory>springfactory</factory> 
  <source>simpleLoadDao</source> 
 </properties>
</destination>    

일반적인 destination을 정의하는 부분과 다릅니다. 바로 <factory>라는 부분인데요, springfactory 라는
새로운 factory를 정의해서 스프링과 remote object를 연결시실수 있습니다.
그러면 springfactory 가 정의된 부분이 있어야 겠죠?

바로 services-config.xml 파일에 정의합니다.

 <!-- 스프링 프레임워크를 사용할수 있게 하기 위한 팩토리 설정  -->
 <factories>
  <factory id="springfactory" class="flex.messaging.factory.SpringFactory" /> 
 </factories>


위의 내용이 springfactory를 정의한 부분입니다.
이제 이 factory를 통해서 스프링과 remote object가 연결됩니다.
그러면 flex.messaging.factory.SpringFactory 는 원래 flex package에 존재하는 클래스일까요?
그렇지 않습니다. 스프링과의 연동을 위해 따로 제작된 클래스죠. 저도 외국 사이트에서 다운로드 했습니다.
첨부파일로 올리니 다운 받아서 lib에 등록해서 사용하시면 됩니다..


remoting-config.xml 에서 source로 설정되어 있는 simpleLoadDao도 마저 살펴봅시다.
스프링의 bean설정파일인 applicationContext.xml 파일에 등록되어 있겠죠.

applicationContext.xml

 <bean id="simpleLoadDao" class="flexintegration.spring.sample.SimpleLoadDao">
   <property name="sqlMapClient" ref="sqlMapClient" />
  </bean>

 <!-- SqlMap setup for iBATIS Database Layer : 스프링 프레임워크와 iBATIS의 연동  -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="WEB-INF/ibatis/sql-map-config.xml" />
  <property name="dataSource" ref="dataSource" />
 </bean>

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
  </bean>

  <bean id="propertyConfigurer" 
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="locations">
          <list>
              <value>classpath:jdbc.properties</value>
          </list>
      </property>
  </bean>


이렇게 설정이 되면 Remote Object로 바로 스프링의 DI(Dependency Injection)를 이용하는 bean을 
사용할수가 있게 됩니다. ( iBatis를 이용하고 있어서 iBatis에 대한 경험이 없으시면 약간 이해하기
힘들수도 있겠네요 )

여기까지 Remote Object로 스프링 bean을 연동해서 사용하는 방법에 대해서 알아보았습니다.
Remote Object로 스프링의 강력한 DI를 바로 사용할 수 있다는 건 대단한 장점이죠.

참고로 AOP도 Remote Object 사용시 제대로 동작합니다. ( 테스트 해 보았죠 )

스프링과의 연동을 생각하셨던 분들에게 도움이 되셨기를...

 

Posted by 1010
반응형

출처 : http://softworld.tistory.com/entry/Flex-4Blazeds-Spring-%EC%84%A4%EC%A0%95-%EC%99%84%EB%A3%8C%EB%90%9C-war

 

blazeds-spring.war

 

blazeds.war

 

Adobe가 제공 다운로드에다가 장난질을 쳐놨넹..

Turnkey안에 spring 설정된 war가 있었는데 지워놓은듯... spring설정시 의존성때문에 잘 되지도 않더만 이걸 지워 놓으면 고생할 사람많겠구만...

LiveCycle Data Services살릴려고 Blazeds는 개발 완전 중단되있고 그나마 남은 Freamwork는 graniteds

우선 제공되는 blazeds + spring 연동 war file을 남겨 본다. Test 결과는 잘 돌아감!!!

blazeds-spring.war

Blazeds Ver.4 + Spring Ver.3.0.1

spring ver.을 최신으로 올려봤지만 의존성때문에 잘 안됨..

blazeds.war

기본 Blazeds ver.4 도 올려 놓는다!

Posted by 1010
반응형

출처 : http://lahuman.tistory.com/55

 

주요 몇가지 소스를 간단히 소개 하면,

1. /WEB-INF/web.xml


 <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
 <servlet>
     <servlet-name>Spring MVC Dispatcher Servlet</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>

 <!-- Map all *.spring requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>


2. /WEB-INF/flex/services-config.xml

        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>


3. application-context.xml

 <!-- Maps request paths at /* to the BlazeDS MessageBroker -->
 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">
         <value>
             /*=mySpringManagedMessageBroker
         </value>
     </property>
 </bean>
 
 <!-- Dispatches requests mapped to a MessageBroker -->
 <bean class="org.springframework.flex.messaging.servlet.MessageBrokerHandlerAdapter"/>
 <!-- Bootstraps and exposes the BlazeDS MessageBroker -->
 <bean id="mySpringManagedMessageBroker" class="org.springframework.flex.messaging.MessageBrokerFactoryBean" /> 
    <!-- Implementation of ProductDAO using low-level JDBC -->
    <bean id="productDAO" class="flex.spring.samples.product.ProductDAO" >
        <constructor-arg ref="dataSource"/>
    </bean>
   
 <!-- Expose the productDAO bean for BlazeDS remoting -->
 <bean id="product" class="org.springframework.flex.messaging.remoting.FlexRemotingServiceExporter">
     <property name="messageBroker" ref="mySpringManagedMessageBroker"/>
     <property name="service" ref="productDAO"/>
 </bean>
   



위 예제를 보면 Spring MVC를 이용해서 flex BlazeDS를 호출 한다.

아래 파일을 찬찬히 봐라!

Posted by 1010
반응형

시스템 환경

BlazeDS 4.0.x

Spring 3.0.x

SBI 1.3 or 1.5

 

Webapplicationcontext.xml에서 <flex-remoting> 태그 사용시 발생하는 오류

예)

    <bean id="SimpleExampleService2" class="com.mydomain.data.SimpleExample">

        <flex:remoting-destination/>

    </bean>

 

오류메시지

SEVERE: Context initialization failed

org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.flex.core.MessageInterceptionAdvice] for bean with name 'org.springframework.flex.core.MessageInterceptionAdvice#0' defined in null: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1211)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:568)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getType(AbstractBeanFactory.java:523)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.findRemotingDestinations(RemotingAnnotationPostProcessor.java:148)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.postProcessBeanFactory(RemotingAnnotationPostProcessor.java:79)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:624)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:614)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:398)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

Caused by: java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

    at java.lang.ClassLoader.defineClass1(Native Method)

    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)

    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1814)

    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:868)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1321)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1200)

    at org.springframework.util.ClassUtils.forName(ClassUtils.java:258)

    at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:408)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1229)

    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1200)

    ... 30 more

Feb 20, 2012 5:19:32 PM org.apache.catalina.core.ApplicationContext log

SEVERE: StandardWrapper.Throwable

org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.flex.core.MessageInterceptionAdvice] for bean with name 'org.springframework.flex.core.MessageInterceptionAdvice#0' defined in null: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1211)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:568)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getType(AbstractBeanFactory.java:523)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.findRemotingDestinations(RemotingAnnotationPostProcessor.java:148)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.postProcessBeanFactory(RemotingAnnotationPostProcessor.java:79)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:624)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:614)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:398)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

Caused by: java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

    at java.lang.ClassLoader.defineClass1(Native Method)

    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)

    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1814)

    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:868)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1321)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1200)

    at org.springframework.util.ClassUtils.forName(ClassUtils.java:258)

    at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:408)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1229)

    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1200)

    ... 30 more

Feb 20, 2012 5:19:32 PM org.apache.catalina.core.StandardContext loadOnStartup

SEVERE: Servlet /web1 threw load() exception

java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

    at java.lang.ClassLoader.defineClass1(Native Method)

    at java.lang.ClassLoader.defineClass(ClassLoader.java:620)

    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1814)

    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:868)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1321)

    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1200)

    at org.springframework.util.ClassUtils.forName(ClassUtils.java:258)

    at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:408)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1229)

    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1200)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:568)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getType(AbstractBeanFactory.java:523)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.findRemotingDestinations(RemotingAnnotationPostProcessor.java:148)

    at org.springframework.flex.config.RemotingAnnotationPostProcessor.postProcessBeanFactory(RemotingAnnotationPostProcessor.java:79)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:624)

    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:614)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:398)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

 

해결방법

Aopalliance-1.0.jar lib폴더에 추가

 

오류메시지

SEVERE: Context initialization failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBrokerDefaultHandlerMapping': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBroker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)

    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBroker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1401)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:392)

    at org.springframework.context.support.AbstractApplicationContext.isSingleton(AbstractApplicationContext.java:1024)

    at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:370)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.registerHandlers(SimpleUrlHandlerMapping.java:129)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.initApplicationContext(SimpleUrlHandlerMapping.java:104)

    at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)

    at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:71)

    at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)

    at org.springframework.context.support.ApplicationContextAwareProcessor.doProcess(ApplicationContextAwareProcessor.java:116)

    at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:99)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    ... 31 more

Caused by: org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.flex.core.MessageBrokerFactoryBean.afterPropertiesSet(MessageBrokerFactoryBean.java:185)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)

    ... 50 more

Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)

    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)

    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)

    at org.springframework.flex.core.EndpointConfigProcessor.processAfterStartup(EndpointConfigProcessor.java:69)

    at org.springframework.flex.core.MessageBrokerFactoryBean.processAfterStart(MessageBrokerFactoryBean.java:294)

    at org.springframework.flex.core.MessageBrokerFactoryBean.afterPropertiesSet(MessageBrokerFactoryBean.java:168)

    ... 52 more

Feb 20, 2012 5:21:11 PM org.apache.catalina.core.ApplicationContext log

SEVERE: StandardWrapper.Throwable

org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBrokerDefaultHandlerMapping': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBroker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)

    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_messageBroker': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1401)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:392)

    at org.springframework.context.support.AbstractApplicationContext.isSingleton(AbstractApplicationContext.java:1024)

    at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:370)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.registerHandlers(SimpleUrlHandlerMapping.java:129)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.initApplicationContext(SimpleUrlHandlerMapping.java:104)

    at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)

    at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:71)

    at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)

    at org.springframework.context.support.ApplicationContextAwareProcessor.doProcess(ApplicationContextAwareProcessor.java:116)

    at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:99)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    ... 31 more

Caused by: org.springframework.beans.factory.BeanInitializationException: MessageBroker initialization failed; nested exception is org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.flex.core.MessageBrokerFactoryBean.afterPropertiesSet(MessageBrokerFactoryBean.java:185)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)

    ... 50 more

Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)

    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)

    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)

    at org.springframework.flex.core.EndpointConfigProcessor.processAfterStartup(EndpointConfigProcessor.java:69)

    at org.springframework.flex.core.MessageBrokerFactoryBean.processAfterStart(MessageBrokerFactoryBean.java:294)

    at org.springframework.flex.core.MessageBrokerFactoryBean.afterPropertiesSet(MessageBrokerFactoryBean.java:168)

    ... 52 more

Feb 20, 2012 5:21:11 PM org.apache.catalina.core.StandardContext loadOnStartup

SEVERE: Servlet /web1 threw load() exception

org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.

    at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)

    at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)

    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)

    at org.springframework.flex.core.EndpointConfigProcessor.processAfterStartup(EndpointConfigProcessor.java:69)

    at org.springframework.flex.core.MessageBrokerFactoryBean.processAfterStart(MessageBrokerFactoryBean.java:294)

    at org.springframework.flex.core.MessageBrokerFactoryBean.afterPropertiesSet(MessageBrokerFactoryBean.java:168)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:392)

    at org.springframework.context.support.AbstractApplicationContext.isSingleton(AbstractApplicationContext.java:1024)

    at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.registerHandler(AbstractUrlHandlerMapping.java:370)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.registerHandlers(SimpleUrlHandlerMapping.java:129)

    at org.springframework.web.servlet.handler.SimpleUrlHandlerMapping.initApplicationContext(SimpleUrlHandlerMapping.java:104)

    at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)

    at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:71)

    at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)

    at org.springframework.context.support.ApplicationContextAwareProcessor.doProcess(ApplicationContextAwareProcessor.java:116)

    at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:99)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1394)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)

    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)

    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)

    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)

    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)

    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)

    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:443)

    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:459)

    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:340)

    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:307)

    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)

    at javax.servlet.GenericServlet.init(GenericServlet.java:211)

    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1164)

    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:984)

    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4043)

    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4349)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)

    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)

    at org.apache.catalina.core.StandardService.start(StandardService.java:450)

    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)

    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:287)

    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)

 

해결방법

cglib-nodep-2.2.jar 라이브러리 추가

 

참조

http://develop.sunshiny.co.kr/80 (스프링 라이브러리 의존성)

Posted by 1010
반응형

3.Spring BlazeDS Integration 설치

본 문서에서는 Flex Plugin을 사용하지 않고 별도로 Flex개발 환경을 구성하는 방법에 대해서 다루도록 한다. Spring BlazeDS Integration을 설치 하기 위해서는 BlazeDS가 먼저 설치 되어야 한다. Web Application 프로젝트에 BalzeDS를 설치 한 후, Spring BlazeDS Integration을 추가로 설치 하는 방법에 대해 살펴 보도록한다.

3.1.BlazeDS의 설치

Adobe Open Source Site에서 최신 버전의 BlazeDS을 다운 받을 수 있다. Turnkey버전과 Binary Distribution을 다운 받을 수 있다. Turnkey의 경우 BlazeDS설치 파일 이외에 Reference 문서, Sample Application, BlazeDS Console Application등이 포함되어 있다.

BlazeDS를 다운 받아 압축을 풀면 blazeds.war파일이 포함되어 있는다. blazeds.war파일은 아래와 같은 폴더들로 구성된다.

다음은 각 폴더와 파일들에 대한 간략한 설명이다.

  • WEB-INF/web.xml : 어플리케이션의 배포지시자로 MessageBrokerServlet에 대한 Servlet설정과 HttpFlexSession 등에 대해 설정되어 있다. SpringBlazeDS Integration을 사용햘 경우에는 MessageBrokerServlet이 아닌 SpringMVC의 DispatcherServlet이 Client요청을 처리 할 수 있도록 Servlet설정을 변경해야 한다.

  • WEB-INF/flex : BlazeDS의 환경 설정 파일들이 있다. 서버측과 통신하기 위한 채널, 아답터, 로깅등의 정보가 세팅되어 있는 파일들이 위치한다.

  • WEB-INF/lib : BlazeDS 서버 측 라이브러리들이 위치해 있다.

3.1.1.BlazeDS 설정 파일

BlazeDS의 WEB-INF/flex폴더의 4개의 xml파일(services-config.xml, remoting-config.xml, proxy-config.xml, messaging-config.xml)을 Web Application Project의 {Web Root folder}/WEB-INF/flex란 이름의 폴더를 생성한 후 아래 그림과 같이 복사한다.

service-config.xml 파일을 열어 remoting-config.xml, messaging-config.xml파일의 include 부분을 삭제 또는 주석처리 한다. 두 파일을 include에서 제외하는 이유는 Spring BlazeDS Integration의 설정파일에서 Remoting, Messaging 통신에 대한 환경설정을 할 수 있기 때문이다. 그리고 Web Application 레벨의 default-channels을 설정한다. 아래는 수정된 service-config.xml파일의 일부이다.

<services-config>
    <services>
        <!-- service-include file-path="remoting-config.xml" / -->
        <service-include file-path="proxy-config.xml" />
        <!-- service-include file-path="messaging-config.xml" / -->  
        <default-channels>
        	<channel ref="my-amf"/>
    	</default-channels>      
    </services>

    <security>
    <!-- 중략 -->

3.1.2.BlazeDS 라이브러리

BlazeDS의 WEB-INF/lib폴더의 BlazeDS 서버 측 라이브러리를 Web Application Project의 {Web Root folder}/WEB-INF/lib폴더에 복사한다. 이 때 Web Application에 이미 등록되어 있는 라이브러리와 충돌나지 않도록 확인해서 복사한다. 예를들어 Anyframe의 Foundation Plugin으로 설치된 Web Application에는 common-logging-1.1.1.jar을 포함하고 있으므로 common-logging.jar은 제외한 후 복사한다.

3.2.Spring BlazeDS Integration 설치

BlazeDS설치가 끝났으면 Spring BlazeDS Integration을 Web Application에 설치 하도록 한다.

3.2.1.Spring BlazeDS Integration 라이브러리

Spring Source Community에서 Spring BlazeDS Integration 1.0.1을 다운 받아 org.springframework.flex-1.0.1.RELEASE.jar파일을 Web Application Project의 {Web Root folder}/WEB-INF/lib에 복사한다.

또 Spring BlazeDS Integration과 Dependency관계에 있는 jackson-core-asl-x.x.x.jar을 다운로드페이지에서 다운 받아 Web Application Project의 {Web Root folder}/WEB-INF/lib에 복사한다.

3.2.2.Servlet 설정

Spring BlazeDS Integration 라이브러리 복사가 끝났으면, Flex UI에서 RPC요청이 왔을 때 MessageBrokerServlet이 아닌 Spring MVC의 DispatcherServlet이 요청을 처리 할 수 있도록 web.xml파일에 Servlet설정을 아래와 같이 추가 한다. 이 때 Spring MVC에 대한 Servlet설정이 이미 정의되어 있으면 새로운 Servlet을 추가 정의한다.

<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/springmvc/common-servlet.xml,
                    classpath:/springmvc/generation-servlet.xml,	
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
	
<servlet>
    <servlet-name>SpringBlazeDS</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/springmvc/flex-servlet.xml
        </param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

위와 같이 SpringBlazeDS Servlet설정을 완료 한 후 아래와 같이 /messagebroker/*에 대한 요청을 SpringBlazeDS Servlet이 처리 할 수 있도록 servlet-mapping을 정의한다.

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

Flex Client에서 RemotingService, HTTPProxyService, MessageService의 Request url 패턴은 /messagebroker/*형태이다.

3.2.3.Spring WebApplicationContext 설정

Web Appliaction의 classpath:/spring위치에 Flex관련 Spring WebApplicationContext설정 파일(flex.xml)을 생성한다.

flex-servlet.xml파일을 열어 flex namespace를 사용하기 위해 다음과 같이 xsd를 정의한다.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:flex="http://www.springframework.org/schema/flex"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/flex 
	http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
		
	
</beans>

BlazeDS설정 파일인 services-config.xml파일을 읽어 MessageBrokerFactoryBean에 등록할 수 있도록 같이 flex namespace를 사용해 정의한다.

<flex:message-broker/>

위는 Default설정으로 services-config.xml파일이 classpath*:services-config.xml에 있을 경우에 사용할 수 있다. 추가적인 설정에 대해서는 Spring BlazeDS Integration Configuration을 참고한다.

3.3.Spring Bean Exporting

BlazeDS, Spring BlazeDS Integration의 설치가 끝났으면 Spring Bean을 Flex의 RemotingService가 접근 할 수 있도록 RemotingDestinationExporter에 등록한다. Spring Bean을 Exporting하기 위해서는 여러 방법이 있는데 여기에서는 @RemotingDestination annotation을 사용하도록 한다.

@Service("foundationGenreService")
@RemotingDestination
public class GenreServiceImpl implements GenreService {

	@Inject
	@Named("foundationGenreDao")
	private GenreDao genreDao;

	public List<Genre> getList() throws Exception {
		return genreDao.getList();
	}

}

@RemotingDestination annotation에 아무런 옵션을 주지 않으면 Bean Id가 Destination Id가 된다. 위의 소스코드에서는 foundationGenreService이 Destination Id가 되고 Flex Client에서는 foundationGenreService란 이름으로 해당 Service에 접근한다.

RemotingService가 접근 할 수 있도록 Spring Bean을 Exporting하는 자세한 방법은 Spring Blazeds Integration Configuration을 참고한다.

3.4.Flex Project 생성

Flex Web Application개발을 하기 위한 서버 측 설정이 완료 됐으면 Flex프로젝트를 생성한다. Flex UI를 개발하기 위해서는 편집기를 이용한 방법과 Flex Builder를 이용한 방법이 있다. Flex Builder는 Flex UI를 개발하기 위한 이클립스 기반의 상용 S/W 로 WYSIWYG Editor, mxml의 자동컴파일, 디버깅등 의 다양한 기능을 제공한다. 본 문서에서는 Flex Builder를 이용해 개발하는 방법에 대해서만 설명한다.

Adobe Flex Builder 3 Download에서 60일동안 사용가능한 Trial버전을 다운 받을 수 있다.

Flex Builder 3를 처음 실행 하게 되면 아래와 같은 화면을 볼 수 있다.

Flex Builder에서 File -> New -> Flex Project를 선택하면 새로운 Flex Project를 생성할 수 있다.

New Flex Project 창이 열리면 Project Name과 Flex Project의 Location등을 입력하고 Application type은 Web application(runs in Flash Player)을 선택, Server technology의 Application server type는 J2EE, Use remote object access service의 체크 박스를 선택, LiveCycle Data Services를 선택한 후 Next버튼을 클릭한다.

Configure J2EE Server창 Server location에서는 BlazeDS가 설치된 Web Application의 정보를 세팅한다. 서버 정보를 입력 한 후 Validate Configuration 버튼을 클릭해 BlazeDS가 설치 된 Web Application인지 확인한다.

Compiled Flex application location의 Output folder는 Flex Project가 컴파일 되서 위치할 경로를 입력한다. 일반적으로는 Web Application Project의 Web Root folder의 특정 폴더를 지정한다. 여기에서는 {Web Root folder}/flex를 Output folder로 설정했다. 입력이 끝났으면 Next버튼을 클릭한다.

다음으로는 Flex Project의 build path를 설정하는 창이 열리는데 Main application file에 Main Application mxml파일의 파일 이름을 입력한 후 Finish버튼을 클릭한다.

아래 그림과 같이 신규 프로젝트가 생성되고 Main Application mxml파일이 열리면 성공적으로 Flex Project가 생성된 것이다.

Web Application Project의 {Web Root folder}/flex폴더에 Flex Project가 컴파일 되어 아래와 같은 파일들이 생성된 것을 확인 할 수 있다. Flex Application Main Application mxml(main.mxml) 파일명(main)이 Flex Application 실행 html파일명(main.html)이 된다.

WAS를 시작해 Flex Application실행 html을 브라우저에서 호출한다.(http://localhost:8080/myproject/flex/main.html) 아래와 같이 화면이 출력 됐다면 Flex Project가 정상적으로 설치 된 것이다.

3.5.Remoting Service Call

Flex Applicatin Main mxml에서 Spring Bean(foundationGenreService)의 getList메소드를 호출한다. 아래와 같이 RemotingObject태그를 사용해 destination(Spring Bean)과 호출할 method를 정의한다.

<mx:RemoteObject id="remotingService" destination="foundationGenreService">
    <mx:method name="getList" result="resultHandler(event)"/>
</mx:RemoteObject>

foundationGenreService getList의 호출 결과는 resultHandler메소드에서 처리한다. 아래는 foundationGenreService getList메소드를 호출한 결과를 DataGird에 바인딩하는 예이다.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="getList()">
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;
			
            [Bindable]
            private var genreList:ArrayCollection;
			
            private function getList():void{
                remotingService.getList();
            }
			
            private function resultHandler(event:ResultEvent):void{
                genreList = event.result as ArrayCollection;
            } 
        ]]>
    </mx:Script>
	
    <mx:RemoteObject id="remotingService" destination="foundationGenreService">
        <mx:method name="getList" result="resultHandler(event)"/>		
    </mx:RemoteObject>
   <mx:Array id="columnsInfo">
		<mx:DataGridColumn dataField="genreId" headerText="GENRE ID" editable="true"/>
		<mx:DataGridColumn dataField="name" headerText="NAME" editable="true"/>	
	</mx:Array>
	
	<mx:DataGrid id="grdGenre" dataProvider="{genreList}" columns="{columnsInfo}"/>
</mx:Application>

위와 같이 작성 한 후 main.html을 호출 하면 다음과 같은 화면을 볼 수 있다.

 

4.Spring BlazeDS Integration 환경 설정

Spring BlazeDS Integration은 Flex를 이용해 Web Application을 개발 할 경우, 서버측과 RPC방식으로 통신할 때 필요한 BlazeDS를 Spring Framework와 연계하여 편리하게 사용할 수 있도록 한다. 복잡한 환경 설정이 flex namespace를 통해 간편해 졌고 Spring Bean을 Exporting하기 위한 annotation이 제공된다.

Spring BlazeDS Integration을 사용하기 위한 환경은 다음과 같다.

  • Java 5 이상

  • Spring 2.5.6 이상

  • Adobe BlazeDS 3.2 이상

4.1.Spring BlazeDS MessageBroker 환경 설정

4.1.1.Spring DispatcherServlet

BlazeDS 에서는 MessageBrokerServlet 을 front Controller 로 사용하여 Flex client 의 요청을 처리했다. Spring BlazeDS Integration 을 사용하면 Spring MVC 의 DispatcherServlet 이 Flex client 의 요청을 처리한다. 따라서 web.xml 에 아래와 같은 설정을 추가한다.

<servlet>
    <servlet-name>SpringBlazeDS</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/springmvc/flex-servlet.xml</param-value>
    </init-param>
</servlet>

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

4.1.2.MessageBroker

Spring BlazeDS Integration에서는 BlazeDS와 Spring과의 연계를 위한 복잡한 환경 설정을 간단히 하기 위해 flex namespace를 제공한다. flex namespace를 사용하기 위해서는 Spring WebApplicationContext 설정 파일에 다음과 같이 xsd를 정의를 추가한다.

<?xml version="1.0" encoding="UTF-8"?>	
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:flex="http://www.springframework.org/schema/flex" 
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/flex 
        http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
        
        ...
</bean>

web.xml 파일의 설정에 의해 flex client 의 요청을 DispatcherServlet 이 처리함으로 그 요청을 MessageBroker로 위임해야 한다.

MessageBroker 설정은 flex namespace 추가로 아래와 같이 간단한 설정만으로 가능하다.

<?xml version="1.0" encoding="UTF-8"?>	
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:flex="http://www.springframework.org/schema/flex" 
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/flex 
        http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
			
    <flex:message-broker />
</beans>

위의 설정의 경우 기본적으로 /WEB-INF/flex/services-config.xml 파일을 참조하게 된다. 설정 파일의 위치가 다를 경우 services-config-path attribute 설정을 통해 변경이 가능하다.

<flex:message-broker services-config-path="classpath*:services-config.xml" />

flex namespace를 사용하지 않을 때에는 아래와 같이 설정한다.

<bean id="messageBroker" 
           class="org.springframework.flex.core.MessageBrokerFactoryBean">
    <property name=""serviceConfigPath" value="classpath*:services-config.xml"/>
</bean>

Configuring the Spring DispatcherServlet에서 처럼 /messagebroker/*요청에 대한 servlet-mapping을 별도로 설정하지 않고 모든 요청에 대해서 DispatcherServlet이 처리 할 경우 /messagebroker/*에 대한 요청을 MessageBroker가 처리 하기 위해서는 아래와 같이 SimpleUrlHandlerMapping을 설정한다.

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
        /messagebroker/*=_messageBroker
        </value>
    </property>
</bean>

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

위의 SimpleUrlHandlerMapping설정은 flex namespace를 사용할 경우는 아래와 같다.

<flex:message-broker>
    <flex:mapping pattern="/messagebroker/*" />
</flex:message-broker>

4.2.Exporting Spring Beans

4.2.1.RemotingService 환경 설정

Application 레벨의 채널 세팅은BlazeDS설정 파일인 services-config.xml파일에 services태그 안에 아래와 같이 정의 한다. Flex Client에서 RemotingService에 별도의 채널 설정이 없을 경우 my-amf채널을 이용한다.

<services>
    ..중략
    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>        
</services>

RemotingService에 대해 특정 채널을 이용하고자 할 경우에는 아래와 같이 remoting-service의 default-channels속성에 채널 이름을 등록한다.

<flex:message-broker>
    <flex:remoting-service default-channels="my-amf, my-secure-amf" />
</flex:message-broker>

4.2.2.remoting-destination 태그

remoting-destination 태그는 Spring Bean 을 Remote 객체로 노출 시킨다.

<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>

include-methods / exclude-methods 속성을 이용해 method 단위의 제어도 가능하다. include-method / exclude-method를 정의하지 않을 경우 default는 include-method이다.

<flex:remoting-destination ref="productService"
    include-methods="read, update"
    exclude-methods="create, delete"
    channels="my-amf, my-secure-amf" />

4.2.3.@RemotingDestination

@RemotingDestination 을 사용해서도 Spring Bean 을 Remote 객체로 노출이 가능하다.

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

@RemotingInclude, @RemotingExclude annotation을 이용해 method별 노출 여부를 설정할 수 있다.

@RemotingInclude
public Category getCategoryList(SearchVO searchVO) throws Exception{
..
}

@RemotingExclude
public void removeCategory(Category category) throws Exception{
...
}

@RemotingDestination annotaion을 이용해 Spring Bean을 노출 할 때 Destination 채널 설정은 아래와 같이 한다.

@Service("categoryService")
@RemotingDestination(channels={"my-amf","my-secure-amf"})
public class CategoryServiceImpl implements CategoryService {

 

Posted by 1010
반응형

출처 : http://blog.naver.com/PostView.nhn?blogId=thunder1119&logNo=100091204490

 

올해초 Srping BlazeDS Integration 1.0.0 M1 으로 스프링과 BlazeDS를 적용해 보았는데

( 머드초보님의 M1 사용기 : http://mudchobo.tomeii.com/tt/371 )

한학기 마치고 다시 접하려고 했더니 정식버전이 나왔더군요!

그래서 반가운 마음에 적용해보려고 Spring 홈페이지( http://www.springsource.org )에서 다운로드후

문서를 보았는데. M1에 비해서 문서의 양이 늘어나있고 영어 잼병인 저에겐 소스코드만이 유일한

해독가능한 언어인데 상황에 따라 다르게 적용해야되는 코드들이라 영 도움이 안되 몇일간 삽질을 시켜주었습니다ㅜㅜ

우선 설명하기에 앞서 플렉스 컴퍼넌트 카페( http://cafe.naver.com/flexcomponent.cafe ) 에 서기님이 올려주신

Flex3+eclipse europa + BlazeDS 셋팅 게시물의 첨부된 문서의 세팅방법을 모두 완료했다는 가정하에 설명하도록

하겠습니다. ( http://cafe.naver.com/flexcomponent.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=10906

서기님이 작성하신 셋팅문서 첨부해 두겠습니다.)



자 이제 위 과정으로 BlazeDS_Hello.mxml을 실행하였을 경우 "Welcome BlazeDS 성공!" 이란 문구를 보았다고 치고

이제 Srping BlazeDS Integration을 적용해 보도록 하겠습니다.

우선 Srping BlazeDS Integration에 필요한 환경(Java 5 or higher, Spring 2.5.6 or higher ,Adobe BlazeDS 3.2 or higher)

을 구성해주어야 되는데 http://www.springsource.org/download 에서 우선 Srping BlazeDS Integration과 Spring 2.5.6

을 받아서 lib안에 넣어줍니다.


그리고 web.xml을 수정해보겠습니다.

우선 spring을 사용하면서 필요없어진 리스너를 삭제합니다.

<!-- 아래의 리스너 삭제 -->
<listener>
        <listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>


그리고 스프링을 사용하기 위한 ContextLoaderListener를 삽입합니다.

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<servlet-mapping>태그는 그대로 두고 <servlet> 태그만 스프링을 사용하기 위해 아래와 같이 수정합니다.

<servlet>
        <servlet-name>MessageBrokerServlet</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>


여기 까지가 web.xml 수정사항입니다.

그 후 spring을 사용하려면 기본적으로 WEB-INF밑에 applicationContext.xml 파일이 있어야 하기에 만들어 줍니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
      
</beans>



 



이제 web.xml에서 <servlet>태그밑에 <param-value>에 선언해 두었던 web-application-config.xml을 만들어줍니다.

안의 내용은 뒤에 설명하도록 하겠습니다.


이제 WEB-INF밑에 flex폴더에 들어있는 BlazeDS관련 xml들을 수정하겠습니다.

우선 remoting-config.xml에 선언해둔 blaze id에 destination 태그를 삭제합니다. 이태그는 이제 spring 관리하에

web-application-config.xml에서 새로운 인생(?)을 살게 될 것입니다.

그리고 services-config.xml <services> 태그밑에  아래와 같이 default-channels 태그를 추가해 줍니다.

<services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="proxy-config.xml" />
        <service-include file-path="messaging-config.xml" />   
        <default-channels>
           <channel ref="my-amf"/>
        </default-channels>     
    </services>


자 이제 주역인 web-application-config.xml에 내용을 넣도록 하겠습니다.

우선 설명하기에 앞서 전체코드 나갑니다.

<!-- web-application-config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:flex="http://www.springframework.org/schema/flex"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
               http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/flex
            http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">
       
       <bean id="mySpringManagedMessageBroker" class="org.springframework.flex.core.MessageBrokerFactoryBean" />

       <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
             p:mappings="/*=mySpringManagedMessageBroker" />
      
       <bean class="org.springframework.flex.servlet.MessageBrokerHandlerAdapter" />
                
       <bean id="test" class="test.Test">
               <flex:remoting-destination destination-id="blaze" message-broker="mySpringManagedMessageBroker"/>
       </bean>

</beans>



얼핏 복잡해보이기도 하지만 사실 그렇게 어렵지 않습니다.

우선 네임스페이스 부분을 보면 xmlns:flex="http://www.springframework.org/schema/flex 추가됬고

스키마부분을 보면

http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd

기존 스프링에서 이두개가 추가되었고

web.xml에서 들어오는 MessageBroker를 아래 태그가 담당합니다.

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


id는 편하신데로 주시면 되고 사실 이부분을 doc에 보면 여러가지 방법으로 표현할 수 있는데 <flex:message-broker/>등

짧게 표현이 가능하지만 doc이 부실한지 제가 못찾는지 이대로 실행하면 오류가나서 실행이안됩니다.

2009/07/13 추가사항

<flex:message-broker/> 방식의 사용법을 보시려면 다음의 페이지를 참고해주세요!

http://actionscripter.tistory.com/27



그래서 전 그냥 기존 spring 방식으로 bean으로 처리했습니다.

다음으로 스프링에 SimpleUrlHandlerMapping 으로 MassageBroker와 연결합니다.

저는 편의상 p 네임스페이스로 축약해서 사용했습니다.

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
             p:mappings="/*=mySpringManagedMessageBroker" />

또는

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/messagebroker/*=mySpringManagedMessageBroker
</value>
</property>
</bean>


그리고 이부분은 저도 잘 모르겠는데 messageBroker와 관련된 adapter인듯 합니다.

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


그리고 저를 가장 고생시킨.. remoting 부분인데 1.0.0 정식이 나오면서 <flex:remoting-service>태그가

<flex:remoting-destination>으로 바겼는지 국내와 국외문서 모두에 <flex:remoting-service>으로 되어있어서

상당히 고생했습니다. 이부분도 다양한 사용방법이 있는데 자세한것은 레퍼런스를 참조하시고 우선 성공한 방법만

소개하겠습니다.

<bean id="test" class="test.Test">
               <flex:remoting-destination destination-id="blaze" message-broker="mySpringManagedMessageBroker"/>
</bean>

또는

<bean id="test" class="test.Test"/>
      
<flex:remoting-destination ref="test" destination-id="blaze" message-broker="mySpringManagedMessageBroker"/>

또는

<bean id="test" class="test.Test"/>

<bean id="product" class="org.springframework.flex.remoting.RemotingDestinationExporter"
             p:messageBroker-ref="mySpringManagedMessageBroker" p:service-ref="test"
             p:destinationId="blaze" />

레퍼런스문서에 ref 외에는 나와있질 않아서 계속 메시지브로커를 찾지못한다는 에러를 보았는데

결국 flex스키마 문서를 죄 뒤져서 속성을 찾아냈습니다 ㅡㅠ

message-broker="mySpringManagedMessageBroker" 부분은 꼭 넣어주시고

remoting-config.xml에서 destination id로 사용되는 부분과 같은 속성이 destination-id 입니다.

사실 이외에도 채널등 여러 속성이 있는데 불필요하다고 판단해서 다 제외했습니다.

자이제 여기까지 설정을 하시고 BlazeDS_Hello.mxml을 실행해보시면 다음과 같은 아름다운 화면을 보실 수 있습니다!


 

Posted by 1010
반응형

Spring Projects

Spring Flex

Spring BlazeDS Integration is a top-level Spring project, and a component of the complete Spring Web stack.  This project's purpose is to make it easier to build Spring-powered Rich Internet Applications using Adobe Flex as the front-end client.  It aims to achieve this purpose by providing first-class support for using the open source Adobe BlazeDS project and its powerful remoting and messaging facilities in combination with the familiar Spring programming model.

The Flex Addon for Spring Roo is a new component that raises the bar for productivity in building Flex clients backed by Spring BlazeDS Integration on the server-side. By utilizing the next-generation code-generation and management facilities of Spring Roo, it provides the fastest way to get up and running with a new Spring-based Flex project by letting developers focus on doing what they do best - write code.

 

Spring BlazeDS Integration is a top-level Spring project, and a component of the complete Spring Web stack.  This project's purpose is to make it easier to build Spring-powered Rich Internet Applications using Adobe Flex as the front-end client.  It aims to achieve this purpose by providing first-class support for using the open source Adobe BlazeDS project and its powerful remoting and messaging facilities in combination with the familiar Spring programming model.

The Flex Addon for Spring Roo is a new component that raises the bar for productivity in building Flex clients backed by Spring BlazeDS Integration on the server-side. By utilizing the next-generation code-generation and management facilities of Spring Roo, it provides the fastest way to get up and running with a new Spring-based Flex project by letting developers focus on doing what they do best - write code.

#maven

Latest News

Spring Flex Resources

Spring Flex Presentations

Spring Flex Articles and Tutorials

 

Maven Artifacts

Here is the Spring External Repository needed for BlazeDS dependencies:

<repository>
<id>spring-external</id>
<name>Spring External Repository</name>
<url>http://maven.springframework.org/external</url>
</repository>

Here is the Spring Flex dependency definition:

<dependency>
<groupId>org.springframework.flex</groupId>
<artifactId>spring-flex-core</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>

 

Posted by 1010
반응형
Posted by 1010