ViewStack에 대해서 알아봅시다.
화면 전환을 위해 이게 가장 많이 쓰인다더군요. 써보니 뭐 좋은 거 같습니다.

탭네이게이터나 아코디언?인가?뭔가 하는 것은 펼치고 접고 하는 식인 반면에 이건 메뉴바를 하나 두고 보이고 싶은 View를 클릭해서 열 수 있다는 차이점이 있습니다.



메인부분에 사용된 ViewStack을 보도록 합시다.






[code]
<mx:ViewStack id="viewstack" width="75%" height="100%" creationPolicy="all">
 
   <mx:Panel id="ViewHome" width="100%" height="100%"
     showEffect="WipeDown" hideEffect="WipeUp">
       <mx:TextArea width="100%" height="100%" borderColor="#ffffff"
         wordWrap="true" editable="false" enabled="true" fontSize="12"
          color="#666666" cornerRadius="5" x="10" y="10">
         <mx:text>예매시스템에 오신 것을 환영합니다.</mx:text>
       </mx:TextArea>
      </mx:Panel>
     
      <comp:BookSeat id="ViewBookSeat"
         showEffect="WipeDown" hideEffect="WipeUp" />
 
      <comp:BookCancel id="ViewBookCancel"
         showEffect="WipeDown" hideEffect="WipeUp" />
 
      <comp:BookList id="ViewBookList"
         showEffect="WipeDown" hideEffect="WipeUp" />
     
      <comp:SeatList id="ViewSeatList"
         showEffect="WipeDown" hideEffect="WipeUp" />
     
      <comp:AgeStatus id="ViewAgeStatus"
         showEffect="WipeDown" hideEffect="WipeUp" />
     
      <comp:SexStatus id="ViewSexStatus"
         showEffect="WipeDown" hideEffect="WipeUp" />
     
    </mx:ViewStack>
[/code]

아....comp:BookSeat 이거는 커스텀 컴포넌트라고 해서 사용자가 직접 만든 컴포넌트를 말하는 겁니다.
즉 이미 있는 컨트롤들을 상속받아서 새로운 기능을 추가하는 그런것이죠.

앞에 comp는 무조건 저게 아니고 처음에 mx:application 선언시에 보시면 xmlns:comp="*" 라고 적어 놓으면 그 해당 폴더에 있는 모든 컴포넌트를 사용할 수 있다 라는 것이죠. 그리고 이름은 comp!

그다음 BookSeat, BookCancel 등은 이 컴포넌트 이름입니다. 처음 플렉스빌더에서
File -> New -> New MXML Component 라고 해서 이름을 쓰는데 즉 파일 이름이 컴포넌트 이름입니다 ^^

저기 6개들은 다 제가 만든 컴포넌트이며 다 Panel을 상속받았습니다.
Panel이라고 치고 해봅시다.

저렇게 ViewStack을 정해 놓으면 ViewStack에는 총 7개의 Panel이 들어가 있습니다. 우선적으로 처음에 쓴 놈부터 보여져서 ViewHome이 먼저 보여집니다.

그리고 viewstack.selectedChild 라는 변수에 ViewBookSeat이라고 넣어주면 ViewBookSeat에 해당하는 컴포넌트가 보여지게 됩니다.

즉 Button에 <mx:button .... click="viewstack.selectedChild = ViewBookSeat"> 요렇게 해주면 화면 전환이 된다는 것이죠 ^^

이 예매시스템은 성격상 마우스를 클릭했을 때 데이터를 먼저 업데이트 해야하기 때문에 업데이트를 하고나서 ViewStack을 바꾸는 식으로 했습니다 ^^

메인부분은 화면 전환하는 거 밖에 없군요-_-;

예매시스템 소스파일입니다.
http://mudchobo.tomeii.com/tt/108
 
Posted by 머드초보
,
 

플렉스 세션에 대한 예제가 별로 없어서 찾기 힘들었는데 그냥 서블릿세션처럼 쓰면 되는 것이더군요-_-;

