2011年5月18日 星期三

Linux上配置Blaze

連結資料:
BlazeDS來源網站連結參考
BlazeDS請於Adobe Open Source網站下載
BlazeDS下載首頁,可選擇一般檔案下載或原碼下載(SVN)。
BlazeDS一般檔案下載頁
BlazeDS Source Code下載頁
這篇文章將會使用一般檔案安裝。

安裝步驟:
Step1.配置JDK環境
請參考
    Ubuntu 10.04是預設是使用open java,如果要程式開發想使用Sun Java請參考install Sun JAVA。

    Step2.下載BlazeDS
    如圖:






     
     
     
    • 點擊後會進入Adobe下載頁面,輸入你在Adobe註冊的帳號與密碼。
    • 登入完畢後會出現BlazeDS的使用條款,點擊IAgree(我同意)。
    • 選擇Binary Distribution版本下載(這個版本沒有內含Tomcat,因為我們選擇自己安裝Tomcat)。 
         
     
    下載頁面也有列出BlazeDS的技術支援表:
    BlazeDS不支援Hibernate adapter,但有支援Spring
     
    在ubuntu使用firefox下載完後檔案會預設存放在home/Downloads裡面
     
    Step3.將BlazeDS解壓縮(解ZIP)
    • /~Downloads$ unzip blazeds-bin-4.0.0.14931.zip
    解開後得到blazeds.war

    Step4.將blazeds.war放置tomcat6中的webapps目錄下
    tomcat6預設上會將war解壓
    webapps是tomcat6預設的web資料夾位置
    • /~Downloads$ sudo mv blazeds.war /opt/tomcat6/webapps
    執行後將會得到一個blazeds資料夾

    Step5.修改blazeds名稱成為blazedsAMF

    • /opt/tomcat6/webapps$ sudo mv blazeds blazedsAMF
    Step6.將blazeds.war從webapps中刪除
    • /opt/tomcat6/webapps$ sudo rm blazeds.war

    Step7.利用Eclipse開啟java專案 (這個檔案沒有使用servlet)
    • 新增一專案,名稱remoteUT
    • 新增一packagecom.jt.remote
    • 新增一檔案,Hello.java
    結構如下:










    Step7.建立Hello.java程式內容
    package com.jt.remote;
    public class Hello
    {
     public Hello()
     {
      super();
     }
     public String getHello()
     {
      return "Hello World";
     }
     //test private
     private String getPackage()
     {
      return "com.jt.remote";
     }
     public String echoHello(String value)
     {
      return value + "Hello World";
     }
    }

    Step8.將remoteUT裡的src複製到blazedsAMF/WEB-INF/src底下
    • ~/workspace$ cp -a -r remoteUT/src/com /opt/tomcat6/webapps/blazedsAMF/WEB-INF/src/
    Step9.編譯Hello.java
    • ubuntu:/opt/tomcat6/webapps/blazedsAMF/WEB-INF/src$
      javac -d ../classes com/jt/remote/Hello.java

      編譯完成,可以在WEB-INF/classes中看見com/jt/remote/Hello.class
    Step10.配置remoting-config.xml
    • sudo gedit /opt/tomcat6/webapps/blazedsAMF/WEB-INF/flex/remoting-config.xml
    在<service>之間加入:

    <destination id="Remote_SayHello">
       <properties>
         <source>com.jt.remote.Hello</source>
       </properties>
    </destination>


    Step11.重新啟動Tomcat
    • /opt/tomcat6/bin$ ./startup.sh
    Step12.寫一個Flex來測試功能
    <?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"
          applicationComplete="completeHandler(event)"
          >
     <s:layout>
      <s:HorizontalLayout/>
     </s:layout>
     <fx:Script>
      <![CDATA[
       import mx.events.FlexEvent;
       import mx.messaging.ChannelSet;
       import mx.messaging.channels.AMFChannel;
       import mx.rpc.events.FaultEvent;
       import mx.rpc.events.ResultEvent;
       import mx.rpc.remoting.Operation;
       import mx.rpc.remoting.RemoteObject;
     
       //Remote Operation
       private var _channelSet:ChannelSet;
       private var _amfChannel:AMFChannel;
     
       private var _getHelloRemoteObject:RemoteObject;
       private var _echoHelloRemoteObject:RemoteObject;
     
       private var _getHelloOperation:Operation;
       private var _echoHelloOperation:Operation;
     
       private var _getHelloData:Object;
       private var _echoHelloData:Object;  
       protected function completeHandler(event:FlexEvent):void
       {
        initRemoteData();
        initRemoteOpertion();    
        initBtnListener();
       }
     
       private function initRemoteData():void
       {
        _getHelloData  = createRemoteData("getHello");
        _echoHelloData = createRemoteData("echoHello");
       } 
       protected function createRemoteData(methodName:String):Object
       {  
        var data:Object = new Object(); 
        //blazeds的AMF Server Service服務位址
        data.uri = "http://192.168.2.103:8400/blazedsAMF/messagebroker/amf";            
        data.channelSetID = "my-amf";
        //服務程式來源path(由classes之後算起)
        data.source = "com.jt.remote.Hello";
        //操作method名稱
        data.name = methodName;   
        data.destination = "Remote_SayHello";
        return data;
       } 
     
       private function initRemoteOpertion():void
       {
        initChannelSet();
        initAMFChannel();
        addChannel();
        initRemoteObject();
        initOperation();
        afterInitOPeration();
       } 
       private function initChannelSet():void
       {  
        _channelSet = new ChannelSet();
       }
       private function initAMFChannel():void
       {
        _amfChannel = new AMFChannel(_getHelloData.channelSetID , _getHelloData.uri);
       }
       private function addChannel():void
       {
        _channelSet.addChannel(_amfChannel);
       }
       private function initRemoteObject():void
       {  
        _getHelloRemoteObject = new RemoteObject();
        _getHelloRemoteObject.destination = _getHelloData.destination;
        _getHelloRemoteObject.channelSet = _channelSet;
        _getHelloRemoteObject.source  = _getHelloData.source;
      
        _echoHelloRemoteObject = new RemoteObject();
        _echoHelloRemoteObject.destination = _echoHelloData.destination;
        _echoHelloRemoteObject.channelSet = _channelSet;
        _echoHelloRemoteObject.source  = _echoHelloData.source;
       }
     
       private function initOperation():void
       {  
        _getHelloOperation = new Operation();
        _getHelloOperation.name = _getHelloData.name;
      
        _echoHelloOperation = new Operation();
        _echoHelloOperation.name = _echoHelloData.name; 
       }
       private function afterInitOPeration():void
       {
        _getHelloRemoteObject.operations  = {getHello:_getHelloOperation};
        _echoHelloRemoteObject.operations = {echoHello:_echoHelloOperation};
      
        _getHelloRemoteObject.addEventListener(ResultEvent.RESULT , getHelloResult);
        _getHelloRemoteObject.addEventListener(FaultEvent.FAULT , getHelloFault);
      
        _echoHelloRemoteObject.addEventListener(ResultEvent.RESULT , echoHelloResult);
        _echoHelloRemoteObject.addEventListener(FaultEvent.FAULT , echotHelloFault);  
       }

       private function getHelloResult(e:ResultEvent):void
       {  
        getHelloOutput.text = e.result.toString();
       }
       private function getHelloFault(e:FaultEvent):void
       { 
        getHelloOutput.text = "Remote失敗";
       } 
     
       protected function echoHelloResult(e:ResultEvent):void
       {
        output.text = e.result.toString();
       }
     
       protected function echotHelloFault(e:FaultEvent):void
       {
        output.text = "Remote失敗";
       }
     
     
       private function initBtnListener():void
       {
        getHelloBtn.addEventListener(MouseEvent.MOUSE_DOWN , callGetHello);
        echoHelloBtn.addEventListener(MouseEvent.MOUSE_DOWN , callEchoHello);
       }
     
       protected function callGetHello(event:MouseEvent):void
       {
        _getHelloRemoteObject.getHello();  
       }
     
       protected function callEchoHello(event:MouseEvent):void
       {
        _echoHelloRemoteObject.echoHello(input.text);
       } 
      ]]>
     </fx:Script>
     <fx:Declarations>
      <!-- 将非可视元素(例如服务、值对象)放在此处 -->
     </fx:Declarations>
     <s:Panel width="300" height="200" title="echoHello">
      <s:layout>
       <s:VerticalLayout gap="2" paddingTop="5"/>
      </s:layout>
     
       <s:HGroup width="100%" >
        <s:Label text="回傳結果"/>
        <s:TextInput id="output"/>
       </s:HGroup> 
       <s:HGroup width="100%">
        <s:Label text="輸入數值"/>
        <s:TextInput id="input"/>
       </s:HGroup>  
       <s:Button id="echoHelloBtn" label="call echoHello"/>  
     </s:Panel>

     <s:Panel width="300" height="200" title="getHello">
      <s:layout>
       <s:VerticalLayout gap="2" paddingTop="5"/>
      </s:layout>
      <s:HGroup width="100%" >
       <s:Label text="回傳結果"/>
       <s:TextInput id="getHelloOutput"/>
      </s:HGroup>  
       <s:Button id="getHelloBtn"  label="call getHello" />
     </s:Panel>
    </s:Application>

    輸出畫面:
    






    下次將來測試一下Servlet與Mapping Value Object

    Linux上安裝tomcat6.039 (圖文版)

    連結資料:
    Apache Tomcat官網
    Tomcat6下載頁

    Step1.下載tomcat
    • 如果你的linux有圖形介面只要使用firefox到tomcat官網直接下載,下載完後檔案會再home/Downloads/底下。
    • 若沒有:
      • cd ~
      • cd Downloads
      • sudo wget http://apache.cdpa.nsysu.edu.tw/tomcat/tomcat-6/v6.0.32/bin/apache-tomcat-6.0.32.tar.gz
      • 輸入你的操作權限密碼
    Step2.修改檔案群組與讀取權限(若你是使用wget下載,需執行此步驟)
    • ~/Downloads$ sudo chgrp -R jeffery apache-tomcat-6.0.32.tar.gz
    • ~/Downloads$ sudo chmod -R 771 apache-tomcat-6.0.32.tar.gz
    Step3.解壓縮
    • 有圖形介面的linux直接點擊解壓縮即可。
    • 若沒有圖形介面:
      • ~/Downloads$ tar xvzf apache-tomcat-6.0.32.tar.gz
    Step4.更改資料夾名稱並將其移到/opt底下
    • ~/Downloads$ mv apache-tomcat-6.0.32 /opt/tomcat6
    Step5.啟動tomcat
    • /opt$ tomcat6/bin/./startup.sh


    執行後出現:






    Step5.使用瀏覽器測試Tomcat6有無運作
    • 瀏覽器URL輸入:http://127.0.0.1:8080/
    Tomcat預設使用Port Number為8080
    出現以下畫面即Tomcat運作成功










    Step6.修改Http使用的PortNumber與使用編碼
    • sudo gedit /opt/tomcat6/conf/server.xml
    找到:
    <Connector port= "8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />

    修改port為8400:
    <Connector port= "8400" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" URIEncoding="UTF-8"/>

    儲存變更

    server.xml是tomcat的組態設定檔

    Step7.重新啟動tomcat
    • /opt/tomcat6/bin$ ./startup.sh

    開打瀏覽器,輸入http://127.0.0.1:8400/,出現tomcat畫面即修改成功。


    Step8.替tomcat設定ubuntu桌面上快速啟動圖示
    • 滑鼠右鍵 → 新增啟動圖示
    出現操作畫面如下輸入:
    • 類型:應用程式
    • 名稱:tomcat6_startup
    • 指令:/opt/tomcat6/bin/startup.sh











    如此,方便操作tomcat的啟動,當然你可以在建立一個shutDown的操作圖示。


    Step9.新增tomcat的環境變數 (要新增此環境變數才可開發與使用servlet)

    #tomcat environment
    export CATALINA_HOME=/opt/tomcat6
    export CLASSPATH=$CLASSPATH:$CATALINA_HOME/lib:$CATALINA_HOME/lib/servlet-api.jar



    Step10.載入新設定

    • source /etc/profile


    補充說明:
    <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true"
                xmlValidation="false" xmlNamespaceAware="false">

    在Server.xml設定檔中,Host name內有一屬性unpackWARs="true",這代表會自動將war解壓縮。

    2011年5月11日 星期三

    FlashBuilder Performance Profile view (性能概要文件與方法統計使用)

    FlashBuilder效能分析工具中,有一項Performance Profile view可以查詢應用程式中每個method被執行的次數,執行的時間花費,以便讓你追查效能狀況得知哪裡需要優化。

    使用範例:
    Step1.建立如下測試功能的程式碼
    //測試程式碼:
    <?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[
                      private var _ran:Boolean = true;
                      protected function button1_mouseDownHandler(event:MouseEvent):void
                      {
                         if(_ran)
                         {
                            _ran = false;
                            for (var j:int = 0; j < 100000; j++)
                            {
                              trace(examA4());
                            }
                            _ran = true;
                         }
                      }
                      private var str:String = "http://www.test.yes/index.html";
                      private function examA4():String
                      {
                          var targetIndex:int;
                          targetIndex = str.lastIndexOf("/") + 1;
                          if(targetIndex >= 0 ) {
                              return(str.slice( targetIndex , str.length));
                          }else {
      return null;
                          }
                      }
                  ]]>
           </fx:Script>
       <s:Button mouseDown="button1_mouseDownHandler(event)"/>
    </s:Application>
    Step2.點擊圖示,進入效能分析模式
    Step3.點擊正在運行的程式,並點擊捕獲性能概要的圖示







    Step4.捕獲文件後,雙擊文件,打開性能概要文件窗口









    可以看到窗口內有所有method被執行的訊息,目前Button的mouseDown還未觸發,所以還沒見到examA4()的執行狀況。

    Step5.點擊瀏覽器上的Button來觸發執行examA4()
    • examA4()還在跑的時候,可以看見瀏覽器上Button還在被MouseDown的狀態,執行完畢的話Button會回復原狀。
    Step6.examA4()執行完成後,再次點擊捕獲性能概要文件
    Step7.再次點擊被捕獲的文件,可以看到examA4()被執行狀況的資訊了










    如此可以觀察到,examA4()被調用了幾次,占了應用程式中總調用的百分比,發費了多少時間等等。

    在這裡只是一個操作範例,一般使用上是拿來追蹤程式中method被調用以及執行效能狀況,以便判斷哪裡需要優化。


    FlashBuilder Object References view(對象引用) 使用

    Object References View是FlashBuilder分析模式裡的一個功能,用來追蹤物件實體的被參考狀況。

    使用範例:
    Step1.建立如下資料結構















    測試程式中,將會建立hero.mxml 、TestInnerObject.as、TestObject.as三支程式來測試Object References View的使用功能。

    FlashBuilder 設置觀察點

    FlashBuilder可以在變數視窗中設定觀察點,觀察點在變數數值發生變動時會停止執行。
    使用範例如下程式碼:

    <?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"
      applicationComplete="application1_applicationCompleteHandler(event)">
    <fx:Script>
    <![CDATA[
    import mx.events.FlexEvent;
    import spark.components.Button;
    private var _i:int;
    protected function application1_applicationCompleteHandler(event:FlexEvent):void
    {
    trace("application complete"); //在此下斷點
    }
    protected function button1_mouseDownHandler(event:MouseEvent):void
    {
    _i++;
    }
    ]]>
    </fx:Script>
    <s:Button mouseDown="button1_mouseDownHandler(event)"/>
    </s:Application>

    Step1.在程式中第14行下斷點,如下圖。














    Step2.執行除錯模式
    按下進入除錯模式,此時系統會停在斷點。

    Step3.於變量view中,找到變數_i,在_i上按下滑鼠右鍵選擇切換觀察點










    設定完成_i上面會出現鉛筆圖示如

    Step4.按下F8讓程序繼續
    Step5.於瀏覽器上按下Button改變_i數值
    你會發現FlashBuilder會停止在程式第19行(_i++下面),打開斷點你可以看到







    其實觀察點就是當你要觀察的變數的數值有改變時,就會停止在變數變動那一行,以便觀察變數數值。

    與斷點不同是:
    • 斷點是程序執行到一定會暫停。
    • 觀察點是只有變數改變才會暫停。
    • 斷點在離開除錯模式後並不會消失。
    • 觀察點在終止除錯模式後就會自動消失。

    2011年5月10日 星期二

    Android Application Components

    Android 應用程式 構成要素

    具有以下四種要素:
    • Activities (活動,前景執行的程序)
      • 一個Activity代表一個單一的螢幕與一個使用者介面。

      • 例如,一個email Application也許它有一個Activity用來顯示一個新的電子郵件列表(new email list),另一個Activity撰寫電子郵件,而另一個Activity則是讀取郵件,這些Activity work凝聚在一起形成了一個電子郵件應用程式,但其實每一個Activity都是獨立的,因此不同的Application可以啟動任一個Activities(如果電子郵件應用程序允許的話)。

      • 例如,攝影機的Application可以啟動email Application的new email的Activities,撰寫新的郵件,讓使用者可以分享圖片。

      • android中的任何activity都是Activity的子類,應用程式中屬於Activity的程序都需要extends Activity這個類或其子類,關於更多的Activities學習請參考Activities學習指南
    • Service(服務,背景執行的程序)
      • Service是一個Component,運作於背景,用來執行長時間運行的操作或是遠端操作的處理程序(remote process)。

      • service是不提供使用者操作介面的(在背景當然不需要囉)。

      • 例如:一個service在背景程序中執行音樂播放,而使用者在其他的Application中執行操作,也可能利用一個remote service經由網路取得資料而不干擾使用者正在進行互動的activity。

      • 其他的component,如一個activity,可以啟動service讓他運作或是綁定(bind)他,目的是為了讓他可以互動。


      • andorid中的service都是Service的子類,屬於service的程序都需要繼承Service或其子類,關於Service請參考Service開發指南
    • Content providers (內容提供者)
      • 一個Content providers管理一組共享的application資料。

      • 你能夠在檔案系統中儲存資料,一個SQLite資料庫在web上或其他持久性的的儲存位置,你的application可以存取。

      • 透由Content providers,其他的應用程式能夠查詢或是修改資料,如果內容供應者允許的話(if the content provider allows it)。

      • 例如,Android系統提供一個Content provider管理著用戶的內容資訊(contact information)。因此任何具有適當權限的應用程序可以查詢部分content providers(ContactsContract.Data)的讀取與寫入特定人的相關訊息。

      • content providers也用於私有的(private)讀取與寫入,在你的應用程式上並且不是分享的。例如,Note Pad應用程式使用一個content provider保存筆記。

      • Android中的content provider都是ContentProvider的子類,content provider除了實現了ContentProvider之外還需實現一套標準的API,使得其他程序能夠藉由API來交易取得資料,關於ContentProvider請參考ContentProvider開發指南

    • Broadcast receivers (廣播接收機)
      • 一個Brodcast receivers是一個component,他用來回應系統全部的廣播通知。

      • 許多廣播是源自於系統本身,例如,螢幕被關閉、電量不足、圖片被截取。

      • 應用程序也可以發出廣播訊息,例如,令其他的應用程式知道,有一些資料已經被下載到裝置上,是可以被使用的。

      • 雖然broadcast receivers不會顯示一個使用者介面,但他們可能會建立一個status bar notification (create a status bar notification)來提醒用戶一個廣播事件發生。

      • 更常見的是, though, a broadcast receiver is just a "gateway" to other components and is intended to do a very minimal amount of work.(做一個非常少量的工作)

      • For instance, it might initiate a service to perform some work based on the event.
        例如它可能會啟動一個service來執行一些基礎的工作。

      • Android的broadcase receiver都是BroadcastReceiver的子類,且每一個broadcast都會交付一個Intent物件,更多的訊息請看BroadcastReceiver Class。

    Android Application Fundamentals

    Android 應用基礎


    Android的應用程式是使用Java程式語法撰寫的,程式的原始碼經由Android的SDK tools編譯成.apk檔,這個.apk檔案可以讓Android行動裝置安裝應用程式使用。

    一但將應用程式安裝在行動裝置上,每一個Android的應用程式是存活在他自己的security sandbox裡。
    • Android的操作系統(指OS),是多使用者的Linux系統,每一個應用程式在Linux中都是不同的使用者。
    • 預設,每個應用程式在Linux中會有一個唯一的使用者ID,Linux會設定好檔案權限,讓應用程式只能操作屬於自己權限的檔案。
    • 每個程序都有他自己的虛擬機器(virtual machine , VM),應此每個應用程序運行是彼此隔離的。
    • 預設,每一個應用程式執行在自己的Linux process上。Android starts the process when any of the application's components need to be executed, then shuts down the process when it's no longer needed or when the system must recover memory for other applications
    然而有一些方法可以讓兩個應用程式共享資源:
    • 可以安排兩個應用程序分享共同的Linux user ID,這樣他們就可以共用檔案文件,為了節省系統資源,也可將有共同用戶ID的應用程序安排運作在相同的Linux process,共享一個VM(應用程序必需簽署相同證書)。
    關於Linux process請查閱計算機結構或作業系統書籍解釋。
    • 應用程式可以請求對於裝置設備、資料的存取權限,如用戶的聯繫人(user's contacts)、簡訊(SMS messages)、SD card、攝影機(camera)、藍芽(Bluetooth)、等等,所有的應用程式權限申請,發生在使用者安裝時期。

    關於Android開發環境安裝請參考:
    Android Linux上開發環境安裝

    參考文件:
    內容來自於Android官方開發指南文件,詳細內容請見