2013年4月13日 星期六

SQL - UPDATE ORDER BY 的資訊

DECLARE @TOP AS INT SET @TOP = 2 UPDATE OffLineMsg SET process = 0 WHERE ID IN ( SELECT TOP(@TOP) ID FROM OffLineMsg WHERE USERID = 'QBO00000001' ORDER BY CDATE DESC ); 上面就是只UPDATE OffLineMsg 中符合條件且ORDER BY CDATE DESC後的 前2筆資訊

2013年4月7日 星期日

Android初體驗 - 讀取XML(使用SAX)


先記錄下參考網站:
http://puremonkey2010.blogspot.tw/2011/08/android-xml-sax-parser.html

Android初體驗 - R.java??


R.java是一個由eclipse自動產生的檔案,主要是敘述所有@id、@string這些resource的位置資訊,他被置放在 gen/packages/R.java 的位置。

所有定義在XML的資源,若需在程式中存取,可透過findViewById(id) 取得其xml中的reference,例如:

Button button = (Button) findViewById(R.id.Button01)

其中的R.id.Button01在main.xml中定義如下:

而R.java中定義:
public static final class id {
public static final int Button01=0x7f050000;
}

因此上述的 Button button = (Button) findViewById(R.id.Button01)
很明白可看出是由R.id.Button01指出resource資訊(xml中的@+id/Button01)再經由findViewById()找到此VIEW。

需注意的是findViewById()統一回傳最上層的VIEW,因此之後須強制傳型為自己所需的類型。

Android初體驗 - LogCat無任何訊息(使用eclipse)



  1. 1.打開window->ShowView->Other->DevicesS
  2. 檢查device中是否有裝置尚未被關閉,如下圖STOP不應該亮燈,若有請關閉
  3. 重新run,此時應該可看到LogCat有訊息了





2013年4月6日 星期六

Quartz初體驗 - Jobs and Triggers介紹


  • Schedule:用來掌管所有需要執行的Job,包含呼叫Job execute(...)
  • Job :所需要執行的內容Class都需implements 此 interface
  • JobDetail :用來定義Job instances 
  • JobBuilder :用來建立JobDetail 
  • Trigger :設定實際運作Job的執行細節,例如:執行時間狀態
  • TriggerBuilder :用來建立Trigger 
常用Trigger:
  1. SimpleTrigger
    使用狀況:一次性執行、指定時間執行(可重複N次)、間隔延遲指定時間執行...
  2. CronTrigger
    使用狀況:指定日期執行,例如:每個星期五早上十點執行、每個月的10號下午兩點執行...etc

  • 重點節錄:

When the Job's trigger fires (more on that in a moment), the execute(..) method is invoked by one of the scheduler's worker threads

  • 將Trigger與Job分開建立的優勢:

  1. 可以定義好幾個不同的Trigger(執行時間),卻執行同一Job
  2. 使用JobKey and TriggerKey來管理你的Jobs與triggers,可用來進行分類管理,例如:Log用、維護用...etc

Quartz初體驗 - 如何使用不同的Schedule PropertySetting


在執行
scheduler.scheduleJob(job, trigger);

時出現:


RROR JobRunShell - Job group1.server.client.loginobserver.BackupGpBaseDataObser
ver@6909db threw an unhandled Exception:
java.lang.NullPointerException
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.j
ava:557)


後來發現原來呼叫預設的

_scheduler = StdSchedulerFactory.getDefaultScheduler();

等同使用quartz.properties 此設定檔中的資料,
而每一個設定檔中的資料只能使用一次,因此若需建立第二個schedule,則需使用不同的設定檔:
  1. 建立新的properties設定檔:"backup.quartz.properties"
     
    org.quartz.scheduler.instanceName = MyBackupScheduler
    org.quartz.threadPool.threadCount = 3
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    
  2. 將建立schedule code改為:
     
    StdSchedulerFactory factory = new StdSchedulerFactory();
     factory.initialize("backup.quartz.properties");
    _scheduler = factory.getScheduler();
    _scheduler.start();
而原先呼叫 StdSchedulerFactory.getDefaultScheduler() 等同於:
 
StdSchedulerFactory factory = new StdSchedulerFactory();
 factory.initialize();//default use quartz.properties 
_scheduler = factory.getScheduler();
_scheduler.start();

不過我搞不太懂為什麼問題出在【重複Schedule設定】,卻會拋出NullException這種這麼不明確的錯誤呢....
參考:Novice question: how do I get to PropertySettingFactory?

Quartz初體驗 - Job and Job Details



參考下列片段:


 
// define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();
        
  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())            
      .build();
        
  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

line 1~3說明了最簡單建立Job的方式,提供簡單的extend Job的Class!Job的建立生命週期如下:

  1. Shedule建立執行Job之前(call job's execute(..)),便為Job建立新的instance(如上述的HelloJob)
  2. Shedule call job's execute(..)
  3. job使用完畢,等待被GC回收
因此由上述可見,我們並無法使用任何有狀態、或需要保存資料的Job,或於Job執行前給予特定資料,因為Job永遠是使用default constuctor建立且於每次execute時重新建立、之後回收。
那麼,我們要怎麼樣在Job被execute之前指定特定資料呢?

使用JobDataMap


1.設定資料:
   
// define the job and tie it to our DumbJob class
  JobDetail job = newJob(DumbJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .usingJobData("jobSays", "Hello World!")
      .usingJobData("myFloatValue", 3.141f)
      .build();

2.取得資料:
 
public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }

如上述範例,可先於創立JobDetail時指定資料,後於Job execute()時使用getJobDetail().getJobDataMap();取得所需資料。
然而需注意的是,置放於DataMap()的資料皆需為serialized 

參考:Lesson 3: More About Jobs and Job Details

Quartz初體驗 - 從Job中自行關閉自己


  1. 於public void execute(JobExecutionContext arg0) throws JobExecutionException自行拋出JobExecutionException
  2. 將欲拋出的JobExecutionException設定為setUnscheduleAllTriggers(true)
  3. throw JobExecutionException

 
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
  //do something...
       try {
            int zero = 0;
            int calculation = 4815 / zero;
        } 
        catch (Exception e) {
            _log.info("--- Error in job!");
            JobExecutionException e2 = 
                new JobExecutionException(e);
            // Quartz will automatically unschedule
            // all triggers associated with this job
            // so that it does not run again
            e2.setUnscheduleAllTriggers(true);
            throw e2;
        }
}

參考:Example - Dealing with Job Exceptions

2013年4月2日 星期二

FB - OpenGragh



使用Graph API Explorer 工具


  1. 先使用上方【存取代碼】(點選取得存取代碼)取得ACCESS_TOKEN
  2. 選擇 GET (or POST)

取得使用者檔案:
  1. https://graph.facebook.com/100004664342888?access_token=xxxxxxxxx
     (後面數字為使用者的FB_ID)
    access_token為上述步驟取得的ACCESS_TOKEN
  2.  

可使用左方的NODE選擇所需欄位,例如,取得LIKES:


https://graph.facebook.com/100004664342888?fields=likes?access_token=xxxxxxxxx