우선 플렉스세션을 만들어야하는데 서버측 프로그래밍할 때 그냥 FlexSession쓸라고하면 에러납니다. LCDS깔 때 있는 flex.war파일에 포함되어있는 jar파일을 서버측 프로그래밍 할 때 즉 컴파일할 때 필요합니다.

저는 작업할 때 Flex Builder2랑 Eclipse랑 두개 띄워놓고 작업합니다-_-;
자바 프로그래밍 하기 위해서 Eclipse에서 세션을 만들어봅시다.

우선 Dynamic Web Project로 프로젝트를 하나 만듭니다.

그리고 필요한 jar파일을 넣어야합니다. flex.war가 디플로이 되면 WEB-INF\LIB폴더에 JAR파일이 있는데 여기서 message관련된거 이클립스에서 만든 프로젝트 lib에다가 복사합니다(사실 잘 몰라서 다 복사했습니다-_-;)
flex-messaging.jar, flex-messaging-common.jar, flex-messaging-opt.jar, flex-messaging-req.jar ^^

[code]
package flex.session;

import flex.messaging.FlexSession;
import flex.messaging.FlexContext;

public class SessionRO {

 public void setSession(String id) {
  FlexSession session = FlexContext.getFlexSession();
  session.setAttribute("id", id);
  System.out.println("세션설정성공");
 }
 
 public String getSession() {
  FlexSession session = FlexContext.getFlexSession();
  String id = session.getAttribute("id").toString();
  System.out.println("세션가져오기성공");
  return id;
 }
 
 public void removeSession() {
  FlexSession session = FlexContext.getFlexSession();
  session.invalidate();
 }
}
[/code]
간단합니다. setSession은 세션을 설정(로그인시)하는 것이고, getSession은 세션을 가져오는 것이고(있으면!), removeSession은 세션을 삭제(로그아웃시)하는 것입니다.

근데 문제점은 이놈을 테스트하려면 {was}/webapp/flex/WEB-INF/classes/에 복사해놓고 mxml이나 as에서 밖에 테스트를 못합니다-_-; jsp에서 테스트를 하려니 안되더군요 ^^ 꽤 고생했습니다-_-;

아 그리고 DB구조는 이렇게 되어있습니다.
[code]
CREATE TABLE `bs_Member` (
  `id` varchar(20) NOT NULL,
  `pwd` varchar(20) default NULL,
  `name` varchar(20) default NULL,
  `age` int(10) unsigned default NULL,
  `sex` varchar(20) default NULL,
  `tel` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
)
[/code]

로그인 메소드를 보도록 합시다.
[code]
public int Login(String id, String pw) {
  Connection con = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
 
  try {
   String jdbcDriver = "jdbc:apache:commons:dbcp:/pool";
         con = DriverManager.getConnection(jdbcDriver);
        
   pstmt = con.prepareStatement("SELECT pwd FROM bs_Member WHERE id = binary(?)");
   pstmt.setString(1, id);
   rs = pstmt.executeQuery();
   rs.last();
   int rowCount = rs.getRow();
   rs.beforeFirst();

   if(rowCount != 0) {
    rs.next();
    if(pw.equals(rs.getString("pwd"))) {
     return 1;
    } else {
     return 2;
    }
   }
   else {
    return 3;
   }
  } catch (SQLException e) {
   e.printStackTrace();
   return 0;
  } finally {
   if (rs != null) try { rs.close(); } catch(SQLException ex) {}
   if (pstmt != null) try { pstmt.close(); } catch(SQLException ex) {}
   if (con != null) try { con.close(); } catch(SQLException ex) {}
  }
 }
[/code]
bs_Member테이블에서 로그인한 id가 있는지 검사를 하고 id가 있으면 3를 리턴하고, 없으면 비밀번호가 같은지 검사하고 같으면 1을 리턴하고, 틀리면 2를 리턴합니다. 플렉스 as에서 1을 받으면 성공이라고 뿌리고 이런식으로 했습니다.

자 그러면 flex에서 보도록 합시다.

[code]
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"
height="100%" xmlns:comp="*" backgroundColor="#c0c0c0"
backgroundAlpha="0.7" creationComplete="initWindow()">
 <mx:Script>
  <![CDATA[
   import mx.rpc.events.ResultEvent;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.remoting.RemoteObject;
   import mx.controls.Alert;
   
   private function initWindow():void {
    loginwindow.x = this.width / 2 - 150;
    loginwindow.y = this.height / 2 - 150;
   }
   
   private function RequestLogin():void {
    var srv:RemoteObject = new RemoteObject();
    loginbtn.enabled = false;
    joinbtn.enabled = false;
    srv.destination = "booksystem";
   
    srv.Login(idtext.text, pwtext.text);
   
    srv.addEventListener("result", resultHandler);
    srv.addEventListener("fault", faultHandler);
   }
   private function resultHandler(event:ResultEvent):void {
    var result:int = int(event.result);
    var srv:RemoteObject = new RemoteObject();
    srv.destination = "session";
   
    switch (result) {
     case 0 :
      Alert.show("DB오류입니다.");
      break;
     case 1 :
      Alert.show(idtext.text + "님 환영합니다.");
      srv.addEventListener("result", sessionresultHandler);
      srv.addEventListener("fault", sessionfaultHandler);
      srv.setSession(idtext.text);
      loginbtn.enabled = true;
      joinbtn.enabled = true;
      break;
     case 2 :
      Alert.show("비밀번호가 틀립니다.");
      pwtext.text = "";
      loginbtn.enabled = true;
      joinbtn.enabled = true;
      break;
     case 3 :
      Alert.show("ID가 없습니다.");
      pwtext.text = "";
      loginbtn.enabled = true;
      joinbtn.enabled = true;
      break;
    }
   }
   private function faultHandler(event:FaultEvent):void {
    Alert.show("실패 메세지: " + event.fault.message);
    loginbtn.enabled = true;
    joinbtn.enabled = true;
   }
   
   private function sessionresultHandler(event:ResultEvent):void {
    parentApplication.loginid = idtext.text;
    parentApplication.infota.text = idtext.text + "님 방가방가!";
    idtext.text = "";
    pwtext.text = "";
    visible = false;
   }
   
   private function sessionfaultHandler(event:FaultEvent):void {
    Alert.show("실패 메세지: " + event.fault.message);
   }
  ]]>
 </mx:Script>
 
 <mx:TitleWindow id="loginwindow" width="300" height="200" layout="absolute"
   title="M.C the MAX공연 예매 시스템에 오신 것을 환영합니다.">
  <mx:Label x="64.5" y="35" text="ID : "/>
  <mx:Label x="64.5" y="65" text="PW : "/>
  <mx:TextInput id="idtext" x="103.5" y="33" width="112"/>
  <mx:TextInput id="pwtext" x="103.5" y="63" width="112"
displayAsPassword="true" enter="RequestLogin();"/>
  <mx:Button id="loginbtn" x="64.5" y="93" label="로그인"
width="73" click="RequestLogin();"/>
  <mx:Button id="joinbtn" x="145.5" y="93" label="회원가입"
click="parentApplication.showJoin();"/>
 </mx:TitleWindow>
</mx:Canvas>
[/code]
id, pw를 입력하고 엔터 또는 로그인버튼을 클릭하게 되면 RemoteObject를 통해서 Login메소드를 호출하게 됩니다. 호출을 해서 성공적으로 리턴하면 resultHandler함수에 리턴값을 받아 그 리턴값에 따라 Alert을 해줍니다. 로그인을 성공해버리면 setSession을 통해 세션을 설정합니다.

이게 다군요-_-; 로그인을 성공하게 되면 자기자신은 visible을 false로 바꿔버립니다. 그래서 뒤에 있는 실제 메뉴를 건드릴 수 있게 했죠-_-; 아....진짜 이따구로도 가능하다는 것을 보여주는군요.

예매시스템 소스파일입니다.
http://mudchobo.tomeii.com/tt/108
 
Posted by 머드초보
,
 

Remote Object
RemoteObject는 Flex데이터 서비를 설치한 WAS(ex.톰캣 등)에서 자바빈즈를 호출하여 그 결과를 Binary 형태의 AMF(Action Message Format)로 처리합니다.
우선 뭔지 잘 모르겠지만, 자바빈즈를 가져올 수 있는 듯하네요 ^^

우선 전에 포스팅한 환경설정을 다 했다면 톰캣폴더\webapps\flex\ 폴더가 생겼을 껍니다.

자 이제 flex builder2 를 켜봅시다.

File -> New -> Flex Project 합시다.
3번째의 Flex Data Services를 선택하고, 옵션은 Complile on the server when the page is viewed로 합시다.

사용자 삽입 이미지


넥스트를 하면 폴더지정하라고 나오는데요.
Root folder는 톰캣폴더\webapps\flex 로 지정하면 되구요.
Root URL은 톰캣은 8080을 써서 8080으로만 바꿔주면 돼요. JRUN이 8700으로 쓰더군요. 톰캣도 뭐 바꾸면 바꿀 수 있죠 ^^ 디폴트가 8080이니 8080으로 써줍시다.
context root는 flex로 합니다.

사용자 삽입 이미지

프로젝트 이름은 RemoteTest로 합시다. Finish로 하면 프로젝트가 하나 만들어집니다^^

자 그러면 빈즈를 작성하기위해 이클립스를 실행합시다.

File -> New -> Project -> Dynamic Web Project로 선택해서 Member라는 이름으로 하고 Finish를 합시다.
Java Resousrces: src에 대고 마우스오른쪽버튼을 눌러서 pakage를 선택합니다.

패키지이름은 flex.member라고 합시다.
이 패키지 안에 자바파일을 두개 만들껍니다. 하나는 Beans파일이고 하나는 Service파일입니다.

우선 Beans파일입니다. MemberVO.java 라는 이름으로 만듭시다.

beans파일은 이클립스가 다 만들어줍니다. 저도 멋도모르고 다 쳤는데 바보같은 짓하지 말고--;

우선 멤버변수만 써줍니다.
[code]
package flex.member;

public class MemberVO {
    String id;
    String password;
    String name;
    int age;
    String sex;
    String tel;
}
[/code]

위와 같이 써주고, Project Explorer에서 MemberVO.java에 오른쪽바우스버튼을 클릭하고 Source -> Generate getter and setter 클릭하시고, Select All하시고 OK만 누르면 자동으로 만들어집니다.

[code]
public class MemberVO {
 String id;
 String password;
 String name;
 int age;
 String sex;
 String tel;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 public String getSex() {
  return sex;
 }
 public void setSex(String sex) {
  this.sex = sex;
 }
 public String getTel() {
  return tel;
 }
 public void setTel(String tel) {
  this.tel = tel;
 }
}
[/code]

다음은 MemberService.java를 만들어봅시다.
[code]
package flex.member;

import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import flex.member.MemberVO;

public class MemberService {
 public List<MemberVO> getElements() throws SQLException {

  long startTime = System.currentTimeMillis();
 
  try {
   Class.forName("com.mysql.jdbc.Driver");
  } catch (ClassNotFoundException e) {
  }

  Connection con = null;
  List<MemberVO> list = new ArrayList<MemberVO>();

  String sql = "SELECT * FROM Member_List";

  try {
   String url = "jdbc:mysql://db주소";
   con = DriverManager.getConnection(url,"db아이디", "db비밀번호");
   PreparedStatement stmt = con.prepareStatement(sql);

   ResultSet rs = stmt.executeQuery();

   while (rs.next()) {
    MemberVO mb = new MemberVO();
    mb.setId(rs.getString("Id"));
    mb.setPassword(rs.getString("Password"));
    mb.setName(rs.getString("Name"));
    mb.setAge(rs.getInt("Age"));
    mb.setSex(rs.getString("Sex"));
    mb.setTel(rs.getString("Tel"));
    list.add(mb);
   }
  } catch (SQLException e) {
   e.printStackTrace();
  } finally {
   try {
    con.close();
   } catch (Exception ignored) {
   }
  }

  System.out.println("Service execution time: "
    + (System.currentTimeMillis() - startTime));

  return list;
 }
}
[/code]

DB를 구축해봅시다. MYSQL을 사용하도록 합시다.
[code]
CREATE TABLE `Member_List` (
  `ID` varchar(10) NOT NULL,
  `Password` varchar(10) NOT NULL,
  `Name` varchar(10) NOT NULL,
  `Age` int(2) NOT NULL,
  `Sex` varchar(2) NOT NULL,
  `Tel` varchar(12) NOT NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=euckr COMMENT='회원 멤버 리스트입니다.';

INSERT INTO `Member_List` (`ID`, `Password`, `Name`, `Age`, `Sex`, `Tel`)
VALUES
('mudchobo', '1234', '성종천', 25, '남', '01000000000'),
('hermusseri', 'hermu', '김효진', 23, '여', '01000000000'),
('k1011606', '1234', '강현욱', 24, '남', '01000000000'),
('shs8326', '1234', '성현식', 58, '남', '01000000000'),
('jor0737', '1234', '조옥렬', 49, '여', '01000000000'),
('boazzang', 'boalove', '보아짱', 30, '여', '0100000000'),
('webserv', 'babo', '웹서비스', 45, '남', '01000000000'),
('child', 'ggoma', '꼬마', 15, '여', '01000000000'),
('mudcosdf', '1234', '성종텬', 99, '남', '01000000000');
[/code]

저 SQL을 그대로 가져다가 써봅시다.

자 이제 만들어진 클래스파일들을 복사해야합니다. 어디로 복사하느냐! flex에 있는 곳에 복사해야합니다.
이클립스에서 작업한 Member프로젝트에서 class폴더를 통채로 복사를 해서
톰캣폴더\webapps\flex\WEB-INF\classes폴더랑 합체를 합니다!

이제 이것을 쓸 수 있게 remoting-config.xml파일을 수정해야합니다. 이파일은 톰캣폴더\webapps\flex\WEB-INF\flex\ 폴더에 있습니다.

[code]
<destination id="member">
  <properties>
   <source>flex.member.MemberService</source>
  </properties>
 </destination>
[/code]
방금복사한 Service클래스를 소스로 id를 member로 지정해서 사용하겠다는 뜻으로 보입니다 ^^

자 이제 플렉스 프로그래밍 해봅시다!-_-;

맨처음 생성한 remotetest프로젝트에서 remotetest.mxml파일을 열어봅시다.
remote object를 사용하는 방법은 두가지 방법이 있는데 mxml태그를 사용할 수도 있고, action script를 사용할 수도 있습니다. action script로 해봅시다.

[code]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                           layout="absolute">
 <mx:Script>
  <![CDATA[
   import mx.rpc.events.ResultEvent;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.remoting.RemoteObject;
   import mx.controls.Alert;
   
   private var startTime:Number;
   
   private function resultHandler(event:ResultEvent):void{
        dg.dataProvider = event.result;
   }
   
   private function faultHandler(event:FaultEvent):void{
        mx.controls.Alert.show("실패 메세지 : " + event.fault.message);
   }
   
   private function retrieve():void
  {
   var srv:mx.rpc.remoting.RemoteObject = new RemoteObject();
   srv.destination = "member";
   
   startTime = new Date().time;
   srv.getElements();
    
   srv.addEventListener("result",resultHandler);
   srv.addEventListener("fault",faultHandler);
  }
   
  private function logResult():void
  {
   if (startTime > 0)
   {
    log.text = "" + (new Date().time - startTime) + " milliseconds";
   }
  } 
  ]]>
 </mx:Script>
 
  <mx:Panel title="AS를 이용한 RemoteObject예" width="100%" height="100%">
  <mx:DataGrid id="dg" width="100%" height="100%"
                 updateComplete="logResult()"/>
   <mx:ControlBar>
    <mx:Button label="데이터 가져오기" click="retrieve()"/>
   <mx:Label id="log"/>
   </mx:ControlBar>
 </mx:Panel>
</mx:Application>
[/code]

이제 톰캣을 가동한다음에 ctrl + F11을 눌러서 실행해봅시다.
사용자 삽입 이미지


 
Posted by 머드초보
,
 

이눔의 강남은 왜이렇게 차가 많은 걸까요-_-; 저번에도 차가 막혀서 늦어서 이번에는 한시간30분이나 일찍 버스를 탔는데도 불구하고 더 오래 걸려버렸습니다-_-; 또 늦었습니다 OTL...
다음에는 두시간 일찍 나와야겠군요.

뭐 어쨌든 10분정도 늦어서 토즈에 도착해서 노트북 세팅하고 공부할 준비를 했습니다.
이번 시간에는 이클립스랑 친해지기 위해 이클립스를 조금 배웠는데요. 이클립스의 세계가 참 무한한 것 같습니다. 정말 생각한 기능들이 다 있는 거 같습니다.

디버깅하는 것도 무지하게 편하고, Refactoring이라는 것도 배웠습니다.

소스의 주석다는 것도 단축키가 있고, 문장 복사하고 그 줄지우고 뭐 생각하고 있는 모든 것이 단축키로 존재하는 것 같습니다-_-; 단축키만 잘 활용하면 키보드로 쉽고 빠르게 코딩할 수 있을 것 같습니다 ^^

디버깅 하는 것은 예전에 해봐서 좀 알고 있었는데 Refactoring이라는 것은 처음 들어봤습니다.
뭐 소스를 최적화 하는 뭐 그런거 같은데요. 제 생각에는 이 기능에 대해서는 소규모에서 쓰면 더 복잡해질 거 같습니다-_-;

이번에 아이군이 바빠서인지 많은 것을 준비를 못했지만 나름 많은 것을 배웠던 거 같습니다. 이클립스와 친숙해져야지 나중에 배울 자바프로그래밍을 쉽게 할 수 있을 것 같습니다.

 
Posted by 머드초보
,
 
오늘은 참 색다른 경험을 많이 한 날인데요 ^^

우선 "토즈"라는 곳을 알게 되었어요. 뭐 모임같은거 할 때 장소제공 하고 그러는 곳 같더라구요.
phpschool에서 하면 자바스터디를 꼽싸리 껴서 따라가게 되었는데요-_-;(친구가 강의를해서 ^^)

우선 첫날이라서 간단하게 설치랑 이클립스 사용법 조금이랑 동작원리, 그리고 가장 중요한 이바닥(?)에 대한 설명을 들었는데요.

우선 이클립스 같은 경우 저는 정말 단순 에디터기로만 사용했다고 생각이 들 정도로 대단한 기능들이 있군요. 아직 맛만 본 기능인데도 저로서는 신기했습니다.(난 대체 뭘한거지-_-;)

이클립스에 대해서 좀더 깊숙히 공부를 해야겠다고 생각했습니다. 이 툴만 잘 다루면 생산성이 향상 될꺼같아요!-_-;

우선 앞으로의 스터디가 기대되구요. 개인적으로 스프링을 배우고 싶었는데 나중에 시간되면 스프링까지 한다고 하니까 배웠으면 좋겠네요.


그리고, 잠시 종각쪽에 갔다가 인사동에 갔었는데 그냥 신기하네요.

다른 세계에 온듯한 느낌이....-_-; 뭐 그냥 밤에 잠깐 봤습니다-_-;

오늘 참 신기한 것을 많이 경험했네요-_-; 은둔형인 제가 하루종일 밖에 돌아다닌것도 신기하고-_-;
 
Posted by 머드초보
,