<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-36974838</id><updated>2012-02-06T18:36:58.770-05:00</updated><category term='ruby'/><category term='ringside'/><category term='shindig'/><category term='openid'/><category term='dom'/><category term='workflow'/><category term='cache'/><category term='ogce'/><category term='maven'/><category term='gadget'/><category term='tomcat'/><category term='youtube'/><category term='api'/><category term='http'/><category term='template'/><category term='xml-rpc'/><category term='hadoop'/><category term='opensocial'/><category term='cms'/><category term='web service'/><category term='oauth'/><category term='eclipse'/><category term='nfs'/><category term='socialnetwork'/><category term='mashup'/><category term='axis2'/><category term='database'/><category term='linux'/><category term='facebook'/><category term='jackrabbit'/><category term='hibernate'/><category term='JavaCOG'/><category term='mysql'/><category term='java'/><category term='authentication'/><category term='Javascript'/><category term='security'/><category term='openssl'/><category term='sling'/><category term='tomcat axis2'/><category term='misc'/><category term='rest'/><category term='db4o'/><category term='pipe yahoo'/><category term='web2.0'/><category term='persistence'/><category term='html'/><category term='drupal'/><category term='hbase'/><category term='prototype javascript'/><title type='text'>Gerald Guo CGL Report</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default?start-index=101&amp;max-results=100'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>119</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-36974838.post-1313912733180038180</id><published>2010-12-26T18:01:00.001-05:00</published><updated>2010-12-26T18:52:13.416-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>Hadoop Log</title><content type='html'>&lt;p&gt;When Hadoop is started, it sets &lt;em&gt;&lt;font face="Courier New"&gt;hadoop.log.dir&lt;/font&gt;&lt;/em&gt; using &lt;em&gt;&lt;font face="Courier New"&gt;-Dhadoop.log.dir=$HADOOP_LOG_DIR&lt;/font&gt;&lt;/em&gt;.     &lt;br /&gt;If you don't set environment variable &lt;font face="Courier New"&gt;HADOOP_LOG_DIR&lt;/font&gt; explicitly, it will be &lt;font face="Courier New"&gt;$HADOOP_HOME/logs&lt;/font&gt;. If you don't specify &lt;font face="Courier New"&gt;HADOOP_HOME&lt;/font&gt;, Hadoop will guess it by using path of the script that you use to start Hadoop. So if you install Hadoop to dir &lt;font face="Courier New"&gt;&amp;lt;hadoop_dir&amp;gt;&lt;/font&gt;, and &lt;font face="Courier New"&gt;HADOOP_LOG_DIR&lt;/font&gt; is not set, then the log dir is &lt;font face="Courier New"&gt;&amp;lt;hadoop_dir&amp;gt;/logs&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;If you want to change root log dir, change file &lt;font face="Courier New"&gt;'conf/hadoop-env.sh&lt;/font&gt;'. Add a line similar to&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font size="4" face="Courier New"&gt;&lt;strong&gt;export HADOOP_LOG_DIR=/your/local/log/dir&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In following table, you should replace those variables which are enclosed in angle brackets.    &lt;br /&gt;&amp;lt;jobid&amp;gt;: id of a job     &lt;br /&gt;&amp;lt;username&amp;gt;: username of the user who starts up Hadoop.     &lt;br /&gt;&amp;lt;host&amp;gt;: host name of the node which runs the process.&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="947"&gt;&lt;tbody&gt;     &lt;tr style="background-color: #a0e4f6"&gt;       &lt;td valign="top" width="394"&gt;         &lt;p align="center"&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;Direcotory&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="262"&gt;         &lt;p align="center"&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;Description&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="289"&gt;         &lt;p align="center"&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;Related config parameters&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="background-color: #d0e4f6"&gt;       &lt;td valign="top" width="394"&gt;&amp;lt;hadoop.log.dir&amp;gt;&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of various daemons&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; hadoop-&amp;lt;username&amp;gt;-jobtracker-&amp;lt;host&amp;gt;.log&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of jobtracker daemon&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; hadoop-&amp;lt;username&amp;gt;-namenode-&amp;lt;host&amp;gt;.log&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of namenode daemon&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; hadoop-&amp;lt;username&amp;gt;-secondarynamenode-&amp;lt;host&amp;gt;.log&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of secondarynamenode daemon&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; hadoop-&amp;lt;username&amp;gt;-tasktracker-&amp;lt;host&amp;gt;.log&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of tasktracker daemon&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; hadoop-&amp;lt;username&amp;gt;-datanode-&amp;lt;host&amp;gt;.log&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Log of datanode daemon&lt;/td&gt;        &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394"&gt;&amp;#160; &lt;font style="background-color: #ffc000"&gt;job_&amp;lt;jobid&amp;gt;_conf.xml&lt;/font&gt;&lt;/td&gt;        &lt;td valign="top" width="262"&gt;Configuration file of a job&lt;/td&gt;        &lt;td valign="top" width="289"&gt; Only exists when the job is running. &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="394" colspan="3"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr style="background-color: #d0e4f6"&gt;       &lt;td valign="top" width="394"&gt;&amp;lt;hadoop.log.dir&amp;gt;/history&lt;/td&gt;        &lt;td valign="top" width="262"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="289"&gt;         &lt;pre&gt;&lt;font color="#ff8000"&gt;mapreduce.jobtracker.jobhistory.location&lt;/font&gt;&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;
        &lt;p&gt;&amp;#160; &lt;font style="background-color: #ffc000"&gt;job_&amp;lt;jobid&amp;gt;_conf.xml&lt;/font&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="262"&gt;&amp;#160;&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160; Only exists when the job is running.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;
        &lt;p&gt;&amp;#160; &lt;font style="background-color: #ffc000"&gt;job_&amp;lt;jobid&amp;gt;_&amp;lt;username&amp;gt;&lt;/font&gt;&lt;/p&gt;
      &lt;/td&gt;

      &lt;td valign="top" width="262"&gt;&amp;#160;&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160; Only exists when the job is running.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394" colspan="3"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="background-color: #d0e4f6"&gt;
      &lt;td valign="top" width="394"&gt;&amp;lt;hadoop.log.dir&amp;gt;/done&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;log of completed jobs&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;
        &lt;pre&gt;&lt;font color="#ff8000"&gt;mapreduce.jobtracker.jobhistory.completed.location&lt;/font&gt;&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;&amp;#160; job_&amp;lt;jobid&amp;gt;_&amp;lt;username&amp;gt;&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;Event logging. It includes all events of the job (e.g. job started, task started).&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;&amp;#160; job_&amp;lt;jobid&amp;gt;_conf.xml&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;Job conf file. It includes all configurations of the job. &lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394" colspan="3"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="background-color: #d0e4f6"&gt;
      &lt;td valign="top" width="394"&gt;&amp;lt;hadoop.log.dir&amp;gt;/userlogs&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;Log of attempts. &lt;font color="#ff0000"&gt;&lt;strong&gt;Stored on each task tracker.&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;&amp;#160; job_&amp;lt;jobid&amp;gt;&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;Each directory contains log of all attempts of the job.&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394" colspan="3"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr style="background-color: #d0e4f6"&gt;
      &lt;td valign="top" width="394"&gt;/jobtracker/jobsInfo (in HDFS)&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;Job Status Store&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;
        &lt;pre&gt;&lt;font color="#ff8000"&gt;mapreduce.jobtracker.persist.jobstatus.active&lt;/font&gt;&lt;/pre&gt;

        &lt;pre&gt;&lt;font color="#ff8000"&gt;mapreduce.jobtracker.persist.jobstatus.hours&lt;/font&gt;&lt;/pre&gt;

        &lt;pre&gt;&lt;font color="#ff8000"&gt;mapreduce.jobtracker.persist.jobstatus.dir&lt;/font&gt;&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="top" width="394"&gt;&amp;#160; &amp;lt;jobId&amp;gt;.info&lt;/td&gt;

      &lt;td valign="top" width="262"&gt;job status of a job&lt;/td&gt;

      &lt;td valign="top" width="289"&gt;&amp;#160;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Job logs in &lt;font face="Courier New"&gt;&amp;lt;hadoop.log.dir&amp;gt;/history/done&lt;/font&gt; directory are kept for &lt;font face="Courier New"&gt;mapreduce.jobtracker.jobhistory.maxage&lt;/font&gt;. Default value is 1 week. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1313912733180038180?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1313912733180038180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1313912733180038180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1313912733180038180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1313912733180038180'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/12/hadoop-log.html' title='Hadoop Log'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-9153715348467833393</id><published>2010-11-29T11:57:00.000-05:00</published><updated>2010-11-29T12:46:37.846-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Schedulers in supercomputers</title><content type='html'>&lt;h2&gt;LoadLeveler&lt;/h2&gt;  &lt;p&gt;&lt;a title="http://www.ccs.ornl.gov/eagle/LL.html" href="http://www.ccs.ornl.gov/eagle/LL.html"&gt;http://www.ccs.ornl.gov/eagle/LL.html&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://www.bu.edu/tech/research/training/scv-software-packages/loadleveler/" href="http://www.bu.edu/tech/research/training/scv-software-packages/loadleveler/"&gt;http://www.bu.edu/tech/research/training/scv-software-packages/loadleveler/&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://kb.iu.edu/data/azvs.html" href="http://kb.iu.edu/data/azvs.html"&gt;http://kb.iu.edu/data/azvs.html&lt;/a&gt;&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="751"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="316"&gt;&amp;nbsp;&lt;/td&gt;        &lt;td valign="top" width="98"&gt;&amp;nbsp;&lt;/td&gt;        &lt;td valign="top" width="335"&gt;&amp;nbsp;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="316"&gt;Cluster status&lt;/td&gt;        &lt;td valign="top" width="98"&gt;llstatus&lt;/td&gt;        &lt;td valign="top" width="335"&gt;&amp;nbsp;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="316"&gt;List jobs in the queues/classes&lt;/td&gt;        &lt;td valign="top" width="98"&gt;llq&lt;/td&gt;        &lt;td valign="top" width="335"&gt;&amp;nbsp;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="316"&gt;List information of classes/queues&lt;/td&gt;        &lt;td valign="top" width="98"&gt;llclass&lt;/td&gt;        &lt;td valign="top" width="335"&gt;&amp;nbsp;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="316"&gt;Reservation check&lt;/td&gt;        &lt;td valign="top" width="98"&gt;llqres&lt;/td&gt;        &lt;td valign="top" width="335"&gt;This may or may not work. Probably you should command &lt;em&gt;showres&lt;/em&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;h2&gt;PBS&lt;/h2&gt;  &lt;p&gt;pbsnodes&lt;/p&gt;  &lt;h2&gt;Moab&lt;/h2&gt;  &lt;p&gt;&lt;a title="http://www.clusterresources.com/products/mwm/docs/a.gcommandoverview.shtml" href="http://www.clusterresources.com/products/mwm/docs/a.gcommandoverview.shtml"&gt;http://www.clusterresources.com/products/mwm/docs/a.gcommandoverview.shtml&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://www.clusterresources.com/products/maui/docs/16.1simulationoverview.shtml" href="http://www.clusterresources.com/products/maui/docs/16.1simulationoverview.shtml"&gt;http://www.clusterresources.com/products/maui/docs/16.1simulationoverview.shtml&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;mshow -a&amp;#160; # show available resources&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-9153715348467833393?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/9153715348467833393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=9153715348467833393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/9153715348467833393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/9153715348467833393'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/11/schedulers-in-supercomputers.html' title='Schedulers in supercomputers'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4388979913661781065</id><published>2010-11-27T15:41:00.000-05:00</published><updated>2010-11-27T18:26:20.165-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><title type='text'>IOMeter</title><content type='html'>&lt;p&gt;Document: &lt;a href="http://iometer.cvs.sourceforge.net/viewvc/iometer/iometer/Docs/Iometer.pdf"&gt;http://iometer.cvs.sourceforge.net/viewvc/iometer/iometer/Docs/Iometer.pdf&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;: install IOMeter (it includes both dynamo and iometer GUI)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;: the linux package only includes dynamo (the runtime engine). It does not include GUI. So you need to connect dynamo to the Windows box on which IOMeter is installed. Use following command to start dynamo&lt;/p&gt;  &lt;p&gt;&lt;code&gt;sudo ./dynamo -i iometer_computer_host -n manager_name -m manager_computer_host&lt;/code&gt; &lt;/p&gt;  &lt;p&gt;Parameters:    &lt;br /&gt;&lt;code&gt;iometer_computer_host&lt;/code&gt;: host/ip where IOMeter GUI is run (Windows box)     &lt;br /&gt;&lt;code&gt;manager_computer_host&lt;/code&gt;: host/ip where dynamo is run     &lt;br /&gt;&lt;code&gt;manager_name&lt;/code&gt;: name of the dynamo manager (can be arbitrary. used to distinguish different dynamo managers connecting to the same IOMeter server)&lt;/p&gt;  &lt;p&gt;Several options that are confusing&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Disk Targets &amp;gt; # of Outstanding I/Os      &lt;br /&gt;&amp;quot;specifies the maximum number of outstanding asynchronous I/O operations per disk the selected worker(s) will attempt to have active at one time.&amp;quot;       &lt;br /&gt;&amp;quot;This control can be overridden by the # of Outstanding I/Os control group in the Test       &lt;br /&gt;Setup tab (depending on the Cycling Options).&amp;quot; &lt;/li&gt;    &lt;li&gt;Test Setup &amp;gt; Cycling Options      &lt;br /&gt;&amp;quot;The Cycling Options control group specifies the series of tests that is run for each access specification.&amp;quot;       &lt;ul&gt;       &lt;li&gt;Number of workers per manager          &lt;br /&gt;Workers are added in the order they are shown in the Topology panel &lt;/li&gt;        &lt;li&gt;Number of targets per worker          &lt;br /&gt;selected targets are added to each worker in the order they are shown in the Disk Targets or Network Targets tab for that worker. &lt;/li&gt;        &lt;li&gt;Number of outstanding I/O operations per target (disk workers only). &lt;/li&gt;     &lt;/ul&gt; Cycling Options       &lt;ol&gt;       &lt;li&gt;Normal - run all selected targets for all workers.          &lt;br /&gt;In all managers, all works are active and each work uses all its selected targets. &amp;quot;The number of outstanding I/Os per disk is specified by the # of Outstanding I/Os field in the Disk Targets tab.&amp;quot; &lt;/li&gt;        &lt;li&gt;Cycle Workers -- add step workers using all selected targets at a time          &lt;br /&gt;&amp;quot;This test type increases the number of workers for each manager in each test.&amp;quot;. In each test, the first &lt;em&gt;N&lt;/em&gt; (depending on iteration and step) workers listed in Topology panel are used. &lt;/li&gt;        &lt;li&gt;Cycle Targets -- add step targets for all workers at a time.          &lt;br /&gt;This test type increases the number of targets for each worker in each test. &lt;/li&gt;        &lt;li&gt;Increment Targets Parallel -- add step targets to all managers at a time.          &lt;br /&gt;          &lt;table style="list-style-type: disc; border-collapse: collapse" border="1" cellspacing="0" cellpadding="0" width="569"&gt;&lt;colgroup&gt;&lt;col style="width: 35pt; mso-width-source: userset; mso-width-alt: 1718" width="47" /&gt;&lt;col style="width: 83pt; mso-width-source: userset; mso-width-alt: 4059" width="111" /&gt;&lt;col style="width: 80pt; mso-width-source: userset; mso-width-alt: 3876" width="106" /&gt;&lt;col style="width: 68pt; mso-width-source: userset; mso-width-alt: 3291" width="90" /&gt;&lt;col style="width: 63pt; mso-width-source: userset; mso-width-alt: 3072" width="84" /&gt;&lt;col style="width: 98pt; mso-width-source: userset; mso-width-alt: 4754" width="130" /&gt;&lt;/colgroup&gt;&lt;tbody&gt;             &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="40" rowspan="2" width="46" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;&lt;strong&gt;Test #&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" width="217" colspan="2" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Manager 1&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" width="174" colspan="2" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Manager 2&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" rowspan="2" width="130" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;&lt;strong&gt;Targets per Manager&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 1&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 2&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 1&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;&lt;strong&gt;Worker 2&lt;/strong&gt;&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;3&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;3 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;4&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;4 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;           &lt;/tbody&gt;&lt;/table&gt;       &lt;/li&gt;        &lt;li&gt;Increment Targets Serial -- add step targets at a time.          &lt;br /&gt;          &lt;table style="list-style-type: disc; width: 582px; border-collapse: collapse; height: 248px" border="1" cellspacing="1" cellpadding="0" width="582"&gt;&lt;colgroup&gt;&lt;col style="width: 48pt" width="64" /&gt;&lt;col style="width: 59pt; mso-width-source: userset; mso-width-alt: 2852" width="78" /&gt;&lt;col style="width: 60pt; mso-width-source: userset; mso-width-alt: 2925" width="80" /&gt;&lt;col style="width: 48pt" width="64" /&gt;&lt;col style="width: 60pt; mso-width-source: userset; mso-width-alt: 2925" width="80" /&gt;&lt;col style="width: 75pt; mso-width-source: userset; mso-width-alt: 3657" width="100" /&gt;&lt;/colgroup&gt;&lt;tbody&gt;             &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="40" rowspan="2" width="64" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Test # &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" width="158" colspan="2" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Manager 1 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" width="144" colspan="2" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Manager 2 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" width="100" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Total Targets&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Worker 1 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font0"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Worker 2 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Worker 1 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font6"&gt;&lt;strong&gt;Worker 2 &lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" align="center"&gt;&amp;#160;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;1 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;1 target &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;1 target &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;3 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;1&lt;font class="font7"&gt; targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;3 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;4 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;4 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;5 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;1 target &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;5 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;6 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;0 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;6 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;7 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;1 target &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;7 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;8 &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;2 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl65" align="center"&gt;&lt;font face="Calibri"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 11pt"&gt;&lt;font class="font7"&gt;8 targets &lt;/font&gt;&lt;/font&gt;&lt;font class="font5"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;           &lt;/tbody&gt;&lt;/table&gt;       &lt;/li&gt;        &lt;li&gt;Cycle Targets and Workers -- add step targets at a time spread across workers          &lt;table style="list-style-type: disc; border-collapse: collapse" border="1" cellspacing="0" cellpadding="0" width="480"&gt;&lt;colgroup&gt;&lt;col style="width: 48pt" width="64" /&gt;&lt;col style="width: 63pt; mso-width-source: userset; mso-width-alt: 3072" width="84" /&gt;&lt;col style="width: 73pt; mso-width-source: userset; mso-width-alt: 3547" width="97" /&gt;&lt;col style="width: 65pt; mso-width-source: userset; mso-width-alt: 3145" width="86" /&gt;&lt;col style="width: 111pt; mso-width-source: userset; mso-width-alt: 5412" width="148" /&gt;&lt;/colgroup&gt;&lt;tbody&gt;             &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" height="20" width="64" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Test&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;#&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" width="84" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 1&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" width="97" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 2&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" width="86" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Worker 3&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl66" width="148" align="center"&gt;&lt;font face="Calibri"&gt;&lt;strong&gt;&lt;font style="font-size: 11pt"&gt;Targets&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;per Manager&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;3&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;4&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;0 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;4 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;5&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;1 target&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;3 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;              &lt;tr style="height: 15pt" height="20"&gt;               &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" height="20" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;6&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;2 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;                &lt;td style="padding-left: 1px; padding-right: 1px; vertical-align: middle; padding-top: 1px" class="xl67" align="center"&gt;&lt;font face="Calibri"&gt;&lt;font style="font-size: 11pt"&gt;6 targets&lt;/font&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;font style="font-size: 11pt"&gt;&amp;#160;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/td&gt;             &lt;/tr&gt;           &lt;/tbody&gt;&lt;/table&gt;       &lt;/li&gt;        &lt;li&gt;Cycle # Outstanding I/Os -- run step outstanding I/Os on all disks at a time. &lt;/li&gt;        &lt;li&gt;Cycle # Outstanding I/Os and Targets -- run step outstanding I/Os on step targets at a time &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Not all managers have the same number of works. Not all works have the same number of targets. Read following paragraph to see how IOMeter handles it.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The ending value for each sequence is determined differently for each quantity. For the number of workers per manager, it is determined by &lt;strong&gt;&lt;font color="#ff0000"&gt;the manager with the most workers&lt;/font&gt;&lt;/strong&gt; in the Topology panel. For the number of targets per worker, it is determined by &lt;strong&gt;&lt;font color="#ff0000"&gt;the worker with the most targets &lt;/font&gt;&lt;/strong&gt;selected in the Disk Targets or Network Targets tab. For the outstanding I/Os per target, it is determined by the # of Outstanding I/Os control group in the Test Setup tab.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If not all managers have the same number of workers, or not all workers have the same number of targets, &lt;strong&gt;&lt;font color="#ff0000"&gt;those managers/workers with less than the maximum number of workers/targets will repeat at their highest value&lt;/font&gt;&lt;/strong&gt; while other managers/workers continue to increase.&amp;#160; &amp;quot;       &lt;br /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In Disk Targets Tab, &amp;quot;A yellow icon with a red slash through it means that the drive needs to be prepared before the test starts&amp;quot;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;&lt;strong&gt;Yellow disk icons represent logical drives&lt;/strong&gt; (i.e. those with a drive letter). They are shown only if they are writable. Disk workers access logical drives by reading and writing a file called &lt;strong&gt;iobw.tst&lt;/strong&gt; in the root directory of the drive. If this file exists, the drive is shown with a plain yellow icon; if the file does not exist, the drive is shown with a red slash through the icon. (If this file exists but is not writable, the drive is considered read-only and is not shown at all.)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; If you select a drive that does not have an iobw.tst file, Iometer will begin the test by creating this file and &lt;strong&gt;expanding it until the drive is full&lt;/strong&gt; (this is shown as “Preparing Drives” in the status bar). You can change the size of this file to control how much of the disk Iometer can use by setting the Maximum Disk Size control to the desired size (in sectors).      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;Blue disk icons represent physical drives.&lt;/strong&gt; They are shown only if they contain nothing but free space (no defined partitions). Disk workers access physical drives by writing direct to the raw disk. Physical drives do not use an iobw.tst file. Running with physical drives is recommended.&amp;quot;      &lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4388979913661781065?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4388979913661781065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4388979913661781065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4388979913661781065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4388979913661781065'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/11/iometer.html' title='IOMeter'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4672185929471459406</id><published>2010-11-12T14:27:00.000-05:00</published><updated>2010-11-12T16:21:48.123-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaCOG'/><title type='text'>JsUnit Maven Plugin</title><content type='html'>&lt;p&gt;Document is at &lt;a title="http://jsunit.berlios.de/maven2.html" href="http://jsunit.berlios.de/maven2.html"&gt;http://jsunit.berlios.de/maven2.html&lt;/a&gt;. It's too brief, especially following paragraph:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The type of the test suite, one of the following values: &lt;/p&gt;   &lt;dl&gt;&lt;dt&gt;ALLTESTS &lt;/dt&gt;&lt;dd&gt;Looks for a class AllTests derived from &lt;a href="http://jsunit.berlios.de/classTestSuite.html"&gt;TestSuite&lt;/a&gt; and runs its suite. &lt;/dd&gt;&lt;dt&gt;TESTSUITES &lt;/dt&gt;&lt;dd&gt;Looks for all classes ending with &lt;a href="http://jsunit.berlios.de/classTestSuite.html"&gt;TestSuite&lt;/a&gt; and that are derived from &lt;a href="http://jsunit.berlios.de/classTestSuite.html"&gt;TestSuite&lt;/a&gt; and run their suites. &lt;/dd&gt;&lt;dt&gt;TESTCASES &lt;/dt&gt;&lt;dd&gt;Looks for all classes ending with &lt;a href="http://jsunit.berlios.de/classTestCase.html"&gt;TestCase&lt;/a&gt; and that are derived from &lt;a href="http://jsunit.berlios.de/classTestCase.html"&gt;TestCase&lt;/a&gt; and runs them (the default). &lt;/dd&gt;&lt;/dl&gt;&lt;/blockquote&gt;  &lt;p&gt;The problem is what &amp;quot;derived from&amp;quot; means and how to to that. I will show in detail how to use JsUnit plugin. &lt;/p&gt;  &lt;h2&gt;1) sample test file&lt;/h2&gt;  &lt;p&gt;Following is a dummy test file. It should be put into &lt;em&gt;src/test/js&lt;/em&gt;.&lt;/p&gt;  &lt;pre class="brush:javascript;"&gt;var dummyobj = dummyobj || {};

function DummyTest(name) {
  TestCase.call(this, name);
};

DummyTest.inherits(TestCase);

DummyTest.prototype.setUp = function() {
    dummyobj.name = &amp;quot;Gerald&amp;quot;;
};

DummyTest.prototype.tearDown = function() {
    delete dummyobj.name;
};

DummyTest.prototype.testDummy = function() {
  this.assertEquals('Gerald', dummyobj.name);
};&lt;/pre&gt;

&lt;p&gt;DummyTest is the test case. 
  &lt;br /&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;It &amp;quot;inherits&amp;quot; from class &lt;em&gt;TestCase&lt;/em&gt;. All of its functions whose name start with &amp;quot;test&amp;quot; will be tested. &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;

&lt;h2&gt;2) Inherit implementation&lt;/h2&gt;

&lt;p&gt;Following is implementation of &lt;em&gt;inherit&lt;/em&gt; borrowedfrom Shindig code. It can be put in a file &lt;em&gt;inherit_implementation.js&lt;/em&gt; under directory &lt;em&gt;src/main/js&lt;/em&gt;.&lt;/p&gt;

&lt;pre class="brush:javascript;"&gt;Function.prototype.inherits = function(parentCtor) {
    function tempCtor() {};
    tempCtor.prototype = parentCtor.prototype;
    this.superClass_ = parentCtor.prototype;
    this.prototype = new tempCtor();
    this.prototype.constructor = this;
};&lt;/pre&gt;

&lt;h2&gt;3) Pom.xml &lt;/h2&gt;

&lt;pre class="brush:xml;"&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;de.berlios.jsunit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jsunit-maven2-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;test&amp;lt;/id&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;sourceDirectory&amp;gt;${basedir}/src/main/js&amp;lt;/sourceDirectory&amp;gt;
                &amp;lt;sources&amp;gt;
                    &amp;lt;source&amp;gt;inherit_implementation.js&amp;lt;/source&amp;gt; &lt;br /&gt;                    &amp;lt;source&amp;gt;file_to_be_tested.js&amp;lt;/source&amp;gt;
                &amp;lt;/sources&amp;gt;
                &amp;lt;testSourceDirectory&amp;gt;${basedir}/src/test/js&amp;lt;/testSourceDirectory&amp;gt;
                &amp;lt;testSuites&amp;gt;
                    &amp;lt;testSuite&amp;gt;
                        &amp;lt;name&amp;gt;SampleSuite&amp;lt;/name&amp;gt;
                        &amp;lt;type&amp;gt;TESTCASES&amp;lt;/type&amp;gt;
                        &amp;lt;includes&amp;gt;
                            &amp;lt;include&amp;gt;*/*test.js&amp;lt;/include&amp;gt;
                        &amp;lt;/includes&amp;gt;
                    &amp;lt;/testSuite&amp;gt;
                &amp;lt;/testSuites&amp;gt;
            &amp;lt;/configuration&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;jsunit-test&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/pre&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;For some tests, you need to provide fake window object, XmlHttpRequest object, DOM objects, etc. Project &lt;a href="https://github.com/thatcher/env-js" target="_blank"&gt;env-js&lt;/a&gt; (&lt;a href="http://www.envjs.com/" target="_blank"&gt;site&lt;/a&gt;) is exactly designed for this purpose. It provides a simulated browser environment. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4672185929471459406?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4672185929471459406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4672185929471459406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4672185929471459406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4672185929471459406'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/11/jsunit-maven-plugin.html' title='JsUnit Maven Plugin'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2989410091742136726</id><published>2010-11-08T13:56:00.000-05:00</published><updated>2010-11-08T13:57:06.544-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>How to run/debug Shindig in Eclipse</title><content type='html'>&lt;p&gt;Instructions here (&lt;a title="http://shindig.apache.org/developers/java/build.html#Setting_up_an_Eclipse_project_to_build_Apache_Shindig" href="http://shindig.apache.org/developers/java/build.html#Setting_up_an_Eclipse_project_to_build_Apache_Shindig"&gt;http://shindig.apache.org/developers/java/build.html#Setting_up_an_Eclipse_project_to_build_Apache_Shindig&lt;/a&gt;) are for old versions of Eclipse.&lt;/p&gt;  &lt;p&gt;I am using Eclipse Helios. You should install Maven plugin m2eclipse before following following instructions.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download or check out shindig code. &lt;/li&gt;    &lt;li&gt;File –&amp;gt; Import      &lt;br /&gt;Maven –&amp;gt; Existing Maven Projects       &lt;br /&gt;Specify the root directory of shindig code. &lt;/li&gt;    &lt;li&gt;Right click top level imported project (*-project):&amp;#160; Debug As –&amp;gt; Debug Configuration      &lt;br /&gt;Create a new configuration for “Maven Build”.       &lt;br /&gt;Base directory: root directory of shindig code       &lt;br /&gt;Profiles: run       &lt;br /&gt;Unselect “Skip Tests”.       &lt;br /&gt;If you want to use a port number rather than 8080, add a parameter “jetty.port”.       &lt;br /&gt;Clicek “Debug”. &lt;/li&gt;    &lt;li&gt;Jetty server should run successfully. Look at your console for possible error messages. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Add breakpoints, then send a request to Jetty server. Eclipse complains that it cannot find source code for the debugged app, and prompt you to add source lookup directories.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2989410091742136726?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2989410091742136726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2989410091742136726' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2989410091742136726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2989410091742136726'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/11/how-to-rundebug-shindig-in-eclipse.html' title='How to run/debug Shindig in Eclipse'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-3238933144850989065</id><published>2010-09-15T23:34:00.001-04:00</published><updated>2010-09-15T23:34:44.635-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='ogce'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>OAuth in OGCE gadget container</title><content type='html'>&lt;p&gt;OGCE gadget container makes support of OAuth as easy as possible.&lt;/p&gt;  &lt;p&gt;Follow two files are the most important related to OAuth configuration.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;config/shindig/shindig.properties      &lt;br /&gt;Most important config parameter is &lt;em&gt;shindig.signing.global-callback-url&lt;/em&gt;. It has been rewritten correctly so the end users don’t need to worry about it. &lt;/li&gt;    &lt;li&gt;config/shindig/oauth.json      &lt;br /&gt;This files contains information of all consumers of which the OGCE gadget container is a proxy. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;If you want to write OAuth gadget, follow instructions showed on this page: &lt;a title="http://code.google.com/apis/gadgets/docs/oauth.html" href="http://code.google.com/apis/gadgets/docs/oauth.html"&gt;http://code.google.com/apis/gadgets/docs/oauth.html&lt;/a&gt;.     &lt;br /&gt;More complicated cases: &lt;a title="http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy" href="http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy"&gt;http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-3238933144850989065?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/3238933144850989065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=3238933144850989065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3238933144850989065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3238933144850989065'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/09/oauth-in-ogce-gadget-container.html' title='OAuth in OGCE gadget container'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1770493732269806909</id><published>2010-01-06T19:07:00.002-05:00</published><updated>2010-02-21T16:31:06.472-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Tomcat SSL configuration. Import certificate chain to keystore (emit error “keytool error: java.lang.Exception: Input not an X.509 certificate”)</title><content type='html'>&lt;p&gt;I seldom use mutual authentication in the context of SSL. Recently, in our derived project (integration with MyOSG), we need to enforce use of mutual SSL authentication.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Enable client authentication in Tomcat server&lt;/h2&gt;  &lt;p&gt;At first, I enabled it in tomcat server configuration file&lt;/p&gt;  

&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[
&lt;Connector port="7443" protocol="HTTP/1.1" SSLEnabled="true"
    maxThreads="150" scheme="https" secure="true"
    clientAuth="true" sslProtocol="TLS"
    keystoreFile="keystore/keystore"
    keystorePass="changeit"
    keyAlias="your-cert-alias" /&gt;
&lt;/script&gt;

&lt;p&gt;An important option is &amp;quot;clientAuth”. 
  &lt;br /&gt;&lt;font color="#ff0000"&gt;Note: before this step, I have generated and imported a certificate for tomcat server.&lt;/font&gt;&lt;/p&gt;
&lt;h2&gt;Import user certificate&lt;/h2&gt;
&lt;p&gt;This is done by the end users who wish to access the protected services. They need to &lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;import received certificate from CA to their browser 
    &lt;br /&gt;Actually, both the private key and certificate need to be imported. 
    &lt;br /&gt;For Firefox, only pkcs#12 format is supported.&amp;#160; If the private key has been imported, you just need to import certificate whose format can be PEM, binary, etc. &lt;/li&gt;
  &lt;li&gt;import server’s certificate into trusted ca repository in browser 
    &lt;br /&gt;The aim is to make the browser trust the certificate received from remote service. It’s useful when the service certificate is not issued by a well-known top-level CA. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After those two steps, I directed my browser to the service url. Unfortunately, I got the following error:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_qiIXUonGAyk/S0UlwqOGl1I/AAAAAAAAAwY/VoW9t5xdpRw/s1600-h/image%5B10%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_qiIXUonGAyk/S0Ulw0rjInI/AAAAAAAAAwc/NfqQ7itg9sM/image_thumb%5B6%5D.png?imgmax=800" width="649" height="337" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After digging a little bit, I found out the cause was that tomcat server does not trust certificate sent by my browser. So the solution is simple: add certificate chain related to my certificate to tomcat keystore.&lt;/p&gt;
&lt;p&gt;I got the certificate chain from the issuer of my certificate. It’s in PKCS#7 format and contains two certificates in the file. You can view PKCS7-formatted file using following commands: 
  &lt;br /&gt;1) openssl pkcs7 -print_certs -text &amp;lt; pkcs7_cert_chain.pem 
  &lt;br /&gt;2) keytool -printcert –file pkcs7_cert_chain.pem&lt;/p&gt;
&lt;p&gt;When I tried to import it into keystore using following command 
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; keytool -importcert -file pkcs7_cert_chain.pem -keystore keystore -alias test-cert –trustcacerts 
  &lt;br /&gt;I got the following error 
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;&lt;font color="#ff0000"&gt;keytool error: java.lang.Exception: Input not an X.509 certificate&lt;/font&gt;&lt;/strong&gt; 
  &lt;br /&gt;I am sure keytool can recognize the file because the following command prints out information in the file correctly. 
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; keytool -printcert –file pkcs7_cert_chain.pem&lt;/p&gt;
&lt;h2&gt;Solution &lt;/h2&gt;
&lt;p&gt;After reading keytool manual carefully, I found following statements:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Importing a New Trusted Certificate &lt;/p&gt;
  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Before adding the certificate to the keystore, keytool tries to verify it by attempting to construct 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; a chain of trust from that certificate to a self-signed certificate (belonging to a root CA), using 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; trusted certificates that are already available in the keystore.&lt;/p&gt;
  &lt;p&gt;Importing a Certificate Reply &lt;/p&gt;
  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; ……&lt;/p&gt;
  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; o If the reply is a PKCS#7 formatted certificate chain, the chain is first ordered (with the user 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; certificate first and the self-signed root CA certificate last), before keytool attempts to 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; match the root CA certificate provided in the reply with any of the trusted certificates in the 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; keystore or the &amp;quot;cacerts&amp;quot; keystore file (if the -trustcacerts option was specified). If no match 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; can be found, the information of the root CA certificate is printed out, and the user is 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; prompted to verify it, e.g., by comparing the displayed certificate fingerprints with the fin- 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; gerprints obtained from some other (trusted) source of information, which might be the root CA 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; itself. The user then has the option of aborting the import operation. If the -noprompt option 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; is given, however, there will be no interaction with the user.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, what I was doing is to import a trusted certificate chain. This is not allowed directly. keytool just accepts cert file that includes a single certificate. &lt;/p&gt;
&lt;p&gt;So I extracted two certificates into two files, and fed them into keytool one by one. Details: 
  &lt;br /&gt;Use command 
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; openssl pkcs7 -print_certs &amp;lt; pkcs7_cert_chain.pem 
  &lt;br /&gt;to display the two certificates in the original pkcs7 file. And then copied and pasted each cert into an individual file.&lt;/p&gt;
&lt;p&gt;Note: when you are importing a certificate reply from a CA, certificate chain can be imported directly into keystore. However, before doing that, you must guarantee that the corresponding private key has already been imported in to the same keystore.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1770493732269806909?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1770493732269806909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1770493732269806909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1770493732269806909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1770493732269806909'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2010/01/tomcat-ssl-configuration-import.html' title='Tomcat SSL configuration. Import certificate chain to keystore (emit error “keytool error: java.lang.Exception: Input not an X.509 certificate”)'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_qiIXUonGAyk/S0Ulw0rjInI/AAAAAAAAAwc/NfqQ7itg9sM/s72-c/image_thumb%5B6%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2656917399200311481</id><published>2009-11-13T13:07:00.000-05:00</published><updated>2009-11-13T13:08:19.423-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='gadget'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>Resources about OAuth support in Gadget</title><content type='html'>&lt;p&gt;&lt;a title="http://sites.google.com/site/oauthgoog/oauth-proxy" href="http://sites.google.com/site/oauthgoog/oauth-proxy"&gt;http://sites.google.com/site/oauthgoog/oauth-proxy&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/apis/gadgets/docs/oauth.html" href="http://code.google.com/apis/gadgets/docs/oauth.html"&gt;http://code.google.com/apis/gadgets/docs/oauth.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/apis/accounts/docs/OAuth.html" href="http://code.google.com/apis/accounts/docs/OAuth.html"&gt;http://code.google.com/apis/accounts/docs/OAuth.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://groups.google.com/group/oauth/browse_thread/thread/5dea93b44dbbb628" href="http://groups.google.com/group/oauth/browse_thread/thread/5dea93b44dbbb628"&gt;http://groups.google.com/group/oauth/browse_thread/thread/5dea93b44dbbb628&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;OAuth test client: &lt;a title="http://term.ie/oauth/example/client.php" href="http://term.ie/oauth/example/client.php"&gt;http://term.ie/oauth/example/client.php&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Google OAuth Playground: &lt;a title="http://googlecodesamples.com/oauth_playground/" href="http://googlecodesamples.com/oauth_playground/"&gt;http://googlecodesamples.com/oauth_playground/&lt;/a&gt; (just for Google’s APIs)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2656917399200311481?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2656917399200311481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2656917399200311481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2656917399200311481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2656917399200311481'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/11/resources-about-oauth-support-in-gadget.html' title='Resources about OAuth support in Gadget'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5456021414635567123</id><published>2009-11-05T00:00:00.001-05:00</published><updated>2009-11-05T00:00:43.608-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>A bug in Shindig code (for revision 832845)</title><content type='html'>&lt;p&gt;Recently, I tried to deploy cyberaide filetransfer gadget (&lt;a title="http://lily01.rit.edu/cyberaideJobman.xml" href="http://lily01.rit.edu/cyberaideFiletransfer.xml"&gt;http://lily01.rit.edu/cyberaideFiletransfer.xml&lt;/a&gt;) and jobman gadget (&lt;a title="http://lily01.rit.edu/cyberaideJobman.xml" href="http://lily01.rit.edu/cyberaideJobman.xml"&gt;http://lily01.rit.edu/cyberaideJobman.xml&lt;/a&gt;). They did NOT work in shindig server built from &lt;font color="#ff0000"&gt;revision 832845&lt;/font&gt;. Those two gadgets use ‘tab’ feature which is not implemented well in shindig code. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Problem description&lt;/font&gt;&lt;/strong&gt;     &lt;br /&gt;See source code of tab feature at &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/features/src/main/javascript/features/tabs/tabs.js?p=832845" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/features/src/main/javascript/features/tabs/tabs.js?p=832845"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/features/src/main/javascript/features/tabs/tabs.js?p=832845&lt;/a&gt;.     &lt;br /&gt;In this file, function ‘&lt;em&gt;html_sanitize&lt;/em&gt;’ is used. It is a function from caja javascript library.     &lt;br /&gt;Shindig website does not provide much useful information about integration of caja. &lt;a title="http://incubator.apache.org/shindig/developers/java/build.html#Running_with_Caja" href="http://incubator.apache.org/shindig/developers/java/build.html#Running_with_Caja"&gt;http://incubator.apache.org/shindig/developers/java/build.html#Running_with_Caja&lt;/a&gt;     &lt;br /&gt;I found a useful wiki page in caja project: &lt;a title="http://code.google.com/p/google-caja/wiki/GettingStarted" href="http://code.google.com/p/google-caja/wiki/GettingStarted"&gt;http://code.google.com/p/google-caja/wiki/GettingStarted&lt;/a&gt;.     &lt;br /&gt;Basically the user needs to add following text to ModulePrefs element of the gadget xml file     &lt;br /&gt;&lt;code&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Require feature=&amp;quot;caja&amp;quot;/&amp;gt;&lt;/code&gt;     &lt;br /&gt;After I changed the gadget xml file, it still didn’t work. It seems that after caja library sanitizes the rendered html/javascript code, some useful code is removed. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;My solution&lt;/font&gt;&lt;/strong&gt;    &lt;br /&gt;To make it simple, I disabled caja. I just removed invocations of functions belonging to caja library. Concretely, I removed invocations of function ‘&lt;em&gt;html_sanitize’&lt;/em&gt; in file ‘&lt;em&gt;tab.js&lt;/em&gt;’&lt;/p&gt;  &lt;p&gt;Also, feature ‘minimessage’ also uses caja functions to sanitize html/javascript. If your gadgets use that feature, corresponding changes must be made as well.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5456021414635567123?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5456021414635567123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5456021414635567123' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5456021414635567123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5456021414635567123'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/11/bug-in-shindig-code-for-revision-832845.html' title='A bug in Shindig code (for revision 832845)'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-7874035850399600274</id><published>2009-11-02T16:48:00.000-05:00</published><updated>2009-11-02T16:49:05.916-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>X connection to localhost:xx.x broken (explicit kill or server shutdown)</title><content type='html'>&lt;p&gt;When I run tomcat server, I got this weird problem. It seems that tomcat tries to access GUI, which is contrary to my thought that tomcat is a background daemon. &lt;/p&gt;  &lt;p&gt;A simple google search brought me lots of posts about this problem: &lt;a title="http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;hs=ugP&amp;amp;q=tomcat+connection+to+localhost%3A+broken+%28explicit+kill+or+server+shutdown%29&amp;amp;aq=f&amp;amp;oq=&amp;amp;aqi=" href="http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;hs=ugP&amp;amp;q=tomcat+connection+to+localhost%3A+broken+%28explicit+kill+or+server+shutdown%29&amp;amp;aq=f&amp;amp;oq=&amp;amp;aqi="&gt;http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;hs=ugP&amp;amp;q=tomcat+connection+to+localhost%3A+broken+%28explicit+kill+or+server+shutdown%29&amp;amp;aq=f&amp;amp;oq=&amp;amp;aqi=&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;According to suggestion from this post &lt;a title="http://bugs.mysql.com/bug.php?id=24226" href="http://bugs.mysql.com/bug.php?id=24226"&gt;http://bugs.mysql.com/bug.php?id=24226&lt;/a&gt;, I just unset environment variable *DISPLAY* in *&lt;em&gt;startup.sh&lt;/em&gt;*.    &lt;br /&gt;In bash, use *&lt;strong&gt;&lt;font color="#ff0000"&gt;unset DISPLAY&lt;/font&gt;&lt;/strong&gt;*&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-7874035850399600274?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/7874035850399600274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=7874035850399600274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7874035850399600274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7874035850399600274'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/11/x-connection-to-localhostxxx-broken.html' title='X connection to localhost:xx.x broken (explicit kill or server shutdown)'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-3313384766242694319</id><published>2009-11-02T16:39:00.000-05:00</published><updated>2009-11-02T16:40:27.194-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='gadget'/><title type='text'>Enable and disable Shindig caching</title><content type='html'>&lt;p&gt;Shindig implements a complex caching hierarchy including referred external resources, locale messages, gadget specification files, etc.   &lt;br /&gt;During development phase, the developers want to disable caching to make modifications take effect immediately.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Build-Time Solution     &lt;br /&gt;It is according to this post &lt;a title="https://studio.atlassian.com/browse/AG-145" href="https://studio.atlassian.com/browse/AG-145"&gt;https://studio.atlassian.com/browse/AG-145&lt;/a&gt;.       &lt;br /&gt;Download source code tree and build the war file using command “&lt;strong&gt;&lt;font color="#ff0000"&gt;mvn –Pdebug package&lt;/font&gt;&lt;/strong&gt;”      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Run-time solution     &lt;br /&gt;HttpCache: caches http request sent out from shindig server. During gadget rendering, this is controlled by “nocache” parameter. So when you render a gadget, add parameter ‘nocache’ with value 1.      &lt;br /&gt;I don’t know how to do it at server side.&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-3313384766242694319?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/3313384766242694319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=3313384766242694319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3313384766242694319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3313384766242694319'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/11/enable-and-disable-shindig-caching.html' title='Enable and disable Shindig caching'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-8661060850296517502</id><published>2009-10-31T23:58:00.000-04:00</published><updated>2009-10-31T23:59:11.439-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gadget'/><title type='text'>Transition from _IG_* APIs to gadgets.* APIs</title><content type='html'>&lt;p&gt;iGoogle announced that legacy gadget APIs (_IG_*) are deprecated:   &lt;br /&gt;&lt;a title="http://igoogledeveloper.blogspot.com/2009/09/more-things-change-more-they-stay-same.html" href="http://igoogledeveloper.blogspot.com/2009/09/more-things-change-more-they-stay-same.html"&gt;http://igoogledeveloper.blogspot.com/2009/09/more-things-change-more-they-stay-same.html&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://groups.google.com/group/Google-Gadgets-API/browse_thread/thread/7f1aa77dcf90064c" href="http://groups.google.com/group/Google-Gadgets-API/browse_thread/thread/7f1aa77dcf90064c"&gt;http://groups.google.com/group/Google-Gadgets-API/browse_thread/thread/7f1aa77dcf90064c&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Migration guide:   &lt;br /&gt;&lt;a title="http://code.google.com/apis/gadgets/docs/migration.html" href="http://code.google.com/apis/gadgets/docs/migration.html"&gt;http://code.google.com/apis/gadgets/docs/migration.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It would be great if there is a migration tool that automate the process.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-8661060850296517502?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/8661060850296517502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=8661060850296517502' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/8661060850296517502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/8661060850296517502'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/10/transition-from-ig-apis-to-gadgets-apis.html' title='Transition from _IG_* APIs to gadgets.* APIs'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5786634771657950160</id><published>2009-09-24T17:02:00.001-04:00</published><updated>2009-09-24T23:13:39.619-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sling'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jackrabbit'/><title type='text'>Trial of Apache Sling</title><content type='html'>&lt;h3&gt;Introduction &lt;/h3&gt;  &lt;p&gt;Sling is based on Felix which is an implementation of OGSi. It includes Felix webconsole (&lt;a title="http://felix.apache.org/site/apache-felix-web-console.html" href="http://felix.apache.org/site/apache-felix-web-console.html"&gt;http://felix.apache.org/site/apache-felix-web-console.html&lt;/a&gt;) bundle to make it easy to inspect OSGi framework. Also Sling integrates Jackrabbit and wraps it as an OSGi bundle. To update Java Content Repository, the client app can send regular HTTP POST requests. &lt;strong&gt;&lt;font color="#ff0000"&gt;In other words, it exposes Java Content Repository in a REST way.&lt;/font&gt;&lt;/strong&gt;    &lt;br /&gt;It can be run either independently or in a servlet container (e.g. Apache Tomcat).&lt;/p&gt;  &lt;h3&gt;Resources &lt;/h3&gt;  &lt;p&gt;Sling: &lt;a title="http://sling.apache.org/site/index.html" href="http://sling.apache.org/site/index.html"&gt;http://sling.apache.org/site/index.html&lt;/a&gt;     &lt;br /&gt;Useful Sling help: &lt;a title="http://felix.apache.org/site/apache-felix-framework-usage-documentation.html" href="http://felix.apache.org/site/apache-felix-framework-usage-documentation.html"&gt;http://felix.apache.org/site/apache-felix-framework-usage-documentation.html&lt;/a&gt;     &lt;br /&gt;Install and upgrade bundles in Felix web console: &lt;a title="http://sling.apache.org/site/installing-and-upgrading-bundles.html" href="http://sling.apache.org/site/installing-and-upgrading-bundles.html"&gt;http://sling.apache.org/site/installing-and-upgrading-bundles.html&lt;/a&gt;     &lt;br /&gt;Address of Felix Management Web Console: &lt;a title="http://gf13.ucs.indiana.edu:4040/system/console/" href="http://ip_address:port/system/console/"&gt;http://ip_address:port/system/console/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;When I clicked “Configuration” link on the top, Null Pointer Exception was thrown out.     &lt;br /&gt;It turns out that this is problem of Felix webconsole. See     &lt;br /&gt;&lt;a title="http://issues.apache.org/jira/browse/FELIX-1135" href="http://issues.apache.org/jira/browse/FELIX-1135"&gt;http://issues.apache.org/jira/browse/FELIX-1135&lt;/a&gt;     &lt;br /&gt;&lt;a title="http://issues.apache.org/jira/browse/FELIX-1028" href="http://issues.apache.org/jira/browse/FELIX-1028"&gt;http://issues.apache.org/jira/browse/FELIX-1028&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This post contains some useful information &lt;a title="http://groups.google.com/group/sakai-kernel/web/building-3akai-sling" href="http://groups.google.com/group/sakai-kernel/web/building-3akai-sling"&gt;http://groups.google.com/group/sakai-kernel/web/building-3akai-sling&lt;/a&gt;. &lt;/p&gt;  &lt;h3&gt;Solution&lt;/h3&gt;  &lt;p&gt;Download sling (standalone distribution) and unzip the tarball:    &lt;br /&gt;&lt;a title="http://mirror.cc.columbia.edu/pub/software/apache/sling/org.apache.sling.launchpad.app-5-incubator-bin.tar.gz" href="http://mirror.cc.columbia.edu/pub/software/apache/sling/org.apache.sling.launchpad.app-5-incubator-bin.tar.gz"&gt;http://mirror.cc.columbia.edu/pub/software/apache/sling/org.apache.sling.launchpad.app-5-incubator-bin.tar.gz&lt;/a&gt;     &lt;br /&gt;Download new version of felix webconsole:     &lt;br /&gt;&lt;a href="https://issues.apache.org/jira/secure/attachment/12407768/org.apache.felix.webconsole-1.2.9-SNAPSHOT.jar"&gt;https://issues.apache.org/jira/secure/attachment/12407768/org.apache.felix.webconsole-1.2.9-SNAPSHOT.jar&lt;/a&gt;     &lt;br /&gt;Assume the new version of webconsole is downloaded to dir &amp;lt;DIR&amp;gt; &lt;/p&gt;  &lt;p&gt;Execute following commands in the directory where sling tarball is unzipped.&lt;/p&gt;  &lt;pre&gt;jar xf org.apache.sling.launchpad.app-5-incubator.jar 
cd resources/bundles/5/ 
rm org.apache.felix.webconsole-1.2.8.jar 
cp &amp;lt;dir&amp;gt;/org.apache.felix.webconsole-1.2.9-SNAPSHOT.jar ./ 
jar cMf org.apache.sling.launchpad.app-5-incubator.jar resources META-INF org&lt;/pre&gt;

&lt;p&gt;Run the server: &lt;/p&gt;

&lt;pre&gt;java -jar org.apache.felix.webconsole-1.2.8.jar -p 4040&lt;/pre&gt;

&lt;p&gt;Note: you CANNOT use arbitrary new version of felix webconsole without updating other components of felix package. The reason is that different versions of felix console requires different versions of felix core/OSGi.&lt;/p&gt;

&lt;h3&gt;Misc.&lt;/h3&gt;

&lt;p&gt;If you are using both JCR Installer and Felix web console to update a bundle, you will get into trouble. 
  &lt;br /&gt;JCR installer: 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a title="http://sling.apache.org/site/jcr-installer-jcrjcrinstall-and-osgiinstaller.html" href="http://sling.apache.org/site/jcr-installer-jcrjcrinstall-and-osgiinstaller.html"&gt;http://sling.apache.org/site/jcr-installer-jcrjcrinstall-and-osgiinstaller.html&lt;/a&gt; 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; JCR installer tries to install OSGi bundles/modules found in Java Content Repository. 

  &lt;br /&gt;Bug 

  &lt;br /&gt;&amp;#160;&amp;#160; “JCR Install prevents update of bundle through other channels like the web console” 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a title="http://issues.apache.org/jira/browse/SLING-1106" href="http://issues.apache.org/jira/browse/SLING-1106"&gt;http://issues.apache.org/jira/browse/SLING-1106&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5786634771657950160?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5786634771657950160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5786634771657950160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5786634771657950160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5786634771657950160'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/09/trial-of-apache-sling.html' title='Trial of Apache Sling'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6126048705122816301</id><published>2009-09-23T23:37:00.000-04:00</published><updated>2009-09-25T16:21:55.789-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jackrabbit'/><title type='text'>Java Conent Repository - Jackrabbit</title><content type='html'>&lt;h2&gt;Resources&lt;/h2&gt;  &lt;p&gt;Wiki: &lt;a title="http://en.wikipedia.org/wiki/Content_repository_API_for_Java" href="http://en.wikipedia.org/wiki/Content_repository_API_for_Java"&gt;http://en.wikipedia.org/wiki/Content_repository_API_for_Java&lt;/a&gt;     &lt;br /&gt;JSR 170: &lt;a href="http://jcp.org/en/jsr/detail?id=170"&gt;http://jcp.org/en/jsr/detail?id=170&lt;/a&gt;     &lt;br /&gt;JSR 170 API: &lt;a title="http://www.day.com/maven/jsr170/javadocs/jcr-1.0/index.html" href="http://www.day.com/maven/jsr170/javadocs/jcr-1.0/index.html"&gt;http://www.day.com/maven/jsr170/javadocs/jcr-1.0/index.html&lt;/a&gt;    &lt;br /&gt;JSR 283 (JCR 2.0): &lt;a href="http://jcp.org/en/jsr/detail?id=283"&gt;http://jcp.org/en/jsr/detail?id=283&lt;/a&gt; (in progress)     &lt;br /&gt;Jackrabbit: &lt;a title="http://jackrabbit.apache.org/" href="http://jackrabbit.apache.org/"&gt;http://jackrabbit.apache.org/&lt;/a&gt;     &lt;br /&gt;List of Jackrabbit components: &lt;a title="http://jackrabbit.apache.org/jackrabbit-components.html" href="http://jackrabbit.apache.org/jackrabbit-components.html"&gt;http://jackrabbit.apache.org/jackrabbit-components.html&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;Introduction&lt;/h2&gt;  &lt;p&gt;Jackrabbit implements JSR 170 and JSR 283. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Wrap JCR to make it a WebDAV server so that WebDAC client can access it.      &lt;br /&gt;Actually it is a fully featured WebDAV server backed by the JCR repository.       &lt;br /&gt;Address for default repository: &lt;a href="http://your_ip:your_port/repository/default/"&gt;http://your_ip:your_port/repository/default/&lt;/a&gt;       &lt;br /&gt;It seems that this method only exposes the file and directories in JCR. If you want more fine-grained access, use JCR remoting instead.       &lt;br /&gt;Also see: &lt;a title="http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-WebDAVaccess" href="http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-WebDAVaccess"&gt;http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-WebDAVaccess&lt;/a&gt;       &lt;br /&gt;&lt;a title="http://jackrabbit.apache.org/jackrabbit-web-application.html" href="http://jackrabbit.apache.org/jackrabbit-web-application.html"&gt;http://jackrabbit.apache.org/jackrabbit-web-application.html&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;JCR remoting      &lt;br /&gt;Provides more fine-grained content access.       &lt;br /&gt;Address for all workspaces of JCR repository: &lt;a href="http://your_ip:your_port/server"&gt;http://your_ip:your_port/server&lt;/a&gt;       &lt;br /&gt;Also see: &lt;a title="http://jackrabbit.apache.org/jackrabbit-web-application.html" href="http://jackrabbit.apache.org/jackrabbit-web-application.html"&gt;http://jackrabbit.apache.org/jackrabbit-web-application.html&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;RMI access      &lt;br /&gt;&lt;a title="http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-RMIaccess" href="http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-RMIaccess"&gt;http://jackrabbit.apache.org/standalone-server.html#StandaloneServer-RMIaccess&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;local access      &lt;br /&gt;Through JNDI or servlet context. &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Installation problem&lt;/h2&gt;  &lt;p&gt;When I tried to install Jackrabbit on gridfarm machine which uses NFS V3, I got problem described in this bug report (&lt;a title="http://issues.apache.org/jira/browse/JCR-1605" href="http://issues.apache.org/jira/browse/JCR-1605"&gt;http://issues.apache.org/jira/browse/JCR-1605&lt;/a&gt;). Basically it says Jackrabbit needs some features that are not implemented in NFS prior to V4. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6126048705122816301?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6126048705122816301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6126048705122816301' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6126048705122816301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6126048705122816301'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/09/java-conent-repository-jackrabbit.html' title='Java Conent Repository - Jackrabbit'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5413218505383245461</id><published>2009-08-28T14:27:00.001-04:00</published><updated>2009-08-28T15:27:24.603-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>Dynamic-height in Shindig</title><content type='html'>&lt;p&gt;Gadget specification provides a feature called dynamic-height to dynamically adjust height of a gadget. &lt;br&gt;If gadget server and gadget container are in the same domain, this can be done using javascript.&lt;br&gt;However, if gadget server and gadget container are in different domains, this can not be achieved by directly using Javascript and DOM because of same-origin policy imposed by modern browsers. &lt;br&gt;This email &lt;a title="http://markmail.org/message/53r5dwhr56lby733#query:dynamic%20height%20shindig+page:1+mid:53r5dwhr56lby733+state:results" href="http://markmail.org/message/53r5dwhr56lby733#query:dynamic%20height%20shindig+page:1+mid:53r5dwhr56lby733+state:results"&gt;http://markmail.org/message/53r5dwhr56lby733#query:dynamic%20height%20shindig+page:1+mid:53r5dwhr56lby733+state:results&lt;/a&gt; includes some information about how to make it work.&lt;br&gt;I am going to give more details here. &lt;/p&gt; &lt;h2&gt;Gadget container&lt;/h2&gt; &lt;ol&gt; &lt;li&gt;Download &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/cookies.js" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/cookies.js"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/cookies.js&lt;/a&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/gadgets.js" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/gadgets.js"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/gadgets.js&lt;/a&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/util.js" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/util.js"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/util.js&lt;/a&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/features/src/main/javascript/features/rpc/rpc.js" href="http://your_shindig_deploy/gadgets/js/rpc.js?c=1&amp;amp;debug=1"&gt;http://your_shindig_deploy/gadgets/js/rpc.js?c=1&amp;amp;debug=1&lt;/a&gt; (//this file actually includes rpc framework and all possible communication mechanism, e.g. ifpc, wpm...)&lt;br&gt;And put them into your gadget container server.  &lt;li&gt;Include following code in your container web page to make them point to those javascript files you downloaded in step 1).&lt;pre style="margin: 0px"&gt;&amp;lt;script type="text/javascript" src="rpc.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="cookies.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="util.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="gadgets.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;li&gt;&lt;a name="download_rpcrelay"&gt;Download&lt;br&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rpc_relay.html : &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.html" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.html"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.html&lt;/a&gt;&lt;br&gt;or &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rpc_relay_uncompressed.html: &lt;a title="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.uncompressed.html" href="http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.uncompressed.html"&gt;http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.uncompressed.html&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;Gadget server/renderer&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Check out Shindig source code. See &lt;a title="http://incubator.apache.org/shindig/source-repository.html" href="http://incubator.apache.org/shindig/source-repository.html"&gt;http://incubator.apache.org/shindig/source-repository.html&lt;/a&gt; 
&lt;li&gt;Change source code of file &lt;em&gt;ifpc.transport.js &lt;br&gt;&lt;/em&gt;&lt;pre style="margin: 0px"&gt;&lt;font face="Trebuchet MS" color="#000000"&gt;Original:&lt;br&gt;&lt;/font&gt;// The RPC mechanism supports two formats for IFPC (legacy and current).
var src = null;
if (rpc.l) {&lt;/pre&gt;New&lt;pre style="margin: 0px"&gt;// The RPC mechanism supports two formats for IFPC (legacy and current).
var src = null;
if (false) {&lt;/pre&gt;This disables use of legacy data format which is buggy. 
&lt;li&gt;Change configuration in file &lt;em&gt;config/container.js&lt;/em&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Original: &lt;em&gt;&lt;font color="#0000ff"&gt;"parentRelayUrl" : "/gadgets/files/container/rpc_relay.html"&lt;/font&gt;&lt;/em&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;&lt;font color="#0000ff"&gt;"parentRelayUrl" : "rpc_relay file address on your gadget container" //it is download in &lt;a href="#download_rpcrelay"&gt;this step&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;br&gt;Also you may want to use ifpc instead of browser-specific communication mechanisms.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Original: "useLegacyProtocol" : false&amp;nbsp;&amp;nbsp;&amp;nbsp; //gadget tries browser-specific communication mechanisms first. If they fail, fall back to ifpc.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "useLegacyProtocol" : true&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //use ifpc directly. &lt;br&gt;Note: the current wire format will be used instead of legacy format because we have disabled legacy format. &lt;br&gt;This option is not used in the way described by comment in the source code. The shindig developers want users to use this option to control whether legacy format is used. I use it to configure whether ifpc is used. If ifpc is used, only current wire format is utilized. &lt;br&gt;This can also be set after you deploy shindig. The configuration file is located at &lt;em&gt;WEB-INF/classes/containers/default/&lt;/em&gt;. 
&lt;li&gt;Rebuild shindig. 
&lt;li&gt;Copy generated &lt;em&gt;.war&lt;/em&gt; file in directory &lt;em&gt;server/target&lt;/em&gt; to your servlet container.&lt;/li&gt;&lt;/ol&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;Detailed discussion: &lt;a title="http://docs.google.com/View?id=dmxthpg_125ckh55fff" href="http://docs.google.com/View?id=dmxthpg_125ckh55fff"&gt;http://docs.google.com/View?id=dmxthpg_125ckh55fff&lt;/a&gt;&lt;br&gt;Cross-Domain Communication with IFrames: &lt;a title="http://softwareas.com/cross-domain-communication-with-iframes" href="http://softwareas.com/cross-domain-communication-with-iframes"&gt;http://softwareas.com/cross-domain-communication-with-iframes&lt;/a&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5413218505383245461?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5413218505383245461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5413218505383245461' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5413218505383245461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5413218505383245461'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/08/dynamic-height-in-shindig.html' title='Dynamic-height in Shindig'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5542262654730282117</id><published>2009-08-21T00:39:00.001-04:00</published><updated>2009-08-21T00:44:00.256-04:00</updated><title type='text'>Google GData API usage</title><content type='html'>Recently, I am using Google GData APIs to access Google Picasa and Google Calendar Services.&lt;br&gt;There is a Java library which is hosted at &lt;a title="http://code.google.com/p/gdata-java-client/" target="_blank" href="http://code.google.com/p/gdata-java-client/" id="u:lb"&gt;http://code.google.com/p/gdata-java-client/&lt;/a&gt;. Currently, the code is maintained using ant. We use maven2 to build our project, so we manually uploaded those jars to our maven repository and added necessary pom files. Dependencies of gdata java library are described at &lt;a title="http://code.google.com/p/gdata-java-client/wiki/Dependencies" href="http://code.google.com/p/gdata-java-client/wiki/Dependencies" id="um0r"&gt;http://code.google.com/p/gdata-java-client/wiki/Dependencies&lt;/a&gt;. &lt;br&gt;Google Picasa doc: &lt;a title="http://code.google.com/apis/picasaweb/docs/2.0/developers_guide.html" href="http://code.google.com/apis/picasaweb/docs/2.0/developers_guide.html" id="bftb"&gt;http://code.google.com/apis/picasaweb/docs/2.0/developers_guide.html&lt;br&gt;&lt;/a&gt;Google Calendar doc: &lt;a title="http://code.google.com/apis/calendar/docs/2.0/developers_guide.html" href="http://code.google.com/apis/calendar/docs/2.0/developers_guide.html" id="glz_"&gt;http://code.google.com/apis/calendar/docs/2.0/developers_guide.html&lt;/a&gt;&lt;br&gt;&lt;p&gt;During using of Google Calendar APIs, one thing I want to do is publish a new event to a specific non-primary calendar. According to &lt;a title="http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle" href="http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle" id="ju92"&gt;http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle&lt;/a&gt;, POST requests should be sent to &lt;i&gt;http://www.google.com/calendar/feeds/default/private/full&lt;/i&gt;. However that results in putting new event to &lt;b&gt;primary&lt;/b&gt; calendar. The document does not tell us how to put a new event to non-primary calendar.&lt;br&gt;
&lt;/p&gt;
&lt;h3&gt;Solution (How to publish a new event to a non-primary calendar)&lt;br&gt;
&lt;/h3&gt;Steps:&lt;br&gt;&lt;ol&gt;&lt;li&gt;Get a list of all calendars owned by the user&lt;br&gt;Send GET request to http://www.google.com/calendar/feeds/default/owncalendars/full&lt;/li&gt;&lt;li&gt;&lt;a id="xg78" name="step2"&gt;&lt;/a&gt;In the response feed, each calendar has an entry.&lt;br&gt;Each entry should has a link element like this:&lt;br&gt;&lt;span style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;link rel="&lt;/span&gt;&lt;b style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;alternate&lt;/b&gt;&lt;span style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;"&lt;/span&gt;&lt;br style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;&lt;span style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type="application/atom+xml"&lt;/span&gt;&lt;br style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;&lt;span style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; href="http://www.google.com/calendar/feeds/pnk4d66rpmiho1pl0m4t6dnki0%40group.calendar.google.com/private/full"/&amp;gt;&lt;/span&gt;&lt;br style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 255);"&gt;Value of attribute &lt;i&gt;href&lt;/i&gt; is the URL to which the POST request should be sent to create a new event in the corresponding calendar.&lt;br&gt;&lt;/li&gt;&lt;li&gt;Send POST request to the URL specified by attribute "&lt;i&gt;href&lt;/i&gt;" found in &lt;a title="step 2)" href="#step2" id="r1_6"&gt;step 2)&lt;/a&gt;&lt;br&gt;Example of POST data is shown &lt;a title="http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle" href="http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle" id="w02o"&gt;http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5542262654730282117?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5542262654730282117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5542262654730282117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5542262654730282117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5542262654730282117'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/08/google-gdata-api-usage.html' title='Google GData API usage'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1881187203692772290</id><published>2009-08-10T13:04:00.001-04:00</published><updated>2009-08-10T13:08:11.715-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>MySQL Connection Timeout Error in Hibernate</title><content type='html'>&lt;h2&gt;Problem &lt;/h2&gt;I am using Hibernate and MySQL in myour project. After our application is started, it just works well. However, if the application is not used for some time (like one day), it throws connection exception when it is used again. Trace of the exception: &lt;pre&gt;com.mysql.jdbc.CommunicationsException: 
The last packet successfully received from the server was seconds ago.
The last packet sent successfully to the server was 407270 seconds ago, which  is longer than the server configured value of 'wait_timeout'. 
You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.&lt;/pre&gt;&lt;p&gt;I googled this problem, and it seems that many other persons also suffer this problem. I found some really nice blog posts about how to solve this problem.&lt;/p&gt;&lt;p&gt;According to the error message, I set the option &lt;em&gt;autoReconnect&lt;/em&gt; (&lt;a title="http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html" href="http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html"&gt;http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html&lt;/a&gt;) to true. But it still does not work. I searched in google and it shows this option works in some platforms while it doesn't work in other platforms.&lt;/p&gt;&lt;h2&gt;Solution&lt;/h2&gt;&lt;p&gt;Basically, the solution is 1) use a connection manager 2) tweak parameters of the connection manager. &lt;/p&gt;&lt;p&gt;C3P0 is a free JDBC connection manager. &lt;br&gt;Some C3p0 configuration parameters are mapped to Hibernate config. Those mapped configuration parameters are listed at &lt;a title="http://www.mchange.com/projects/c3p0/index.html#hibernate-specific" href="http://www.mchange.com/projects/c3p0/index.html#hibernate-specific"&gt;http://www.mchange.com/projects/c3p0/index.html#hibernate-specific&lt;/a&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;"Please note that configuration parameters that &lt;strong&gt;ARE&lt;/strong&gt; mapped into hibernate's config file &lt;strong&gt;MUST&lt;/strong&gt; be set within hibernate's configuration, or else they will be overridden by hibernate-specified defaults.&lt;br&gt;[The hibernate-mapped c3p0 parameters are minPoolSize, maxPoolSize, maxIdleTime, maxStatements, acquireIncrement, testConnectionOnCheckout, and idleConnectionTestPeriod. These map to the fllowing hibernate parameters: hibernate.c3p0.min_size, hibernate.c3p0.max_size, hibernate.c3p0.timeout, hibernate.c3p0.max_statements, hibernate.c3p0.acquire_increment, hibernate.c3p0.validate, and hibernate.c3p0.idle_test_period. DataSources configured in Tomcat should always use c3p0-native parameter names. But pools constructed under the covers by Hibernate must be configured in hibernate's config file with hibernate-defined parameter names where applicable.] "&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;For those C3p0 parameters that are NOT mapped, they should be specified in file &lt;em&gt;&lt;strong&gt;WEB-INF/classes/c3p0.properties&lt;/strong&gt;&lt;/em&gt;.&lt;br&gt;&lt;strong style="font-size: 125%"&gt;Note&lt;/strong&gt;: C3P0 configuration parameter &amp;lt;&lt;em&gt;c3p0.testConnectionsOnCheckout&lt;/em&gt;&amp;gt; is mapped to &amp;lt;&lt;em&gt;hibernate.c3p0.validate&lt;/em&gt;&amp;gt; only in &lt;strong&gt;hibernate 2.x&lt;/strong&gt;!&lt;br&gt;Also the configuration parameter &lt;em&gt;c3p0.testConnectionsOnCheckout&lt;/em&gt; is really expensive. Users can use c3p0.maxIdleTime (it is mapped to &lt;em&gt;hibernate.c3p0.timeout&lt;/em&gt; in hibernate) instead. &lt;/p&gt;&lt;p&gt;&lt;/p&gt;My &lt;tt&gt;hibernate.cfg.xml&lt;/tt&gt; includes following configuration: &lt;pre style="color: blue"&gt;        &amp;lt;property name="connection.provider_class"&amp;gt;org.hibernate.connection.C3P0ConnectionProvider&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.min_size"&amp;gt;5&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.max_size"&amp;gt;30&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.timeout"&amp;gt;600&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.max_statements"&amp;gt;0&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.acquire_increment"&amp;gt;5&amp;lt;/property&amp;gt;
        &amp;lt;property name="c3p0.idle_test_period"&amp;gt;60&amp;lt;/property&amp;gt;
&lt;/pre&gt;&lt;p&gt;The idle test operation can be optimized by specifying option &lt;em&gt;preferrredTestQuery&lt;/em&gt;. &lt;br&gt;I am using MySQL as underlying RDB and putting &lt;strong&gt;&lt;em&gt;c3p0.preferredTestQuery = SELECT 1&lt;/em&gt;&lt;/strong&gt; into c3p0.properties works fine (this is stolen from post comment &lt;a title="http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/#comment-3156" href="http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/#comment-3156"&gt;http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/#comment-3156&lt;/a&gt;). &lt;/p&gt;&lt;h2&gt;Resources&lt;/h2&gt;&lt;p&gt;A really good article about how to reconnect from Hibernate to MySQL: &lt;a title="http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/" href="http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/"&gt;http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/&lt;/a&gt;&lt;br&gt;C3P0 (Connection manager): &lt;a title="http://www.mchange.com/projects/c3p0/index.html" href="http://www.mchange.com/projects/c3p0/index.html"&gt;http://www.mchange.com/projects/c3p0/index.html&lt;/a&gt;&lt;br&gt;How to configure C3P0 in Hibernate: &lt;a title="https://www.hibernate.org/214.html" href="https://www.hibernate.org/214.html"&gt;https://www.hibernate.org/214.html&lt;/a&gt;&lt;br&gt;A forum thread about C3P0 configuration in Hibernate: &lt;a title="https://forum.hibernate.org/viewtopic.php?t=934779&amp;amp;highlight=c3p0" href="https://forum.hibernate.org/viewtopic.php?t=934779&amp;amp;highlight=c3p0"&gt;https://forum.hibernate.org/viewtopic.php?t=934779&amp;amp;highlight=c3p0&lt;/a&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1881187203692772290?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1881187203692772290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1881187203692772290' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1881187203692772290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1881187203692772290'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/08/mysql-connection-timeout-error-in.html' title='MySQL Connection Timeout Error in Hibernate'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6370787970617393131</id><published>2009-06-15T16:01:00.001-04:00</published><updated>2009-06-15T16:02:10.777-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openssl'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Key generation using OpenSSL</title><content type='html'>&lt;h2&gt;Generate RSA public/private key pair&lt;/h2&gt;Generate private key:&lt;pre&gt;openssl genrsa -out private_key.pem 1024&lt;/pre&gt;Convert private key to PKCS8 format:&lt;pre&gt;openssl pkcs8 -topk8 -in privkey.pem -nocrypt&lt;/pre&gt;Generate public key:&lt;pre&gt;openssl rsa -pubout -in private_key.pem -out public_key.pem&lt;/pre&gt;Read Base64 Encoded private key&lt;br&gt;&lt;pre&gt;openssl rsa -text -in private_key.pem&lt;/pre&gt;
&lt;h2&gt;Generate Self-Signed certificate&lt;/h2&gt;&lt;pre&gt;openssl req \
  -x509 -nodes -days 365 \
  -newkey rsa:1024 -keyout private_key.pem -out cert.pem
&lt;/pre&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6370787970617393131?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6370787970617393131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6370787970617393131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6370787970617393131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6370787970617393131'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/06/key-generation-using-openssl.html' title='Key generation using OpenSSL'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-446806479656264671</id><published>2009-06-04T17:12:00.000-04:00</published><updated>2009-06-04T17:13:34.775-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>2-legged OAuth System Tutorial</title><content type='html'>&lt;h2&gt;Use Cases:&lt;/h2&gt; &lt;p&gt;&lt;strong&gt;(1) A user wants to grant data access priviledges to a third-party application. &lt;/strong&gt;&lt;br&gt;&amp;nbsp; Here three parties are involved:&lt;br&gt;&amp;nbsp; User&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the end user&lt;br&gt;&amp;nbsp; Third-Party application&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; It wants to manipulate user's data on behalf of the user.&lt;br&gt;&amp;nbsp; Service Provider&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a remote application that provides the real service.  &lt;p&gt;&amp;nbsp; The procedure of granting priviledges:&lt;br&gt;&amp;nbsp; (I) complete steps described in section &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="#provider_side_regular_users"&gt;(Provider side) &amp;gt; (For regular users)&lt;/a&gt;&lt;br&gt;&amp;nbsp; (II) complete steps described in section&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="#consumer_side_regular_users"&gt;(Consumer side) &amp;gt; (For regular users)&lt;br&gt;&lt;/a&gt;&amp;nbsp; Note: the public key uploaded in step (I) and private key uploaded in&lt;br&gt;&amp;nbsp; step (II) must match.  &lt;p&gt;&lt;strong&gt;(2) A user wants to develop a third-party application for our service.&lt;/strong&gt;&lt;br&gt;&amp;nbsp; (I) Register the application by completing steps described in section&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="#provider_side_thirdapp_developers"&gt;(Provider side) &amp;gt; (For thrid-party application developers)&lt;/a&gt;&lt;br&gt;&amp;nbsp; Now, the application can use the service.  &lt;p&gt;&amp;nbsp; (II) To make use of built-in third-party application, complete steps&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; described in section&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="#consumer_side_app_manager"&gt;(Consumer side) &amp;gt; (For application manager) &lt;/a&gt; &lt;p&gt;&lt;strong&gt;(3) A user wants to use a deployed and configured third-party application.&lt;/strong&gt;&lt;br&gt;&amp;nbsp; (I) Go to http://yourhost:yourport/oauthConsumer-0.1&lt;br&gt;&amp;nbsp; (II) Login with existing account and you will be directed to page 'account.jsp'&lt;br&gt;&amp;nbsp; (III) All supported third-party applications are listed under section&lt;br&gt;&amp;nbsp; (Available service providers). Click a link to use the corresponding&lt;br&gt;&amp;nbsp; application.  &lt;p&gt;&amp;nbsp; &lt;h2&gt;Consumer side &lt;/h2&gt; &lt;h3&gt;&lt;a name="consumer_side_regular_users"&gt;For regular users&lt;/a&gt;&lt;/h3&gt;&lt;strong&gt;Steps&lt;/strong&gt;&lt;br&gt;&amp;nbsp; (1) Go to http://yourhost:yourport/oauthConsumer-0.1&lt;br&gt;&amp;nbsp; (2) Register a new account or log in with existing account&lt;br&gt;&amp;nbsp; (3) Go to account.jsp (you should be automatically directed to this page)&lt;br&gt;&amp;nbsp; (4) If it is the first time for the user to request an OAuth protected&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; service via client application, the user should do some configurations.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Click the link "Private Key Binding And Service Provider Setting"&lt;br&gt;&amp;nbsp; (5) On this page, user can do some configurations&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5.1) UserId binding&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This setting binds local user Id to user Id used by remote service.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For example, if a user wants to access remote Yahoo flickr service&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; through a third-party app, the local user Id is the user id used by the&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; third-party app and it is bound to the user Id used by Yahoo Flickr.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5.2) Private key setting&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Possession of private key makes the third-party app be able to access&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; remote service on behalf of the user.  &lt;p&gt; &lt;h3&gt;&lt;a name="consumer_side_app_manager"&gt;For application manager&lt;/a&gt;&lt;/h3&gt;Actually, only administrators should have the priviledge to manage third-party&lt;br&gt;application registry. But currently user management system is simple and all&lt;br&gt;users have the same priviledges. &lt;br&gt;Steps&lt;br&gt;&amp;nbsp; (1) Go to &lt;a href="http://yourhost:yourport/oauthConsumer-0.1"&gt;http://yourhost:yourport/oauthConsumer-0.1&lt;/a&gt;&lt;br&gt;&amp;nbsp; (2) Register a new account or log in with existing account&lt;br&gt;&amp;nbsp; (3) Go to account.jsp (you should be automatically directed to this page)&lt;br&gt;&amp;nbsp; (4) Click the link "Attributes of available service providers"&lt;br&gt;&amp;nbsp; (5) Now, the user can register a new third-party app, remove an existing&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; registration and modify existing registration information.  &lt;p&gt; &lt;h2&gt;Provider side&lt;/h2&gt;Currently, only one service is offered - echo service.  &lt;h3&gt;&lt;a name="provider_side_regular_users"&gt;For regular users&lt;/a&gt;&lt;/h3&gt;&lt;strong&gt;Steps&lt;/strong&gt;&lt;br&gt;&amp;nbsp; (1) Go to &lt;a href="http://yourhost:yourport/oauthServer-0.1"&gt;http://yourhost:yourport/oauthServer-0.1&lt;/a&gt;&lt;br&gt;&amp;nbsp; (2) Register a new account or log in with existing account&lt;br&gt;&amp;nbsp; (3) Go to account.jsp (you should be automatically directed to this page)&lt;br&gt;&amp;nbsp; (4) Click the link "Certificate Setting"&lt;br&gt;&amp;nbsp; (5) On this page, user can do some configurations&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5.1) Third-party app priviledge setting&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Users can specify which third-party applications are allowed to access&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; their data.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5.2) Certificate upload&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Upload your X.509 certificate (of PEM format).  &lt;h3&gt;&lt;a name="provider_side_thirdapp_developers"&gt;For thrid-party application developers&lt;/a&gt;&lt;/h3&gt;&lt;strong&gt;Steps&lt;/strong&gt;&lt;br&gt;&amp;nbsp; (1) Go to &lt;a href="http://yourhost:yourport/oauthServer-0.1"&gt;http://yourhost:yourport/oauthServer-0.1&lt;/a&gt;&lt;br&gt;&amp;nbsp; (2) Register a new account or log in with existing account&lt;br&gt;&amp;nbsp; (3) Go to account.jsp (you should be automatically directed to this page)&lt;br&gt;&amp;nbsp; (4) Click the link "Developer Account"&lt;br&gt;&amp;nbsp; (5) Type information of the third-party application that is to be registered.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A consumer key/secret pair is generated as well.  &lt;p&gt; &lt;h2&gt;Use of Public/Private key pair&lt;/h2&gt;There are two types of private/public key pair:&lt;br&gt;&lt;a name="key_use1"&gt;(1)&lt;/a&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; One is used to guarantee integrity of messages transmissioned between&lt;br&gt;&amp;nbsp; third-party application and service provider.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; So for service provider, the public key is published. If a third-party&lt;br&gt;&amp;nbsp; application wants to access the service, it should use the published public&lt;br&gt;&amp;nbsp; key to sign outbound messages.&lt;br&gt;&lt;a name="key_use2"&gt;(2)&lt;/a&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The other is owned and deployed by end user. The goal is to provide a way so&lt;br&gt;&amp;nbsp; that third-party application can use backend service on behalf of user&lt;br&gt;&amp;nbsp; without user involvement. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; So this pair is owned by end user. To deploy the key pair:&lt;br&gt;&amp;nbsp; (*) upload the public key to service provider&lt;br&gt;&amp;nbsp; (*) upload the private key to third-party application&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Then the third-party application uses the private key to sign part of the&lt;br&gt;&amp;nbsp; message (The whole message is signed using pub/priv key pair described in&lt;br&gt;&amp;nbsp; &lt;a href="#key_use1"&gt;bullet 1&lt;/a&gt;).  &lt;p&gt;&lt;strong&gt;OAuth message&lt;/strong&gt;&lt;pre&gt;    ___________________________________________________________
   |                                                           |
   |     _________________________________________________     |
   |    |   ___________________________________________   |    |
   |    |  |  ______________       _________________   |  |    |
   |   P|  | |              |     |                 |  |  |    |
   |   a|  | | Payload 2    |     |  Signature (2)  |  |  |    |
   |   y|  | |______________|     |_________________|  |  |    |
   |   l|  |___________________________________________|  |    |
   |   o|                                                 |    |
   |   a|   ___________________________________________   |    |
   |   d|  |                                           |  |    |
   |    |  |                Other parts                |  |    |
   |   1|  |___________________________________________|  |    |
   |    |_________________________________________________|    |
   |     _________________________________________________     |
   |    |                                                 |    |   
   |    |       Signature (1)                             |    |
   |    |_________________________________________________|    |
   |                                                           |
   |___________________________________________________________|

&lt;/pre&gt;
&lt;p&gt;In above figure, &amp;lt;Signature (1)&amp;gt; is calculated using key described in &lt;a href="#key_use1"&gt;bullet 1&lt;/a&gt;. &amp;lt;Signature (2)&amp;gt; is calculated using key described in &lt;a href="#key_use2"&gt;bullet 2&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-446806479656264671?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/446806479656264671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=446806479656264671' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/446806479656264671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/446806479656264671'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/06/2-legged-oauth-system-tutorial.html' title='2-legged OAuth System Tutorial'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6893044507610689514</id><published>2009-06-02T23:21:00.001-04:00</published><updated>2009-06-02T23:21:32.465-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>H2 Exception "Database may be already in use: Locked by another process"</title><content type='html'>&lt;p&gt;I wrote two Java web servlet apps (oauth consumer app, and oauth server app) both of which rely on H2 as database engine. I want H2 to be run in embedded mode instead of server mode. According to the official document, following statement should be added to &lt;em&gt;web.xml&lt;/em&gt; &lt;pre&gt;&amp;lt;listener&amp;gt;
    &amp;lt;listener-class&amp;gt;org.h2.server.web.DbStarter&amp;lt;/listener-class&amp;gt;
&amp;lt;/listener&amp;gt;&lt;/pre&gt;
&lt;p&gt;This class has methods that listen to the servlet context event (context initialization, context destroyed). &lt;/p&gt;
&lt;p&gt;When I deploy just one of the two web apps to tomcat, it works fine. When I deploy both of them, following exception is thrown&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Exception in thread "main" org.h2.jdbc.JdbcSQLException: Database may be already in use: Locked by another process. Possible solutions: close all other connecti on(s); use the server mode [90020-63]&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I am 100% sure that those two apps use different databases. To make myself 200% sure that my code does not create or use additional databases unintentionaly, I rechecked my code many many times. But my code looks just fine. So I doubted it may be because of the H2 database engine. &lt;br&gt;Then I used command '&lt;em&gt;lsof&lt;/em&gt;' to list opened files by tomcat java process. Surprisingly, a database named '&lt;em&gt;test&lt;/em&gt;' is created under my home directory. &lt;br&gt;I reread the document &lt;a title="http://www.h2database.com/html/tutorial.html#web_applications" href="http://www.h2database.com/html/tutorial.html#web_applications"&gt;http://www.h2database.com/html/tutorial.html#web_applications&lt;/a&gt;, and I got what I missed before. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For details on how to access the database, see the file DbStarter.java. By default the DbStarter listener opens an embedded connection using the database URL &lt;strong&gt;'jdbc:h2:~/test'&lt;/strong&gt;, user name 'sa', and password 'sa'.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Code of class &lt;em&gt;DbStarter&lt;/em&gt; can be accessed at &lt;a href="http://code.google.com/p/h2database/source/browse/trunk/h2/src/main/org/h2/server/web/DbStarter.java"&gt;http://code.google.com/p/h2database/source/browse/trunk/h2/src/main/org/h2/server/web/DbStarter.java&lt;/a&gt;.&lt;br&gt;I am just curious about why a default database is created by class &lt;em&gt;DbStarter&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solutions&lt;/strong&gt;&lt;br&gt;(1) remove the listener declaration in &lt;em&gt;web.xml&lt;/em&gt;&lt;br&gt;In other words, remove&lt;br&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listener&amp;gt; &amp;lt;listener-class&amp;gt;org.h2.server.web.DbStarter&amp;lt;/listener-class&amp;gt; &amp;lt;/listener&amp;gt;&lt;/code&gt;&lt;br&gt;(2) change url of created database.&lt;pre&gt;  &amp;lt;context-param&amp;gt;
    &amp;lt;param-name&amp;gt;db.url&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;jdbc:h2:&lt;strong&gt;your_new_db_url&lt;/strong&gt;&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6893044507610689514?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6893044507610689514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6893044507610689514' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6893044507610689514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6893044507610689514'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/06/h2-exception-may-be-already-in-use.html' title='H2 Exception &amp;quot;Database may be already in use: Locked by another process&amp;quot;'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4115335456334090619</id><published>2009-05-17T17:48:00.001-04:00</published><updated>2009-05-17T17:48:36.094-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Change ROOT app in Tomcat</title><content type='html'>&lt;p&gt;Recently, I tried new version of shindig - shindig-1.1-SNAPSHOT-java (&lt;a title="http://incubator.apache.org/shindig/download/index.html" href="http://incubator.apache.org/shindig/download/index.html"&gt;http://incubator.apache.org/shindig/download/index.html&lt;/a&gt;). It is a reference implementation for OpenSocial 0.9 spec. &lt;/p&gt; &lt;p&gt;The old problem (described at &lt;a title="http://cglreport.zhenhua.info/2009/02/shindig-server-on-tomcat.html" href="http://cglreport.zhenhua.info/2009/02/shindig-server-on-tomcat.html"&gt;http://cglreport.zhenhua.info/2009/02/shindig-server-on-tomcat.html&lt;/a&gt;) has not been solved.&lt;br&gt;At first I wanted to try it by deploying the &lt;em&gt;war&lt;/em&gt; as root application in tomcat. &lt;/p&gt; &lt;p&gt;One easy solution is to rename the &lt;em&gt;war&lt;/em&gt; file to &lt;em&gt;ROOT.war&lt;/em&gt;. &lt;br&gt;I used another solution. &lt;br&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;br&gt;Deployment:&lt;br&gt;&amp;nbsp; (1) create directory &lt;em&gt;&amp;lt;tomcat_root&amp;gt;/myapps&lt;/em&gt;&lt;br&gt;&amp;nbsp; (2) put the &lt;em&gt;war &lt;/em&gt;file (shindig-server-1.1-SNAPSHOT.war) to the directory created in step 1.&lt;br&gt;&amp;nbsp; (3) rename the original directory &lt;em&gt;ROOT&lt;/em&gt;. (This step may be overlooked sometimes)&lt;br&gt;Configuration:&lt;br&gt;&amp;nbsp; (1) Add file &lt;em&gt;&amp;lt;tomcat_root&amp;gt;/conf/Catalina/localhost/ROOT.xml&lt;/em&gt;&lt;br&gt;&amp;nbsp; (2) Content of the file is&lt;pre style="margin-left: 10px"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;Context
    path=""
    docBase="/globalhome/zhguo/servers/apache-tomcat-6.0.18/myapps/shindig-server-1.1-SNAPSHOT.war"
    debug="0"
    reloadable="true"&amp;gt;
&amp;lt;/Context&amp;gt;&lt;/pre&gt;&amp;nbsp; (3) restart tomcat  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4115335456334090619?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4115335456334090619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4115335456334090619' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4115335456334090619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4115335456334090619'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/05/change-root-app-in-tomcat.html' title='Change ROOT app in Tomcat'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1648946436729434139</id><published>2009-05-06T01:59:00.000-04:00</published><updated>2009-05-06T02:05:00.597-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>Implementation of 2-Legged OAuth</title><content type='html'>&lt;h2&gt;2-Legged OAuth &lt;/h2&gt; &lt;p&gt;I did not change the process flow of original 3-legged OAuth to support 2-legged OAuth. I made a small change to user authorization step described at &lt;a href="http://oauth.net/core/1.0/#auth_step2"&gt;http://oauth.net/core/1.0/#auth_step2&lt;/a&gt;. Two additional parameters are added to support 2-legged OAuth: &lt;em&gt;user_id&lt;/em&gt; and &lt;em&gt;cgl_oauth_signagure&lt;/em&gt;. See &lt;a href="http://zhenhua-guo.blogspot.com/2009/04/oauth-myproxy-integration-prototype.html"&gt;http://zhenhua-guo.blogspot.com/2009/04/oauth-myproxy-integration-prototype.html&lt;/a&gt; for more information.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Integrity check: &lt;/strong&gt;&lt;/p&gt; &lt;ol&gt; &lt;li&gt;check trust relationship between service provider and client app.&lt;br&gt;Currently, just check whether the clien app has been registered at service provider with correct information.  &lt;li&gt;check pre-assigned priviledges to client app by user (this only applies to 2-legged OAuth) &lt;br&gt;A client app must have been granted access priviledge before it can access user data stored at service provider&lt;br&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Implementation&lt;/h2&gt; &lt;p&gt; &lt;h2&gt;Client&lt;/h2&gt; &lt;h3&gt;Client App&lt;/h3&gt; &lt;p&gt;Most important information about a client application includes:  &lt;ul&gt; &lt;li&gt;name  &lt;li&gt;description  &lt;li&gt;consumer key&lt;br&gt;See http://oauth.net/core/1.0/#anchor6  &lt;li&gt;consumer secret&lt;br&gt;See http://oauth.net/core/1.0/#anchor6  &lt;li&gt;callback URL&lt;br&gt;The address to which user is redirected after data owner accepts access request.  &lt;li&gt;signature method&lt;br&gt;HMAC-SHA1 or RSA-SHA1. Currently, only use RSA-SHA1.  &lt;li&gt;private key&lt;br&gt;Used to generate signature  &lt;li&gt;request token URL&lt;br&gt;See http://oauth.net/core/1.0/#auth_step1  &lt;li&gt;authorization URL&lt;br&gt;See http://oauth.net/core/1.0/#auth_step2  &lt;li&gt;access token url &lt;br&gt;See http://oauth.net/core/1.0/#auth_step3 &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;A list of client applications is listed and users can add or remove client applications.&lt;br&gt;Snapshot:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/_qiIXUonGAyk/SgEnbWOuIeI/AAAAAAAAAfg/prkH7eD8ddA/s1600-h/oauthConsumer-0_1_consumers%5B10%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="1556" alt="oauthConsumer-0_1_consumers" src="http://lh5.ggpht.com/_qiIXUonGAyk/SgEneHpL0RI/AAAAAAAAAfo/jo_p0bE67oA/oauthConsumer-0_1_consumers_thumb%5B8%5D.jpg?imgmax=800" width="420" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Users can set userid that is used during invocation of remote service. Also to make it possible for client app to access user data at service provider, the user should upload private key to client app so that correct signature can be generated during OAuth process. &lt;br&gt;&lt;a href="http://lh3.ggpht.com/_qiIXUonGAyk/SgEnfCtlAyI/AAAAAAAAAfI/rPbFw7XJQM0/s1600-h/oauthConsumer-0_1_myproxy%5B3%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="931" alt="oauthConsumer-0_1_myproxy" src="http://lh4.ggpht.com/_qiIXUonGAyk/SgEnf6G71aI/AAAAAAAAAfM/pSFyvEsRplw/oauthConsumer-0_1_myproxy_thumb%5B1%5D.jpg?imgmax=800" width="832" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h3&gt;Tables&lt;/h3&gt;Four tables in database:  &lt;dl&gt; &lt;dt&gt;oauth_consumer_users  &lt;dd&gt;This table stores basic user account information. Currently, &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; are the only two attributes.  &lt;dt&gt;oauth_consumer_settting  &lt;dd&gt;This table stores private key belonging to each user. The private key is used during OAuth authorization process.  &lt;dt&gt;oauth_consumer_spbinding  &lt;dd&gt;This table stores binding relationships between users and service providers. So the information in this table is used when client app invokes remote service on behalf of user. Currently the main information is the user id that is used by service provider. In other words, a mapping from local user id to remote user id is established.  &lt;dt&gt;oauth_consumers  &lt;dd&gt;This table stores information of client applications. &lt;/dd&gt;&lt;/dl&gt; &lt;p&gt;&lt;/p&gt; &lt;h2&gt;Service Provider &lt;/h2&gt; &lt;p&gt;Service provider provides interfaces that can be used by third party applications to access users' data. &lt;/p&gt; &lt;h3&gt;For application developer &lt;/h3&gt; &lt;h4&gt;Client application registration&lt;/h4&gt; &lt;p&gt;To register a client app, developers need to follow these instructions:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;apply for a consumer key/secret pair.  &lt;li&gt;type informatoin about the clien app including  &lt;ul&gt; &lt;li&gt;app name  &lt;li&gt;app description  &lt;li&gt;app callback URL  &lt;li&gt;public key &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;In my implementation, the registration page can be accessed at &lt;code&gt;&amp;lt;baseurl&amp;gt;/oauthServer-0.1/developerAcc.jsp&lt;/code&gt; after our system is installed. &lt;br&gt;Screenshot:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/_qiIXUonGAyk/SgEniIb_ZSI/AAAAAAAAAfQ/g0BCI8-8MOw/s1600-h/oauthServer-0_1_developerAcc%5B3%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="727" alt="oauthServer-0_1_developerAcc" src="http://lh3.ggpht.com/_qiIXUonGAyk/SgEnkbr4SvI/AAAAAAAAAfU/LxJf5whEyU4/oauthServer-0_1_developerAcc_thumb%5B1%5D.jpg?imgmax=800" width="847" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h4&gt;For common users&lt;/h4&gt; &lt;p&gt;Some third-party applications may want to access users' data stored at service provider. In 3-legged OAuth, the service provider redirects the user to a web page where the access request can be accepted or denied. In 2-legged, no user intervenetion is involved, so the authorization setting must be preset. &lt;br&gt;In our system, we provide a way for common users to grant priviledge to and revoke priviledge from client (3rd party) applications. Also the user must upload a public key against which signature of requests receieved from client app can be verified. &lt;br&gt;&lt;strong&gt;Snapshot&lt;/strong&gt;&lt;br&gt;&lt;a href="http://lh5.ggpht.com/_qiIXUonGAyk/SgEnm-tMxLI/AAAAAAAAAfY/i-KZivxsEzk/s1600-h/oauthServer-0_1_myproxy%5B3%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="809" alt="oauthServer-0_1_myproxy" src="http://lh5.ggpht.com/_qiIXUonGAyk/SgEnpFjbbPI/AAAAAAAAAfc/_txIk3flukA/oauthServer-0_1_myproxy_thumb%5B1%5D.jpg?imgmax=800" width="835" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h3&gt;Tables&lt;/h3&gt; &lt;dl&gt; &lt;dt&gt;oauth_server_users  &lt;dd&gt;Basic user account information. Currently, just includes user name and password.  &lt;dt&gt;oauth_server_setting  &lt;dd&gt;stores public key extracted from myproxy server or direct upload.  &lt;dt&gt;oauth_server_dev  &lt;dd&gt;Stores information of registered client applications.  &lt;dt&gt;oauth_server_userappauth  &lt;dd&gt;Stores information of priviledge authorization set by each user. &lt;/dd&gt;&lt;/dl&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1648946436729434139?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1648946436729434139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1648946436729434139' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1648946436729434139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1648946436729434139'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/05/implementation-of-2-legged-oauth.html' title='Implementation of 2-Legged OAuth'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_qiIXUonGAyk/SgEneHpL0RI/AAAAAAAAAfo/jo_p0bE67oA/s72-c/oauthConsumer-0_1_consumers_thumb%5B8%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2912652875392892516</id><published>2009-04-08T10:54:00.001-04:00</published><updated>2009-04-08T10:54:40.096-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><title type='text'>Port attribute in HTTP Cookie</title><content type='html'>&lt;p&gt;Recently, I have encountered a http session problem in jetty.&lt;br&gt;I start two Jetty instances on the same machine. These two jetty instances share the same base URL, but port numbers are different.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; http://example.com:8000/&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; http://example.com:9000/&lt;br&gt;When I visit http://example.com:8000/, a cookie (called JSESSIONID) is set by the server automatically. &lt;br&gt;After that I visit the other URL http://example.com:9000/, the cookie set for http://example.com:8000/ is sent to the server by user agent. The the server gets confused :-( &lt;/p&gt; &lt;p&gt;After debugging it, I found the reason is that the server does NOT include port number in the Set-Cookie header. According to section 3.3.1 in &lt;a href="http://www.faqs.org/rfcs/rfc2965.html"&gt;RFC 2965&lt;/a&gt;, if the port attribute is missing in the Set-Cookie header, the user agent would react based on following description:&lt;/p&gt;&lt;pre&gt;   Port    The default behavior is that a cookie MAY be returned to any
           request-port.&lt;/pre&gt;
&lt;p&gt;That means if a cookie is set for address &lt;em&gt;A&lt;/em&gt;, the cookie also matches those addresses which share all the same URL components with &lt;em&gt;A&lt;/em&gt; but port number.&lt;/p&gt;
&lt;p&gt;For tomcat, I searched its email list&lt;br&gt;&lt;a title="http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;q=cookie+port+site%3Ahttp%3A%2F%2Fmail-archives.apache.org%2Fmod_mbox%2Ftomcat-users%2F&amp;amp;btnG=Search" href="http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;q=cookie+port+site%3Ahttp%3A%2F%2Fmail-archives.apache.org%2Fmod_mbox%2Ftomcat-users%2F&amp;amp;btnG=Search"&gt;http://www.google.com/search?hl=en&amp;amp;client=firefox-a&amp;amp;rls=org.mozilla%3Aen-US%3Aofficial&amp;amp;q=cookie+port+site%3Ahttp%3A%2F%2Fmail-archives.apache.org%2Fmod_mbox%2Ftomcat-users%2F&amp;amp;btnG=Search&lt;/a&gt;&lt;br&gt;It seems that port number currently is not supported in cookie management. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;(1) use different domain names which map to the same IP&lt;br&gt;(2) use different paths.&lt;br&gt;E.g.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; http://example.com:8000/&lt;strong&gt;&lt;em&gt;webapp1&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; http://example.com:9000/&lt;strong&gt;&lt;em&gt;webapp2&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2912652875392892516?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2912652875392892516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2912652875392892516' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2912652875392892516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2912652875392892516'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/04/port-attribute-in-http-cookie.html' title='Port attribute in HTTP Cookie'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-676210425592193203</id><published>2009-04-03T02:38:00.001-04:00</published><updated>2009-04-03T02:38:53.108-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>OAuth + MyProxy integration prototype</title><content type='html'>&lt;h2&gt;Client&lt;/h2&gt; &lt;p&gt;Client is the consumer of backend services. &lt;br&gt;Functionalities  &lt;ul&gt; &lt;li&gt; &lt;div&gt;A simple user management system&lt;br&gt;Users can create new accounts, log in the system and log out the system. &lt;/div&gt; &lt;li&gt; &lt;div&gt;Each user can upload her/his private key &lt;/div&gt; &lt;li&gt; &lt;div&gt;&lt;a id="user_id_backend_service_setting" name="user_id_backend_service_setting"&gt;&lt;/a&gt;For each backend service, the user can set his/her user id which is bound to the backend service.&lt;br&gt;&lt;a href="http://lh6.ggpht.com/_qiIXUonGAyk/SdWu-U-bihI/AAAAAAAAAdA/2LOCqCz6PaM/s1600-h/oauth_myproxy_consumer_uid_binding%5B2%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; margin: 10px 0px; border-left: 0px; border-bottom: 0px" height="286" alt="oauth_myproxy_consumer_uid_binding" src="http://lh4.ggpht.com/_qiIXUonGAyk/SdWu-1qHpPI/AAAAAAAAAdE/l6ia9R3zXyo/oauth_myproxy_consumer_uid_binding_thumb.png?imgmax=800" width="498" border="0"&gt;&lt;/a&gt; &lt;/div&gt;In above figure, the end user logins the client app as user "john". The client support accessing of three backend services. Then the user sets the binding of user id to each backend service. When the user wants to invoke backend service 1, the client app would set the user id to "mark" in the requests. &lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Service Provider &lt;/h2&gt; &lt;p&gt;Functionalities of the service provider:  &lt;ul&gt; &lt;li&gt; &lt;div&gt;A simple user management system&lt;/div&gt; &lt;li&gt;&lt;a id="myproxy_account_binding" name="myproxy_account_binding"&gt;&lt;/a&gt; &lt;div&gt;Each user can bind a MyProxy account to his/her local account.&lt;br&gt;The needed information of MyProxy account includes username, password, MyProxy server host and port number. &lt;br&gt;Then the server would automatically retrieve a certificate chain from the specified MyProxy server. After parsing the certificate chain, public key of the original certificate that belongs to the user is extracted. &lt;br&gt;&lt;strong&gt;Note&lt;/strong&gt;: we don't use public key included the proxy certificate. There is just one original certificate stored in the MyProxy server while many proxy certificates can be acquired. Each time a new proxy certificate is requested, a new public/private key is created and the public key is sent to MyProxy server. Usually, this process is done by system automatically. &lt;/div&gt; &lt;li&gt; &lt;div&gt;Each service could be accessed by various client applications. Users can set which client apps are allowed to access their data. &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;OAuth Integration &lt;/h2&gt; &lt;p&gt;In &lt;a href="http://oauth.net/core/1.0"&gt;OAuth&lt;/a&gt; authorization procedure, there are three main steps: &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Get a request token  &lt;li&gt;Ask user to authorize the request  &lt;li&gt;Exchange request token with an access token &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Then the access token acquired in step (3) is used to access protected resources. &lt;br&gt;Trust relationship between client app and service provider is built out of band. Two mechanisms are supported: shared secret and RSA. &lt;br&gt;In my solution, step (2) is extended with step (1) and (3) staying the same. Two additional parameters are added: &lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;cgl_oauth_signagure&lt;/code&gt;. Parameter &lt;code&gt;user_id&lt;/code&gt; is described &lt;a href="#user_id_backend_service_setting"&gt;here&lt;/a&gt;. The &lt;code&gt;cgl_oauth_signature&lt;/code&gt; is calculated against &lt;code&gt;user_id&lt;/code&gt; using the user's private key. After service provider receives the request, the corresponding public key (&lt;a href="#myproxy_account_binding"&gt;retrieved from MyProxy server&lt;/a&gt;) is used to verify the signature.&lt;/p&gt; &lt;h2&gt;Future Work &lt;/h2&gt; &lt;ol&gt; &lt;li&gt;Revoke the authorized privileges  &lt;ol&gt; &lt;li&gt;Users can set an expiration time after which the access token will become invalid. Then the whole OAuth authorization process must be executed once again.  &lt;li&gt;Provides a way for user to revoke authorized privileges at any time they like. &lt;/li&gt;&lt;/ol&gt; &lt;li&gt;Trust relationship establishment.&lt;br&gt;Developers of client apps go to specified web page of the service provider to apply for development account. Then one of the following two things happens:  &lt;ul&gt; &lt;li&gt;A shared secret would be generated automatically and copied to the corresponding client app.  &lt;li&gt;The developers of the client apps upload their certificate to backend service. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-676210425592193203?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/676210425592193203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=676210425592193203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/676210425592193203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/676210425592193203'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/04/oauth-myproxy-integration-prototype.html' title='OAuth + MyProxy integration prototype'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_qiIXUonGAyk/SdWu-1qHpPI/AAAAAAAAAdE/l6ia9R3zXyo/s72-c/oauth_myproxy_consumer_uid_binding_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2372700911741411614</id><published>2009-02-28T19:48:00.000-05:00</published><updated>2009-02-28T19:49:22.606-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gadget'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>Deploy standalone shindig on Quarry and an OAuth gadget demo</title><content type='html'>&lt;p&gt; I got a virtual machine which I can log in as root. The virtual machine is pretty clean without any more packages besides CentOS. &lt;br&gt;I installed vim using yum install vim-enhanced. I also installed jdk1.5 and maven2.&lt;/p&gt; &lt;p&gt;Then I checked out the source code from shindig svn trunk. See instructions here &lt;a title="http://incubator.apache.org/shindig/#tab-building" href="http://incubator.apache.org/shindig/#tab-building"&gt;http://incubator.apache.org/shindig/#tab-building&lt;/a&gt;.&lt;br&gt;Unfortunately, the test failed when I compiled and installed shindig. This kind of things always happens because of instability of trunk code. So I copied my previous checkout of shindig code which worked well from another machine. Then the compilation and installation succeeded. &lt;/p&gt; &lt;h3&gt;OAuth gadget demo to retrieve google contact list&lt;/h3&gt; &lt;p&gt;Now the sample demo is here:&lt;br&gt;&lt;a title="http://gw11.quarry.iu.teragrid.org:9999/gadgets/files/samplecontainer/samplecontainer.html" href="http://gw11.quarry.iu.teragrid.org:9999/gadgets/files/samplecontainer/samplecontainer.html"&gt;http://gw11.quarry.iu.teragrid.org:9999/gadgets/files/samplecontainer/samplecontainer.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Set field "Displaying gadget" to &lt;a title="http://156.56.104.196:8888/oauth/gadgets/os_gadget.xml" href="http://156.56.104.196:8888/oauth/gadgets/os_gadget.xml"&gt;http://156.56.104.196:8888/oauth/gadgets/os_gadget.xml&lt;/a&gt;, Uncheck "use cache".&lt;br&gt;Click button "reset all". If everything works fine, you would see following in main panel:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/_qiIXUonGAyk/Sanbgfu2oOI/AAAAAAAAAcw/OgS6h5GZN7o/s1600-h/temp%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="210" alt="temp" src="http://lh6.ggpht.com/_qiIXUonGAyk/SanbhmX-WjI/AAAAAAAAAc0/Kfohu6BqYhI/temp_thumb%5B1%5D.jpg?imgmax=800" width="795" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Clieck "Personalize this gadget", a popup window would appear which prompts you to login to your google account. Then you can choose grant or deny the access request. If you grant the request, the popup window would be closed automatically, and the main panel would be populated with your google contact list.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2372700911741411614?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2372700911741411614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2372700911741411614' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2372700911741411614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2372700911741411614'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/02/deploy-standalone-shindig-on-quarry-and.html' title='Deploy standalone shindig on Quarry and an OAuth gadget demo'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_qiIXUonGAyk/SanbhmX-WjI/AAAAAAAAAc0/Kfohu6BqYhI/s72-c/temp_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6831432606713461730</id><published>2009-02-21T22:57:00.001-05:00</published><updated>2009-02-21T22:58:29.839-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='dom'/><title type='text'>Manipulate IFrame in Javascript</title><content type='html'>&lt;p&gt;&lt;strong&gt;Create a iframe and set the content directly&lt;/strong&gt;:&lt;br&gt;&lt;pre class="js:nocontrols" name="code"&gt;var frame = document.createElement('iframe');
parentElement.appendChild(frame);
frame.contentDocument.write(result);&lt;/pre&gt;According to Dom level 2 HTML specification, &lt;em&gt;contentDocument&lt;/em&gt; is a property of &lt;a href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-50708718" target="_blank"&gt;HTMLIFrameElement&lt;/a&gt;. 
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Following code may also work. However I have not found the &lt;em&gt;contentWindow&lt;/em&gt; property in W3C DOM specification.&lt;pre class="js:nocontrols" name="code"&gt;var frame = document.createElement('iframe');
parentElement.appendChild(frame);
frame.contentWindow.document.write(result);&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6831432606713461730?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6831432606713461730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6831432606713461730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6831432606713461730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6831432606713461730'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/02/manipulate-iframe-in-javascript.html' title='Manipulate IFrame in Javascript'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6137313624009427390</id><published>2009-02-14T23:58:00.001-05:00</published><updated>2009-02-17T23:34:49.735-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><title type='text'>Integration of OpenSocial containers via OAuth</title><content type='html'>&lt;p&gt;For &lt;a href="http://code.google.com/apis/opensocial/" target="_blank"&gt;OpenSocial gadgets&lt;/a&gt;,&amp;nbsp; OpenSocial containers are necessary to hold users' data (friends, profile, ...). In Javascript API, class &lt;a href="http://code.google.com/apis/opensocial/docs/0.8/reference/#opensocial.DataRequest" target="_blank"&gt;opensocial.DataRequest&lt;/a&gt; can be used to get users' data from the container which renders the gadget. &lt;/p&gt; &lt;p&gt;But to integrate users' data from third-party OpenSocial containers, some additional steps are needed. &lt;a href="http://code.google.com/apis/opensocial/docs/0.8/reference/#opensocial.DataRequest" target="_blank"&gt;opensocial.DataRequest&lt;/a&gt; does not allow gadget developers to specify which OpenSocial container would be used to serve the data. Also the gadgets can not send requests directly to third-party containers because of Same-Origin policy imposed by browsers. &lt;/p&gt; &lt;p&gt;Method &lt;em&gt;gadgets.io.makeRequest&lt;/em&gt; can be used to send arbitrary HTTP GET/POST requests. These requests are sent to the original container first. The original container does some processing and relays the requests to the destination address. &lt;br&gt;&lt;a title="http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#gadgets.io.makeRequest" href="http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#gadgets.io.makeRequest"&gt;http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#gadgets.io.makeRequest&lt;/a&gt;&lt;br&gt;&lt;a title="http://code.google.com/apis/opensocial/articles/makerequest-0.8.html" href="http://code.google.com/apis/opensocial/articles/makerequest-0.8.html"&gt;http://code.google.com/apis/opensocial/articles/makerequest-0.8.html&lt;/a&gt;&lt;br&gt;&lt;a title="http://code.google.com/apis/gadgets/docs/remote-content.html" href="http://code.google.com/apis/gadgets/docs/remote-content.html"&gt;http://code.google.com/apis/gadgets/docs/remote-content.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;Both REST and RPC protocol specifications requires that compliant containers must be OAuth service provider:&lt;br&gt;&lt;a title="http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/restful-protocol" href="http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/restful-protocol"&gt;http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/restful-protocol&lt;/a&gt; (Section 4)&lt;br&gt;&lt;a title="http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/rpc-protocol" href="http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/rpc-protocol"&gt;http://www.opensocial.org/Technical-Resources/opensocial-spec-v081/rpc-protocol&lt;/a&gt;&lt;br&gt;Also I found &lt;a href="http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/1/spec.html" target="_blank"&gt;OAuth Consumer Request 1.0 Draft 1&lt;/a&gt; (hosted at googlecode, not oauth.net) which standardizes two-legged authorization process without a User involvement. It is useful in server-to-server interaction. &lt;/p&gt; &lt;p&gt;How to use OAuth in gadgets&lt;br&gt;&lt;a title="http://code.google.com/apis/gadgets/docs/oauth.html" href="http://code.google.com/apis/gadgets/docs/oauth.html"&gt;http://code.google.com/apis/gadgets/docs/oauth.html&lt;/a&gt; (&lt;strong&gt;&lt;font color="#ff0000"&gt;Very useful&lt;/font&gt;&lt;/strong&gt;)&lt;br&gt;&lt;a title="http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy" href="http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy"&gt;http://sites.google.com/site/oauthgoog/oauth-proxy/social-oauthproxy&lt;/a&gt;&lt;/p&gt; &lt;p&gt;OpenSocial container list:&lt;br&gt;&lt;a title="http://wiki.opensocial.org/index.php?title=Main_Page#Container_Information" href="http://wiki.opensocial.org/index.php?title=Main_Page#Container_Information"&gt;http://wiki.opensocial.org/index.php?title=Main_Page#Container_Information&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Extensions:&lt;/strong&gt;&lt;br&gt;Also, I found many OAuth extension drafts which are not listed in OAuth.net. I guess these extensions are implemented in Shindig and evaluated. &lt;br&gt;&lt;a title="http://oauth.googlecode.com/svn/spec/ext/" href="http://oauth.googlecode.com/svn/spec/ext/"&gt;http://oauth.googlecode.com/svn/spec/ext/&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6137313624009427390?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6137313624009427390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6137313624009427390' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6137313624009427390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6137313624009427390'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/02/integration-of-opensocial-containers.html' title='Integration of OpenSocial containers via OAuth'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-3307051008199007636</id><published>2009-02-07T16:44:00.000-05:00</published><updated>2009-02-07T16:45:55.714-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Enable/Disabl Directory Listing in Tomcat</title><content type='html'>&lt;p&gt;By default, directory listing (list content of a directory instead of render a web page) is forbidden in Tomcat.&lt;/p&gt; &lt;p&gt;&lt;font color="#0000ff" size="3"&gt;To enable it globally&lt;/font&gt;, modified file &lt;em&gt;&amp;lt;tomcat&amp;gt;/conf/web.xml&lt;/em&gt;.&lt;br&gt;Default setting for default servlet is:&lt;/p&gt;&lt;pre&gt;    &amp;lt;servlet&amp;gt;
        &amp;lt;servlet-name&amp;gt;default&amp;lt;/servlet-name&amp;gt;
        &amp;lt;servlet-class&amp;gt;org.apache.catalina.servlets.DefaultServlet&amp;lt;/servlet-class&amp;gt;
        &amp;lt;init-param&amp;gt;
            &amp;lt;param-name&amp;gt;debug&amp;lt;/param-name&amp;gt;
            &amp;lt;param-value&amp;gt;0&amp;lt;/param-value&amp;gt;
        &amp;lt;/init-param&amp;gt;
        &amp;lt;init-param&amp;gt;
            &lt;font color="#0000ff"&gt;&amp;lt;param-name&amp;gt;listings&amp;lt;/param-name&amp;gt;
            &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;&lt;/font&gt;
        &amp;lt;/init-param&amp;gt;
        &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
    &amp;lt;/servlet&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Change the &lt;em&gt;param-value&lt;/em&gt; for parameter &lt;em&gt;listings&lt;/em&gt; to &lt;em&gt;true.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#0000ff" size="3"&gt;To enable it for a specific web application&lt;/font&gt;, add following snippet to the &lt;em&gt;web.xml&lt;/em&gt; of the application&lt;pre&gt;    &amp;lt;servlet&amp;gt;
        &amp;lt;servlet-name&amp;gt;&lt;font color="#ff0000"&gt;default_new&lt;/font&gt;&amp;lt;/servlet-name&amp;gt;
        &amp;lt;servlet-class&amp;gt;
          org.apache.catalina.servlets.DefaultServlet
        &amp;lt;/servlet-class&amp;gt;
        &amp;lt;init-param&amp;gt;
            &amp;lt;param-name&amp;gt;debug&amp;lt;/param-name&amp;gt;
            &amp;lt;param-value&amp;gt;0&amp;lt;/param-value&amp;gt;
        &amp;lt;/init-param&amp;gt;
        &amp;lt;init-param&amp;gt;
            &amp;lt;param-name&amp;gt;listings&amp;lt;/param-name&amp;gt;
            &amp;lt;param-value&amp;gt;&lt;font color="#ff0000"&gt;true&lt;/font&gt;&amp;lt;/param-value&amp;gt;
        &amp;lt;/init-param&amp;gt;
        &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
    &amp;lt;/servlet&amp;gt;
    &amp;lt;!-- The mapping for the default servlet --&amp;gt;
&lt;font color="#ff0000"&gt;    &amp;lt;servlet-mapping&amp;gt;
        &amp;lt;servlet-name&amp;gt;default_new&amp;lt;/servlet-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/servlet-mapping&amp;gt;&lt;/font&gt;&lt;/pre&gt;Note: &lt;strong&gt;servet-name can not be &lt;em&gt;default&lt;/em&gt; because it is name of tomcat's default servlet .&lt;/strong&gt; So you need to use a different name. Also &lt;em&gt;servlet-mapping&lt;/em&gt; element is necessary to make it work.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-3307051008199007636?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/3307051008199007636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=3307051008199007636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3307051008199007636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3307051008199007636'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/02/enabledisabl-directory-listing-in.html' title='Enable/Disabl Directory Listing in Tomcat'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-7291838631099656289</id><published>2009-02-07T16:01:00.000-05:00</published><updated>2009-02-07T16:02:59.853-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shindig'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>Shindig server on Tomcat</title><content type='html'>&lt;p&gt;Shindig can be run with built-in jetty server without problems. But after I deployed the &lt;em&gt;war&lt;/em&gt; to Tomcat, there are some problems. I got a blank page when I tried to render a gadget. I searched for the problem, some other guys got this problem as well.&lt;/p&gt; &lt;p&gt;Other posts related to this problem:&lt;br&gt;&lt;a title="http://mail-archives.apache.org/mod_mbox/incubator-shindig-dev/200805.mbox/%3C483C780B.6080802@oracle.com%3E" href="http://mail-archives.apache.org/mod_mbox/incubator-shindig-dev/200805.mbox/%3C483C780B.6080802@oracle.com%3E"&gt;http://mail-archives.apache.org/mod_mbox/incubator-shindig-dev/200805.mbox/%3C483C780B.6080802@oracle.com%3E&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Finally I figured out how to make shindig work on Tomcat.&lt;br&gt;&lt;b&gt;Why does not it work?&lt;/b&gt;&lt;br&gt;It ignores the context path. In other words, the implementation only considers the situation that the application is deployed as root application.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Two possible Solutions&lt;/b&gt;&lt;br&gt;(1) make shindig &lt;em&gt;war&lt;/em&gt; the root application&lt;br&gt;Two alternative ways:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (*) rename it to ROOT.war and deploy it to tomcat. (The original ROOT application cannot be used)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (*) change &lt;i&gt;conf/context.xml&lt;/i&gt; to set shindig application as root application&lt;br&gt;(2) Modify shindig configuration files &lt;i&gt;&amp;lt;shindig&amp;gt;/java/common/conf/shindig.properties&lt;/i&gt; and &lt;i&gt;&amp;lt;shindig&amp;gt;/config/container.js&lt;/i&gt; to add context path in all related urls.&lt;br&gt;It seems to work well. I am not sure whether there is any potential problem.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-7291838631099656289?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/7291838631099656289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=7291838631099656289' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7291838631099656289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7291838631099656289'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2009/02/shindig-server-on-tomcat.html' title='Shindig server on Tomcat'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6168288041804609097</id><published>2008-11-08T02:21:00.000-05:00</published><updated>2008-11-08T02:22:28.199-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Maven cheat sheet</title><content type='html'>Download and install maven: &lt;a title="http://maven.apache.org/download.html" href="http://maven.apache.org/download.html"&gt;http://maven.apache.org/download.html&lt;/a&gt;.  &lt;p&gt;&lt;font face="Courier New" size="4"&gt;&lt;strong&gt;Running Maven&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;&lt;a title="http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html" href="http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html"&gt;http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html&lt;/a&gt;&lt;br&gt;&lt;a title="http://maven.apache.org/guides/getting-started/index.html" href="http://maven.apache.org/guides/getting-started/index.html"&gt;http://maven.apache.org/guides/getting-started/index.html&lt;/a&gt;&lt;br&gt;Generally the local repository is provided in USER_HOME/.m2/repository.  &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;&lt;font face="Courier New"&gt;&lt;font size="4"&gt;Configuration&lt;/font&gt;&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;a title="http://maven.apache.org/guides/mini/guide-configuring-maven.html" href="http://maven.apache.org/guides/mini/guide-configuring-maven.html"&gt;http://maven.apache.org/guides/mini/guide-configuring-maven.html&lt;/a&gt; &lt;br&gt;Three levels:  &lt;ul&gt; &lt;li&gt;&lt;i&gt;Project&lt;/i&gt; - most static configuration occurs in &lt;tt&gt;pom.xml&lt;/tt&gt;.&lt;br&gt;There should be a project configuration for every project. The configuration in &lt;tt&gt;pom.xml&lt;/tt&gt; overrides the same configuration in other two levels. A user does not need to specify every aspect of the configuration. Those unspecified aspects are inherited from Maven's default &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Super_POM" target="_blank"&gt;Super POM&lt;/a&gt;.&lt;br&gt;Introduction to POM: &lt;a title="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Super_POM" href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Super_POM"&gt;http://maven.apache.org/guides/introduction/introduction-to-the-pom.html&lt;/a&gt;.&lt;br&gt;POM reference: &lt;a title="http://maven.apache.org/pom.html" href="http://maven.apache.org/pom.html"&gt;http://maven.apache.org/pom.html&lt;/a&gt;  &lt;li&gt;&lt;i&gt;Installation&lt;/i&gt; - this is configuration added once for a Maven installation&lt;br&gt;This configuration file is generally located in M2_HOME/conf/settings.xml. &lt;br&gt;NOTE: This location can be overridden with the system property:&lt;br&gt;&lt;tt&gt;-Dorg.apache.maven.global-settings=/path/to/global/settings.xml&lt;/tt&gt; &lt;br&gt;Guide: &lt;a title="http://maven.apache.org/guides/mini/guide-configuring-maven.html" href="http://maven.apache.org/guides/mini/guide-configuring-maven.html"&gt;http://maven.apache.org/guides/mini/guide-configuring-maven.html&lt;/a&gt;&lt;br&gt;Reference: &lt;a title="http://maven.apache.org/ref/2.0.8/maven-settings/settings.html" href="http://maven.apache.org/ref/2.0.8/maven-settings/settings.html"&gt;http://maven.apache.org/ref/2.0.8/maven-settings/settings.html&lt;/a&gt;&lt;br&gt;Detailed reference: &lt;a title="http://maven.apache.org/settings.html" href="http://maven.apache.org/settings.html"&gt;http://maven.apache.org/settings.html&lt;/a&gt;  &lt;li&gt;&lt;i&gt;User&lt;/i&gt; - this is configuration specific to a particular user &lt;br&gt;This configuration file is generally located in USER_HOME/.m2/settings.xml.&lt;br&gt;NOTE: This location can be overridden with the system property:&lt;br&gt;&lt;tt&gt;-Dorg.apache.maven.user-settings=/path/to/user/settings.xml&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;font size="4"&gt;&lt;strong&gt;Build&lt;/strong&gt;&lt;/font&gt; your own private/internal repository:&lt;/font&gt;&lt;br&gt;This article introduces how to create a repository using Artifactory: &lt;a title="http://www.theserverside.com/tt/articles/article.tss?l=SettingUpMavenRepository" href="http://www.theserverside.com/tt/articles/article.tss?l=SettingUpMavenRepository"&gt;http://www.theserverside.com/tt/articles/article.tss?l=SettingUpMavenRepository&lt;/a&gt;. In addition, the author also compares some mainstream maven remote repository managers including Standard maven proxy, Dead simple Maven Proxy, Proximity and Artifactory.&lt;br&gt;In my case, I also use Artifactory and deploy it to tomcat. It has a nice web-based interface. Artifactory uses database(derby I think) to store various repository data so a user can not know the repository content by directly looking at the directory. &lt;br&gt;&lt;br&gt;&lt;font size="3"&gt;&lt;strong&gt;&lt;font size="4"&gt;Deploy&lt;/font&gt;&lt;/strong&gt; your artifacts to remote repository by using maven-deploy plugin:&lt;/font&gt;&lt;br&gt;&lt;a title="http://maven.apache.org/plugins/maven-deploy-plugin/usage.html" href="http://maven.apache.org/plugins/maven-deploy-plugin/usage.html"&gt;http://maven.apache.org/plugins/maven-deploy-plugin/usage.html&lt;/a&gt;&lt;br&gt;(1) If the artifacts are built by using Maven, you should use &lt;em&gt;deploy:deploy&lt;/em&gt; Mojo.&lt;br&gt;In your pom.xml, element &lt;tt&gt;&amp;lt;distributionManagement/&amp;gt;&lt;/tt&gt; should be inserted to tell Maven how to deploy current package. If your repository is secured, you may also want to configure your &lt;tt&gt;settings.xml&lt;/tt&gt; file to define corresponding &lt;tt&gt;&amp;lt;server/&amp;gt;&lt;/tt&gt; entries which provides authentication information.&lt;br&gt;Command: &lt;em&gt;mvn deploy.&lt;/em&gt;&lt;br&gt;(2) If the artifacts are &lt;strong&gt;NOT&lt;/strong&gt; built by using Maven, you should use &lt;em&gt;deploy:deploy-file&lt;/em&gt; Mojo.&lt;br&gt;Sample command:&lt;br&gt;mvn deploy:deploy-file -Dpackaging=jar -Durl=file:/grids/c2/www/htdocs/maven2&amp;nbsp; &lt;br&gt;-Dfile=./junit.jar -DgroupId=gridshib -DartifactId=junit -Dversion=GTLAB&lt;br&gt;&lt;br&gt;&lt;font face="Courier New" size="5"&gt;&lt;strong&gt;FAQ:&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;(1) What does maven standard directory layout look like?&lt;br&gt;&lt;a title="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html" href="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html"&gt;http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html&lt;/a&gt;&lt;br&gt;(1) How to specify parent artifact in &lt;tt&gt;pom.xml&lt;/tt&gt;?&lt;br&gt;Read &lt;a title="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Super_POM" href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html"&gt;http://maven.apache.org/guides/introduction/introduction-to-the-pom.html&lt;/a&gt;.&lt;br&gt;(2) If a dependent package can not be download from central Maven repository, three methods can be used to deal with it:&lt;/p&gt; &lt;blockquote&gt;"  &lt;ol style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 0px; padding-top: 0px"&gt; &lt;li&gt;Install the dependency locally using the install plugin. The method is the simplest recommended method. For example: &lt;pre&gt;mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1&lt;/pre&gt;
&lt;p&gt;Notice that an address is still required, only this time you use the command line and the install plugin will create a POM for you with the given address.&lt;/p&gt;
&lt;li&gt;Create your own repository and deploy it there. This is a favorite method for companies with an intranet and need to be able to keep everyone in synch. There is a Maven goal called &lt;tt&gt;deploy:deploy-file&lt;/tt&gt; which is similar to the &lt;tt&gt;install:install-file&lt;/tt&gt; goal (read the plugin's goal page for more information). 
&lt;li&gt;Set the dependency scope to &lt;tt&gt;system&lt;/tt&gt; and define a &lt;tt&gt;systemPath&lt;/tt&gt;. This is not recommended, however, but leads us to explaining the following elements: &lt;/li&gt;&lt;/ol&gt;"&lt;/blockquote&gt;(2) How to add new repository?&lt;br&gt;Put following code snippet into &lt;em&gt;pom.xml&lt;/em&gt; or &lt;em&gt;settings.xml&lt;/em&gt;.&lt;pre&gt;&amp;lt;repository&amp;gt;
  &amp;lt;id&amp;gt;your-new-repository-id&amp;lt;/id&amp;gt;
  &amp;lt;name&amp;gt;New Maven Repository &amp;lt;/name&amp;gt;
  &amp;lt;layout&amp;gt;default&amp;lt;/layout&amp;gt;
  &amp;lt;url&amp;gt;Address of the new repository&amp;lt;/url&amp;gt;
  &amp;lt;snapshots&amp;gt;
    &amp;lt;enabled&amp;gt;enable-it?&amp;lt;/enabled&amp;gt;
  &amp;lt;/snapshots&amp;gt;
  &amp;lt;releases&amp;gt;
    &amp;lt;enabled&amp;gt;enable-it?&amp;lt;/enabled&amp;gt;
  &amp;lt;/releases&amp;gt;
&amp;lt;/repository&amp;gt;&lt;/pre&gt;(3) How to disable default central maven repository?&lt;br&gt;Put following snippet into your pom.xml.&lt;pre&gt;&amp;lt;repository&amp;gt;
  &amp;lt;id&amp;gt;central&amp;lt;/id&amp;gt;
  &amp;lt;name&amp;gt;Maven Repository Switchboard&amp;lt;/name&amp;gt;
  &amp;lt;layout&amp;gt;default&amp;lt;/layout&amp;gt;
  &amp;lt;url&amp;gt;http://repo1.maven.org/maven2&amp;lt;/url&amp;gt;
  &amp;lt;snapshots&amp;gt;
    &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;
  &amp;lt;/snapshots&amp;gt;
  &amp;lt;releases&amp;gt;
    &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;
  &amp;lt;/releases&amp;gt;
&amp;lt;/repository&amp;gt;&lt;/pre&gt;(4) How can I package source code without run test?&lt;br&gt;Feed parameter &lt;code&gt;-Dmaven.test.skip=true&lt;/code&gt; into the command line. &lt;br&gt;Note this property is defined by maven plugin &lt;em&gt;surefire&lt;/em&gt;.&lt;br&gt;(5) Why does "mvn clean" delete my source code?&lt;br&gt;In your pom.xml, if content of element &amp;lt;&lt;em&gt;directory&lt;/em&gt;&amp;gt; nested in element &amp;lt;&lt;em&gt;build&lt;/em&gt;&amp;gt; is "./", "mvn clean" will delete all content in current directory including the &lt;em&gt;src&lt;/em&gt; directory. &lt;br&gt;There are two more elements which can be used to specify locations of compiled classes.&lt;br&gt;&lt;tt&gt;outputDirectory&lt;/tt&gt;:&amp;nbsp; The directory where compiled &lt;em&gt;&lt;strong&gt;application classes&lt;/strong&gt;&lt;/em&gt; are placed.&lt;br&gt;&lt;tt&gt;testOutputDirectory&lt;/tt&gt;:&amp;nbsp; The directory where compiled &lt;strong&gt;&lt;em&gt;test classes&lt;/em&gt;&lt;/strong&gt; are placed.&lt;br&gt;(6) How to add resources into built package?&lt;br&gt;&lt;a title="http://maven.apache.org/guides/getting-started/index.html#How_do_I_add_resources_to_my_JAR" href="http://maven.apache.org/guides/getting-started/index.html#How_do_I_add_resources_to_my_JAR"&gt;http://maven.apache.org/guides/getting-started/index.html#How_do_I_add_resources_to_my_JAR&lt;/a&gt;.&lt;br&gt;&lt;a title="http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files" href="http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files"&gt;http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6168288041804609097?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6168288041804609097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6168288041804609097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6168288041804609097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6168288041804609097'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/11/maven-cheat-sheet.html' title='Maven cheat sheet'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1276980946869179382</id><published>2008-10-10T18:09:00.001-04:00</published><updated>2008-10-10T18:09:52.782-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Automatically adjust height of IFrame using Javascript</title><content type='html'>&lt;p&gt;A simple and natural requirement, but unfortunately it may or may not work as you expect.&lt;br&gt;What matters here is security. If src of an iframe does not access external address, it works well. Otherwise, nothing will solve the problem except that the user lowers the security level. Javascript can not access information of an IFrame whose content is hosted by a third-party site.&lt;/p&gt; &lt;p&gt;Let us assume that src of an iframe does not point to an external resource, following code can be used:&lt;pre&gt;var ele =document.getElementById(frameid); 
ele.style.height = ele.contentWindow.document.body.scrollHeight&lt;/pre&gt;
&lt;p&gt;You may wonder why &lt;em&gt;document.frames[frame_name]&lt;/em&gt; is not used here. Anyway, I tried it on Firefox 3, it did not work. As you know, compatibility is a real pain for web developers.&lt;/p&gt;
&lt;p&gt;One possible solution is to set up a proxy server which relays the requests/responses.&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1276980946869179382?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1276980946869179382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1276980946869179382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1276980946869179382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1276980946869179382'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/10/automatically-adjust-height-of-iframe.html' title='Automatically adjust height of IFrame using Javascript'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1062155933308166278</id><published>2008-09-10T13:22:00.001-04:00</published><updated>2008-09-10T13:22:50.821-04:00</updated><title type='text'>Some notes about tomcat/hibernate/servlet</title><content type='html'>&lt;p&gt; &lt;h4&gt;Tomcat&lt;/h4&gt;For tomcat applications, resources (configuration files...) should be put in directory WEB-INF/classes. The files cannot be symbolic links. They MUST be regular files in order for tomcat to handle them correctly. Of course, you can embed resources into your .jar files.&lt;br&gt;For Tomcat, the regular CLASSPATH environment variable is IGNORED. The resources (jars, configuration files...) must be put into your tomcat app directory. Read &lt;a href="http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html"&gt;this post&lt;/a&gt; to see what is under the hood.&lt;br&gt;Resource/class search order for web apps:&amp;nbsp; &lt;ul&gt; &lt;li&gt;Bootstrap classes of your JVM  &lt;li&gt;System class loader classses (described above)  &lt;li&gt;&lt;em&gt;/WEB-INF/classes&lt;/em&gt; of your web application  &lt;li&gt;&lt;em&gt;/WEB-INF/lib/*.jar&lt;/em&gt; of your web application  &lt;li&gt;&lt;em&gt;$CATALINA_HOME/lib&lt;/em&gt;  &lt;li&gt;&lt;em&gt;$CATALINA_HOME/lib/*.jar&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;The System class loader is the only place where CLASSPATH can be parsed and used. However, tomcat startup script(&lt;em&gt;bin/catalina.sh&lt;/em&gt;) totally ignore environment variable CLASSPATH. You will figure it out if you read file &lt;em&gt;bin/setclasspath.sh&lt;/em&gt;. In my case, first several lines are :&lt;pre&gt;#  Set CLASSPATH and Java options
# 
#  $Id: setclasspath.sh 589060 2007-10-27 08:19:24Z jfclere $
# -----------------------------------------------------------------------------

# &lt;font color="#ff0000"&gt;First clear out the user classpath&lt;/font&gt;
CLASSPATH= &lt;/pre&gt;Now, you know the root of the problem right? If you want to include CLASSPATH, you can modify the bash file. I have not tried it. It should work. 
&lt;p&gt;
&lt;h4&gt;Hibernate&lt;/h4&gt;For hibernate app, corresponding mapping tables must be created before you can run your app. Hibernate will NOT create those tables automatically for you. For the primary key property/column, If you use generator "&lt;em&gt;native&lt;/em&gt;", you must set property of the primary key column correctly in order to let database generate primary key values correctly. For example, you can use AUTO_INCREMENT to make database automatically generate primary key values in MySQL. You can choose to use generator "&lt;em&gt;assigned&lt;/em&gt;" to assign primary key values in your programs. &lt;br&gt;For database operations in Hibernate, you should always &lt;strong&gt;EXPLICITLY&lt;/strong&gt; start and commit a transaction. 
&lt;p&gt;
&lt;h4&gt;Servlet/JSP&lt;/h4&gt;Method &lt;a href="http://java.sun.com/products/servlet/2.2/javadoc/javax/servlet/RequestDispatcher.html#forward(javax.servlet.ServletRequest,%20javax.servlet.ServletResponse)"&gt;Forward&lt;/a&gt; declared in RequestDispatcher should be understood correctly. It is an INTERNAL control transfer. It means this control transfer is TRANSPARENT to end users. One consequence is that the links in the target page, to which you forward control, MUST use absolute path instead of relative path.&lt;br&gt;For example, first a user sends request to &lt;em&gt;&lt;a href="http://domain/users/gerald.jsp"&gt;http://domain/users/gerald.jsp&lt;/a&gt;&lt;/em&gt;. At server side, your servlet internally transfers control to &lt;em&gt;/users/profiles/g/gerald.jsp&lt;/em&gt;. In the target page, if you have links with relative path, the paths are relative to the original request path (&lt;em&gt;/users/&lt;/em&gt; in this example) instead of path of the target page (&lt;em&gt;/users/profiles/g/&lt;/em&gt; in this example).&lt;br&gt;Your servlet should not have generated any response ( in output stream to request sender ) when redirection or forwarding is carried out. 
&lt;p&gt;&lt;/p&gt;
&lt;style&gt;
h4{
    margin-bottom: 0px;
    padding-bottom: 0px;
}&lt;/style&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1062155933308166278?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1062155933308166278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1062155933308166278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1062155933308166278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1062155933308166278'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/09/some-notes-about-tomcathibernateservlet.html' title='Some notes about tomcat/hibernate/servlet'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1056241603472541275</id><published>2008-09-07T16:59:00.000-04:00</published><updated>2008-09-07T17:14:13.318-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>Hibernate installation (run on MySQL)</title><content type='html'>&lt;p&gt;Recently, I tried to install Hibernate on gridfarm machine. The version I used was 3.3.0 SP1.&lt;br&gt;Configuration document can be found &lt;a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html" target="_blank"&gt;here&lt;/a&gt;. However, the document seems not to be updated. &lt;br&gt;&lt;strong&gt;(1) Configuration file hibernate.properties vs. hibernate.cfg.xml.&lt;/strong&gt;&lt;br&gt;In the document, either one can be used. If both are used, configurations in &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; would override configurations in &lt;em&gt;hibernate.properties&lt;/em&gt;. The document says using &lt;em&gt;hibernate.properties&lt;/em&gt; is an easy way to configure Hibernate. So I chose it. However, after trial I found that in Hibernate 3.3.0 SP1 &lt;em&gt;hibernate.cfg.xml&lt;/em&gt;. In other words, you MUST have a configuration file &lt;em&gt;"hibernate.cfg.xml&lt;/em&gt;". Of course, you can use programmatical configuration which is not covered in this post.&lt;br&gt;&lt;strong&gt;(2) Logger&lt;/strong&gt;&lt;br&gt;In documents, I saw "&lt;tt&gt;Hibernate logs various events using Apache commons-logging.&lt;/tt&gt;". However, when I tried to run my Hibernate app, it complained that logger class can not be found. After inspection, I figured out that Hibernate 3.3.0 does NOT use Apache common-logging any more. Instead it uses &lt;a href="http://www.slf4j.org/" target="_blank"&gt;&lt;em&gt;slf4j&lt;/em&gt;&lt;/a&gt;. But in Hibernate 3.3.0 SP1 distribution only &lt;em&gt;slf4j-api&lt;/em&gt; jar is included while an implementation is needed to run Hibernate(If you turn off logging, I don't know whether it will still complain). In other words, to use logging functionality, you must download an implementation of logging service supported by &lt;em&gt;slf4j&lt;/em&gt;. I used &lt;em&gt;slf4j-simple&lt;/em&gt;.&lt;br&gt;&lt;strong&gt;(3) JNDI bindings (for session factory and data source).&lt;/strong&gt; &lt;br&gt;Because I just wanted to write a simple prototype without deploying in J2EE server, I chose not to use JNDI bindings for data source or session factory. After several hour trial, I could not get it to work!! I always got the error &lt;code&gt;"org.hibernate.impl.SessionFactoryObjectFactory - Could not bind factory to JNDI"&lt;/code&gt;.It seemed that Hibernate always was always trying to use JNDI to bind Session Factory. However, the official document says &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;"A JNDI bound Hibernate &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; can simplify the lookup of the factory and the creation of new &lt;tt class="literal"&gt;Session&lt;/tt&gt;s. Note that this is not related to a JNDI bound &lt;tt class="literal"&gt;Datasource&lt;/tt&gt;, both simply use the same registry! &lt;/p&gt; &lt;p&gt;If you wish to have the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; bound to a JNDI namespace, specify a name (eg. &lt;tt class="literal"&gt;java:hibernate/SessionFactory&lt;/tt&gt;) using the property &lt;tt class="literal"&gt;hibernate.session_factory_name&lt;/tt&gt;. &lt;font color="#ff0000"&gt;&lt;strong&gt;If this property is omitted, the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; will not be bound to JNDI.&lt;/strong&gt;&lt;/font&gt; (This is especially useful in environments with a read-only JNDI default implementation, e.g. Tomcat.) &lt;/p&gt; &lt;p&gt;When binding the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; to JNDI, Hibernate will use the values of &lt;tt class="literal"&gt;hibernate.jndi.url&lt;/tt&gt;, &lt;tt class="literal"&gt;hibernate.jndi.class&lt;/tt&gt; to instantiate an initial context. If they are not specified, the default &lt;tt class="literal"&gt;InitialContext&lt;/tt&gt; will be used. &lt;/p&gt; &lt;p&gt;Hibernate will automatically place the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; in JNDI after you call &lt;tt class="literal"&gt;cfg.buildSessionFactory()&lt;/tt&gt;. This means you will at least have this call in some startup code (or utility class) in your application, unless you use JMX deployment with the &lt;tt class="literal"&gt;HibernateService&lt;/tt&gt; (discussed later). &lt;/p&gt; &lt;p&gt;If you use a JNDI &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt;, an EJB or any other class may obtain the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; using a JNDI lookup. &lt;/p&gt; &lt;p&gt;We recommend that you bind the &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; to JNDI in a managend environment and use a &lt;tt class="literal"&gt;static&lt;/tt&gt; singleton otherwise. To shield your application code from these details, we also recommend to hide the actual lookup code for a &lt;tt class="literal"&gt;SessionFactory&lt;/tt&gt; in a helper class, such as &lt;tt class="literal"&gt;HibernateUtil.getSessionFactory()&lt;/tt&gt;. Note that such a class is also a convenient way to startup Hibernate—see chapter 1. "&lt;/p&gt;&lt;/blockquote&gt;It turned out that a property called "&lt;tt&gt;hibernate.current_session_context_class&lt;/tt&gt;" must be set. &lt;br&gt;My &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; looks like:&lt;br&gt;&lt;pre class="xml:nocontrols" name="code"&gt;&amp;lt;!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&amp;gt;

&amp;lt;hibernate-configuration&amp;gt;
    &amp;lt;session-factory&amp;gt;
        &amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;
        &amp;lt;property name="current_session_context_class"&amp;gt;thread&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.username"&amp;gt;username&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.password"&amp;gt;password&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.url"&amp;gt;jdbc:mysql://localhost/hibernate&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.driver_class"&amp;gt;com.mysql.jdbc.Driver&amp;lt;/property&amp;gt;
        &amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.MySQLDialect&amp;lt;/property&amp;gt;
        &amp;lt;mapping resource="User.hbm.xml"/&amp;gt; 
    &amp;lt;/session-factory&amp;gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;/pre&gt;Then, I tried a very very simple read-only JNDI service provider - &lt;a href="http://www.osjava.org/simple-jndi/" target="_blank"&gt;&lt;em&gt;simple-jndi&lt;/em&gt;&lt;/a&gt;. My simple-jndi configuration file (&lt;em&gt;jndi.properties&lt;/em&gt; which should be put into root of your classpath) looks like: &lt;pre&gt;#The first (required) parameter, org.osjava.sj.root, is the location 
#of your simple-jndi root, which is the location in which simple-jndi
#looks for values when code asks for them.

org.osjava.sj.root=/home/zhguo/share/simple-JNDI/config
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory&lt;/pre&gt;Under directory pointed to by &lt;em&gt;org.osjava.sj.root&lt;/em&gt; property, I have a jndi data file called &lt;em&gt;hibernate_jndi.properties&lt;/em&gt;:&lt;pre&gt;mysql.type=javax.sql.DataSource
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://localhost/hibernate
mysql.user=username
mysql.password=password&lt;/pre&gt;So, my new version of &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; looks like:&lt;pre class="xml:nocontrols" name="code"&gt;&amp;lt;hibernate-configuration&amp;gt;
    &amp;lt;session-factory&amp;gt;
        &amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;
        &amp;lt;property name="current_session_context_class"&amp;gt;thread&amp;lt;/property&amp;gt;
        &amp;lt;property name="connection.datasource"&amp;gt;hibernate_jndi.mysql&amp;lt;/property&amp;gt;
        &amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.MySQLDialect&amp;lt;/property&amp;gt;
        &amp;lt;mapping resource="User.hbm.xml"/&amp;gt; 
    &amp;lt;/session-factory&amp;gt;
&amp;lt;/hibernate-configuration&amp;gt;&lt;/pre&gt;Note: in the file, session factory name is not set! This is because we are using a read-only JNDI. If you use a read-write JNDI, you can set the session factory name in one of the following ways:&lt;br&gt;(*) In &lt;em&gt;hibernate.properties&lt;/em&gt; file:&lt;br&gt;&lt;code&gt;hibernate.session_factory_name hibernate/session_factory&lt;/code&gt;&lt;br&gt;(*) In &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; file:&lt;br&gt;&lt;code&gt;&amp;lt;session-factory name="your name goes here"&amp;gt;&lt;/code&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1056241603472541275?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1056241603472541275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1056241603472541275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1056241603472541275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1056241603472541275'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/09/hibernate-installation-run-on-mysql.html' title='Hibernate installation (run on MySQL)'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4632595663965282699</id><published>2008-08-27T01:18:00.000-04:00</published><updated>2008-08-27T01:19:37.865-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hbase'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>Hadoop and HBase port usage</title><content type='html'>&lt;div class="PubSectionHeader"&gt;&lt;font size="+0"&gt;Hadoop port usage&lt;/font&gt;&lt;/div&gt;&lt;a name="NDSelIwoQqMb3icAj"&gt;&lt;/a&gt; &lt;div class="PubNote"&gt; &lt;div class="PubNoteContentArea"&gt;&lt;b&gt;On name node&lt;/b&gt;&lt;br&gt;50090: org.apache.hadoop.dfs.SecondaryNameNode&lt;br&gt;33220: ditto.(This port is not fixed and may be changed when hadoop is restarted)&lt;br&gt;&lt;br&gt;50070: org.apache.hadoop.dfs.NameNode&lt;br&gt;9000:ditto&lt;br&gt;46684: ditto(This port is not fixed and may be changed when hadoop is restarted)&lt;br&gt;&lt;br&gt;9001: org.apache.hadoop.mapred.JobTracker&lt;/div&gt; &lt;div class="PubNoteContentArea"&gt;50030: ditto&lt;br&gt;60502: ditto(This port is not fixed and may be changed when hadoop is restarted)&lt;br&gt;&lt;br&gt;&lt;b&gt;On data node&lt;/b&gt;&lt;br&gt;50075: org.apache.hadoop.dfs.DataNode &lt;br&gt;50010: ditto&lt;br&gt;45868: ditto(This port is not fixed and may be changed when hadoop is restarted)&lt;br&gt;&lt;br&gt;50060: org.apache.hadoop.mapred.TaskTracker&lt;br&gt;55027: ditto(This port is not fixed and may be changed when hadoop is restarted)&lt;/div&gt;&lt;/div&gt;&lt;a name="NDSVoIgoQ6Y-FlMAj"&gt;&lt;/a&gt; &lt;p&gt; &lt;div class="PubNoteContentArea"&gt;&lt;font size="+0"&gt;HBase port usage&lt;/font&gt;&lt;br&gt;&lt;b&gt;On master&lt;/b&gt;&lt;br&gt;60000: org.apache.hadoop.hbase.master.HMaster start&lt;br&gt;60010: ditto&lt;br&gt;&lt;br&gt;&lt;b&gt;On data node&lt;/b&gt;&lt;br&gt;60030: org.apache.hadoop.hbase.regionserver.HRegionServer&lt;br&gt;60020: ditto&lt;br&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4632595663965282699?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4632595663965282699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4632595663965282699' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4632595663965282699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4632595663965282699'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/08/hadoop-and-hbase-port-usage.html' title='Hadoop and HBase port usage'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6441916017722587849</id><published>2008-08-25T15:04:00.000-04:00</published><updated>2008-08-25T15:08:39.059-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hbase'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>Insert pubchem data into HBase</title><content type='html'>&lt;strong&gt;HBase shell&lt;/strong&gt;&lt;br&gt;HBase provides a shell utility which lets users to execute simple commands. The shell can be started up using:&lt;br&gt;&lt;code&gt;${HBASE_HOME}/bin/hbase shell&lt;/code&gt;&lt;br&gt;Then input command &lt;em&gt;help&lt;/em&gt; to get help document which describes usage of various supported commands. These commands can be used to manipulate data stored in HBase. E.g. command &lt;em&gt;list&lt;/em&gt; can be used to list all tables in hbase. Command &lt;em&gt;get&lt;/em&gt; can be used to get row or cell contents from hbase. Command &lt;em&gt;put&lt;/em&gt; can be used to store data into a cell.  &lt;p&gt;&lt;strong&gt;Data insertion&lt;/strong&gt;&lt;br&gt;Data source is &lt;a title="ftp://ftp.ncbi.nlm.nih.gov/pubchem/" href="ftp://ftp.ncbi.nlm.nih.gov/pubchem/"&gt;ftp://ftp.ncbi.nlm.nih.gov/pubchem/&lt;/a&gt;. I modified python scripts and C source code given by Rajarshi.&lt;br&gt;Data retrieval and processing steps:  &lt;ol style="margin-top: 5px"&gt; &lt;li&gt;Download all information about compounds from &lt;a title="ftp://ftp.ncbi.nlm.nih.gov/pubchem/Compound/CURRENT-Full/SDF" href="ftp://ftp.ncbi.nlm.nih.gov/pubchem/Compound/CURRENT-Full/SDF"&gt;ftp://ftp.ncbi.nlm.nih.gov/pubchem/Compound/CURRENT-Full/SDF&lt;/a&gt;. I finally got 123 GB.  &lt;li&gt;Decompress those files  &lt;li&gt;Extract information from these &lt;em&gt;.sdf&lt;/em&gt; files and write it to &lt;em&gt;.txt&lt;/em&gt; files. Library o&lt;em&gt;penbabel&lt;/em&gt; is used to compile the C++ code.  &lt;li&gt;Combine those &lt;em&gt;.txt&lt;/em&gt; files generated in step 3 into one big &lt;em&gt;.dat&lt;/em&gt; file  &lt;li&gt;Write a ruby script to insert all data in the &lt;em&gt;.dat&lt;/em&gt; file into HBase. &lt;br&gt;Command is like this: &lt;code&gt;${HBASE_HOME}/bin/hbase org.jruby.Main rubyscript.rb&lt;/code&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;Why did I write Ruby script instead of Java program in step 5?&lt;/strong&gt;&lt;br&gt;HBase is written in Java and so provides Java API. However, to compile Java programs is kind of cumbersome -- set lengthy CLASSPATH ...&amp;nbsp; &lt;br&gt;So I chose to write scripts which can be executed directly by HBase shell. I found useful information on &lt;a href="http://wiki.apache.org/hadoop/Hbase/Shell" target="_blank"&gt;this page&lt;/a&gt;. There is a section called "&lt;em&gt;scripting&lt;/em&gt;" in that post. But the information there is far from complete. It does not tell readers how to write the scripts. At first, I wrote a script which included some shell commands, one command per line, and then fed it to hbase shell. Unfortunately, it didn't work. After enumerous trials, I found that Ruby scripts could be fed to shell. Ruby scripts cannot make use of existing shell commands directly. Ruby binding of original Java APIs must be used. &lt;/p&gt; &lt;p&gt;I have not learnt Ruby at all before. So I must teach myself to grasp basic knowledge about Ruby. Ruby is sort of different in terms of syntactic flexibility. It supports so many shorthands to improve productivity. Anyway, "Ruby is easy to learn, but hard to master". By the way, Ruby documents seem not to be abundant compared with Python, Perl...&lt;/p&gt; &lt;p&gt;&lt;strong&gt;How to write Ruby scripts for HBase?&lt;/strong&gt;&lt;br&gt;This site &lt;a title="http://wiki.apache.org/hadoop/Hbase/JRuby" href="http://wiki.apache.org/hadoop/Hbase/JRuby"&gt;http://wiki.apache.org/hadoop/Hbase/JRuby&lt;/a&gt; contains related information. But I could not run the sample script successfully because of errors in the script!!! Damn it! I wonder whether the author had tested the code before he released it. Some errors are so obvious. &lt;br&gt;After the ruby script is completed, it can be executed using:&lt;br&gt;&lt;code&gt;${HBASE_HOME}/bin/hbase org.jruby.Main rubyscript.rb&lt;/code&gt;&amp;nbsp;&lt;br&gt;&lt;strong&gt;Java API: &lt;/strong&gt;&lt;br&gt;&lt;a title="http://hadoop.apache.org/hbase/docs/current/api/index.html" href="http://hadoop.apache.org/hbase/docs/current/api/index.html"&gt;http://hadoop.apache.org/hbase/docs/current/api/index.html&lt;/a&gt;&lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;My ruby script:&lt;/strong&gt;&lt;pre class="ruby:nocontrols" name="code"&gt;#!/usr/bin/ruby -w

include Java
import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.HColumnDescriptor
import org.apache.hadoop.hbase.HTableDescriptor
import org.apache.hadoop.hbase.client.HBaseAdmin
import org.apache.hadoop.hbase.client.HTable
import org.apache.hadoop.hbase.io.BatchUpdate
import org.apache.hadoop.io.Text

pubchem_compound_fields = [
    'cid',
    'iupac_openeye_name',
    'iupac_cas_name',
    'iupac_name',
    'iupac_systematic_name',
    'iupac_traditional_name',
    'nist_inchi',
    'cactvs_xlogp',
    'cactvs_exact_mass',
    'openeye_mw',
    'openeye_can_smiles',
    'openeye_iso_smiles',
    'cactvs_tpsa',
    'total_charge',
    'heavy_atom_count']

compound_table_name = 'compound'

numfields = pubchem_compound_fields.length

path = "/home/zhguo/BigTable/BigTable-Pubchem/data/"
filename = "#{path}compound.dat"
file = File.new(filename, 'r')
counter = 0

conf = HBaseConfiguration.new
tablename = compound_table_name
tablename_text = Text.new(tablename)
desc = HTableDescriptor.new(tablename)
coltextarr = Array.new
pubchem_compound_fields.each_with_index do |v, i|
    if (i == 0) then next; end
    desc.addFamily(HColumnDescriptor.new("#{v}:"))
    coltextarr &amp;lt;&amp;lt; Text.new("#{v}:")
end

admin = HBaseAdmin.new(conf)
if !admin.tableExists(tablename_text) then
    admin.createTable(desc)
=begin
    puts "deleting table #{tablename_text}"
    admin.disableTable(tablename_text)
    admin.deleteTable(tablename_text)
    puts "deleted table #{tablename_text} successfully"
=end
end

#admin.createTable(desc)
table = HTable.new(conf, tablename_text)

startind = 1641500 #from which line should we start.This
                   #is useful when you don't want to start
                   #from the beginning of the data file.

nlines = `cat #{filename} | wc -l`

logfilename = 'updatedb.log'
logfile = File.new(logfilename, "a")
while (line = file.gets) #&amp;amp;&amp;amp; (counter &amp;lt; 20)
    counter += 1
    if (counter &amp;lt; startind) then
        next
    end
    msg = "processing line #{counter}/#{nlines}"
    logfile.puts msg
    if counter%100 == 0 then
        print  msg
        STDOUT.flush
        logfile.flush
    end

    arr = line.split("\t")
    len = arr.length
        if (numfields != len) then
        next
    end
    rowindex = 0
    rowname = arr[rowindex]
    arr.delete_at(rowindex)
    row = Text.new(rowname)
    b = BatchUpdate.new(row)

    arr.each_with_index do |v, i|
        str = java.lang.String.new(v)
        b.put(coltextarr[i], str.getBytes("UTF-8"))
    end
    table.commit(b)
end&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6441916017722587849?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6441916017722587849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6441916017722587849' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6441916017722587849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6441916017722587849'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/08/insert-pubchem-data-into-hbase.html' title='Insert pubchem data into HBase'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1927185099983278658</id><published>2008-08-24T18:33:00.001-04:00</published><updated>2008-08-27T01:55:00.241-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hbase'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><category scheme='http://www.blogger.com/atom/ns#' term='hadoop'/><title type='text'>Installation and configuration of Hadoop and Hbase</title><content type='html'>&lt;p&gt; &lt;h3&gt;Hadoop&lt;/h3&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;Hadoop installation instructions: &lt;a title="http://hadoop.apache.org/core/docs/current/quickstart.html" href="http://hadoop.apache.org/core/docs/current/quickstart.html"&gt;http://hadoop.apache.org/core/docs/current/quickstart.html&lt;/a&gt; and &lt;a title="http://hadoop.apache.org/core/docs/current/cluster_setup.html" href="http://hadoop.apache.org/core/docs/current/cluster_setup.html"&gt;http://hadoop.apache.org/core/docs/current/cluster_setup.html&lt;/a&gt;.&lt;br&gt;To set up hadoop cluster, generally two configuration files should be modified:&lt;br&gt;hadoop-site.xml and slaves.&lt;br&gt;(1) My &lt;em&gt;hadoop-site.xml&lt;/em&gt; looks like: &lt;pre&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;property&amp;gt;
    &amp;lt;name&amp;gt;fs.default.name&amp;lt;/name&amp;gt;
    &amp;lt;value&amp;gt;pg3:9000&amp;lt;/value&amp;gt;
  &amp;lt;/property&amp;gt;
  &amp;lt;property&amp;gt;
    &amp;lt;name&amp;gt;mapred.job.tracker&amp;lt;/name&amp;gt;
    &amp;lt;value&amp;gt;pg3:9001&amp;lt;/value&amp;gt;
  &amp;lt;/property&amp;gt;
  &amp;lt;property&amp;gt;
    &amp;lt;name&amp;gt;dfs.replication&amp;lt;/name&amp;gt;
    &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;
  &amp;lt;/property&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;Read file &lt;em&gt;hadoop-default.xml&lt;/em&gt; for all available options.&lt;br&gt;(2) My &lt;em&gt;slaves&lt;/em&gt; file looks like: &lt;pre&gt;localhost
pg1
pg2&lt;/pre&gt;
&lt;p&gt;I need to install Hadoop on three machines now and I use &lt;em&gt;rsync&lt;/em&gt; to make these machines synchronized with eath other in terms of configuration. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Commands&lt;/strong&gt;&lt;br&gt;(*) Format a new file system: &lt;code&gt;hadoop namenode -format&lt;/code&gt;&lt;br&gt;(*) Start/stop Hadoop&lt;br&gt;&lt;code&gt;start-dfs.sh/stop-dfs.sh&lt;/code&gt; &lt;br&gt;start up the distributed file system (HDFS)&lt;br&gt;&lt;code&gt;start-mapred.sh/stop-mapred.sh&lt;/code&gt; &lt;br&gt;start up map reduce service.&lt;br&gt;&lt;code&gt;start-all.sh/stop-all.sh&lt;/code&gt; &lt;br&gt;start up both HDFS and map reduce service&lt;/p&gt;
&lt;p&gt;Hadoop reads content in file &lt;em&gt;slaves&lt;/em&gt; to get all nodes and then starts up all these nodes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Check status of the services&lt;/strong&gt;&lt;br&gt;HDFS: &lt;a title="http://pg3.ucs.indiana.edu:50070/" href="http://domain:50070/"&gt;http://domain:50070/&lt;/a&gt;&lt;br&gt;MapReduce: &lt;a title="http://pg3.ucs.indiana.edu:50070/" href="http://domain:50030/"&gt;http://domain:50030/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;HBase&lt;/h3&gt;Installation instructions: &lt;a title="http://hadoop.apache.org/hbase/docs/current/api/overview-summary.html#overview_description" href="http://hadoop.apache.org/hbase/docs/current/api/overview-summary.html#overview_description"&gt;http://hadoop.apache.org/hbase/docs/current/api/overview-summary.html#overview_description&lt;/a&gt;&lt;br&gt;The configuration file is &lt;em&gt;hbase-site.xml&lt;/em&gt;. My &lt;em&gt;hbase-site.xml&lt;/em&gt; looks like&lt;pre&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;property&amp;gt;
    &amp;lt;name&amp;gt;hbase.master&amp;lt;/name&amp;gt;
    &amp;lt;value&amp;gt;pg3:60000&amp;lt;/value&amp;gt;
    &amp;lt;description&amp;gt;The host and port that the HBase master runs at.&amp;lt;/description&amp;gt;
  &amp;lt;/property&amp;gt;

  &amp;lt;property&amp;gt;
    &amp;lt;name&amp;gt;hbase.rootdir&amp;lt;/name&amp;gt;
    &amp;lt;value&amp;gt;hdfs://pg3.ucs.indiana.edu:9000/hbase&amp;lt;/value&amp;gt;
    &amp;lt;description&amp;gt;The directory shared by region servers.&amp;lt;/description&amp;gt;
  &amp;lt;/property&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Commands&lt;/strong&gt;&lt;br&gt;&lt;code&gt;start-hbase.sh&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;starts up hbase service&lt;br&gt;&lt;code&gt;stop-hbase.sh&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&amp;nbsp; stop hbase service&lt;/p&gt;
&lt;p&gt;Note: &lt;em&gt;hbase&lt;/em&gt; bases its functionalities on &lt;em&gt;hadoop&lt;/em&gt;. Sometimes it is necessary for &lt;em&gt;hbase&lt;/em&gt; to know the configuration of &lt;em&gt;hadoop&lt;/em&gt;. Following statements are excerpted from &lt;em&gt;hbase&lt;/em&gt; document which I think is important: 
&lt;blockquote&gt;"Of note, if you have made &lt;i&gt;HDFS client configuration&lt;/i&gt; on your hadoop cluster, hbase will not see this configuration unless you do one of the following: 
&lt;ul&gt;
&lt;li&gt;Add a pointer to your &lt;code&gt;HADOOP_CONF_DIR&lt;/code&gt; to &lt;code&gt;CLASSPATH&lt;/code&gt; in &lt;code&gt;hbase-env.sh&lt;/code&gt; 
&lt;li&gt;Add a copy of &lt;code&gt;hadoop-site.xml&lt;/code&gt; to &lt;code&gt;${HBASE_HOME}/conf&lt;/code&gt;, or 
&lt;li&gt;If only a small set of HDFS client configurations, add them to &lt;code&gt;hbase-site.xml&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;An example of such an HDFS client configuration is &lt;code&gt;dfs.replication&lt;/code&gt;. If for example, you want to run with a replication factor of 5, hbase will create files with the default of 3 unless you do the above to make the configuration available to hbase. "&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1927185099983278658?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1927185099983278658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1927185099983278658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1927185099983278658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1927185099983278658'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/08/installation-and-configuration-of.html' title='Installation and configuration of Hadoop and Hbase'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5763874629414358164</id><published>2008-08-18T15:06:00.000-04:00</published><updated>2008-08-18T15:08:13.203-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='nfs'/><title type='text'>Mysql error "InnoDB: Unable to lock ./ibdata1, error: 11"</title><content type='html'>&lt;p&gt;Recently, there was a power outage in the lab. I did not shut down my machines before the power outage. After I restarted my Ubuntu, I could not start up Mysql. The error was:&lt;pre&gt;InnoDB: Unable to lock ./ibdata1, error: 11
InnoDB: Check that you do not already have another mysqld process
InnoDB: using the same InnoDB data or log files.
InnoDB: Error in opening ./ibdata1&lt;/pre&gt;
&lt;p&gt;But I am 100% sure that no another mysqld process was running. After I searched on line, I found that I was not the only one encountering this error. See &lt;a href="http://forums.mysql.com/read.php?22,22344,22344#msg-22344" target="_blank"&gt;this post&lt;/a&gt;. &lt;br&gt;&lt;a href="http://forums.mysql.com/read.php?22,22344,24497#msg-24497" target="_blank"&gt;This post&lt;/a&gt; has an insight into this problem. It seems to be caused by NFS. Mysql is not installed on a local file system. It is installed on a remote file system which is mounted to other file systems by using NFS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;make a copy of the original files (ibdata1, ib_logfile0, ib_logfile1...).&lt;pre&gt;mv ibdata1 ibdata1.bak&lt;br&gt;cp -a ibdata1.bak ibdata1&lt;br&gt;......&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5763874629414358164?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5763874629414358164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5763874629414358164' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5763874629414358164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5763874629414358164'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/08/mysql-error-unable-to-lock-ibdata1.html' title='Mysql error &amp;quot;InnoDB: Unable to lock ./ibdata1, error: 11&amp;quot;'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2874270567796783423</id><published>2008-07-29T22:01:00.001-04:00</published><updated>2008-07-29T22:01:32.102-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cms'/><category scheme='http://www.blogger.com/atom/ns#' term='drupal'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Social Networking on Drupal</title><content type='html'>&lt;p&gt;Previously, I tried several open source social networking frameworks including &lt;a href="http://elgg.org" target="_blank"&gt;elgg&lt;/a&gt;, &lt;a href="http://www.barnraiser.org/demos/aroundme" target="_blank"&gt;aroundme&lt;/a&gt;, &lt;a href="http://www.broadbandmechanics.com" target="_blank"&gt;peopleaggregator&lt;/a&gt;... However, few of them are mature and stable. So I also tried Content Management Systems. I delved into Drupal.&lt;br&gt;Drupal is an excellent CMS which has many powerful modules. Some modules provide social networking support. There exists a &lt;a href="http://groups.drupal.org/social-networking-sites" target="_blank"&gt;drupal group&lt;/a&gt; which promotes social networking support in Drupal. &lt;br&gt;Here I list some useful modules which may be used in social networking:&lt;br&gt;&lt;a href="http://drupal.org/project/og" target="_blank"&gt;Organic Groups&lt;/a&gt;&lt;br&gt;"Enable users to create and manage their own groups. Each group can have subscribers, and maintains a group home page. Groups get their own theme, language, taxonomy, and so on."&lt;br&gt;&lt;br&gt;&lt;a href="http://drupal.org/project/buddylist" target="_blank"&gt;Buddylist&lt;/a&gt;&lt;br&gt;Allows users to add other users to buddy list, organize buddies into buddy group and monitor buddies' content.&lt;/p&gt; &lt;p&gt;&lt;a href="http://drupal.org/project/invite" target="_blank"&gt;Invite&lt;/a&gt;&lt;br&gt;Adds an 'Invite a friend' feature that allows users to send and track invitations to join a web site.&lt;/p&gt; &lt;p&gt;&lt;a href="http://drupal.org/project/foaf" target="_blank"&gt;FOAF&lt;/a&gt;&lt;br&gt;Functionalities:&lt;br&gt;"1. automatically import/synchronize profile information between any Drupal-powered sites&lt;br&gt;2. import profile information from external FOAF files&lt;br&gt;3. export a FOAF file based on a user's profile"&lt;/p&gt; &lt;p&gt;&lt;a href="http://drupal.org/project/privatemsg" target="_blank"&gt;Privatemsg&lt;/a&gt;&lt;br&gt;Allows users to send private messages to each other.&lt;/p&gt; &lt;p&gt;&lt;a href="http://drupal.org/project/user_relationships" target="_blank"&gt;User Relationships&lt;/a&gt;&lt;br&gt;Allow users to create named relationships between each other.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Wiki&lt;/strong&gt;&lt;br&gt;&lt;a href="http://drupal.org/project/interwiki" target="_blank"&gt;interwiki&lt;/a&gt;&lt;br&gt;This filter provides a simplified, wiki-like syntax for linking to articles or search results on many commonly-used internet reference websites&lt;br&gt;&lt;a href="http://drupal.org/project/liquid" target="_blank"&gt;Liquid Wiki&lt;/a&gt;&lt;br&gt;The Liquid Wiki Engine Project aims to build a module providing wiki funktionality to Drupal.&lt;br&gt;&lt;a href="http://drupal.org/project/mediawiki" target="_blank"&gt;MediaWiki&lt;/a&gt;&lt;br&gt;Integrate Drupal with an existing MediaWiki installation.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Online Chat&lt;/strong&gt;&lt;br&gt;&lt;a href="http://drupal.org/project/chatroom" target="_blank"&gt;Chat Room&lt;/a&gt;&lt;br&gt;This module enables chat rooms to be set up on Drupal sites. No additional software is required. Chat Room uses AJAX to update chats without page reloads. Chat rooms are nodes that provide access to chats and chat archives.&lt;br&gt;&lt;a href="http://drupal.org/project/bowob" target="_blank"&gt;BoWoB&lt;/a&gt;&lt;br&gt;Free Chat for your website, integrated with your Drupal users and design. It is implemented in Flash.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2874270567796783423?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2874270567796783423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2874270567796783423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2874270567796783423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2874270567796783423'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/social-networking-on-drupal.html' title='Social Networking on Drupal'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6147272283254023612</id><published>2008-07-17T02:27:00.000-04:00</published><updated>2008-07-17T13:53:01.149-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><category scheme='http://www.blogger.com/atom/ns#' term='ringside'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Google Calendar Demo Gadgets</title><content type='html'>&lt;p&gt;I have implemented some calendar gadgets based on existing legacy gadgets. &lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;a name="app1"&gt;&lt;strong&gt;(1) Google calendar viewer gadget&lt;/strong&gt;&lt;/a&gt;&lt;/font&gt;&lt;br&gt;This app does not use Google Calendar Javascript API. Google Calendar generates automatically feeds for &lt;strong&gt;&lt;em&gt;public events&lt;/em&gt;&lt;/strong&gt; owned by a user. Address of the feed is &lt;a title="http://www.google.com/calendar/feeds/username@gmail.com/public/basic. " href="http://www.google.com/calendar/feeds/username@gmail.com/public/full"&gt;http://www.google.com/calendar/feeds/username@gmail.com/public/full&lt;/a&gt;. This gadget retrieves public events of a specific calendar user and display them accordingly. Not all events are retrieved and displayed. &lt;br&gt;Assume today is &lt;em&gt;A&lt;/em&gt;, then events that fall into period (&lt;em&gt;A-30days) &lt;/em&gt;to&lt;em&gt; (A + 60days)&lt;/em&gt; are handled.&lt;br&gt;&lt;strong&gt;&lt;em&gt;Note: this gadget can just get public events.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;I deployed it in both Orkut sandbox and Ringside.&amp;nbsp; Following screenshots are taken from Orkut.&lt;/p&gt; &lt;p&gt;Main page:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SH-G7c_w1JI/AAAAAAAAATw/5Z-lPM7-OVw/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="374" alt="image" src="http://lh3.ggpht.com/Jenvor/SH-G8SL24UI/AAAAAAAAAT0/2ergtg6uF9c/image_thumb%5B1%5D.png?imgmax=800" width="582" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Description of various parts of the page:&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SH-G9BLobNI/AAAAAAAAAT4/7UkKG5cQQko/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="468" alt="image" src="http://lh6.ggpht.com/Jenvor/SH-G901LxrI/AAAAAAAAAT8/F8xcKv6d8f4/image_thumb%5B3%5D.png?imgmax=800" width="732" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;When a user clicks the brief information of an event, detailed information will be displayed in place.&lt;br&gt;&amp;nbsp;&lt;a href="http://lh5.ggpht.com/Jenvor/SH-G-f6IImI/AAAAAAAAAUA/h5UBmzamlb0/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="374" alt="image" src="http://lh4.ggpht.com/Jenvor/SH-G_MZUPVI/AAAAAAAAAUE/C4ZrAvBI6gc/image_thumb%5B5%5D.png?imgmax=800" width="584" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;&lt;a name="app2"&gt;(2) Standalone Google calendar client application.&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;This app does not rely on Gadget API or Open Social API. It just relies on Google Calendar Javascript library. So it can be run independently without gadget container. I deployed it on Ringside &lt;strong&gt;&lt;em&gt;using IFrame&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;It can be accessed by visiting &lt;a title="http://gf1.ucs.indiana.edu:8080/gcalendar/calendar2.htm" href="http://gf1.ucs.indiana.edu:8080/gcalendar/calendar2.htm"&gt;http://gf1.ucs.indiana.edu:8080/gcalendar/calendar2.htm&lt;/a&gt; or you can use it in Ringside.&lt;/p&gt; &lt;p&gt;If a user has not logged in Google account, he/she will see a "Login" button.&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SH7nPHQ68zI/AAAAAAAAASw/1oboBICTDd4/s1600-h/image%5B33%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="456" alt="image" src="http://lh6.ggpht.com/Jenvor/SH7nPiBJQrI/AAAAAAAAAS0/q2gezqrlXrE/image_thumb%5B17%5D.png?imgmax=800" width="486" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;After user clicks the "Login" button, he/she will be redirected to Google login page. After he/she logs in Google, he/she will be redirected to a "Access Request Authorization" page. Then the user can choose to grant or deny the access. It is shown below:&lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SH7nQKdv9AI/AAAAAAAAAS4/McN0ffYGY_g/s1600-h/image%5B37%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="234" alt="image" src="http://lh6.ggpht.com/Jenvor/SH7nQq2NFqI/AAAAAAAAAS8/Gs1fFw74RGk/image_thumb%5B19%5D.png?imgmax=800" width="1275" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;After the user grants access, following initial page will be displayed:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SH7nQ6OXFqI/AAAAAAAAATA/SY8ax7thMhs/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="486" alt="image" src="http://lh4.ggpht.com/Jenvor/SH7nRQJU1DI/AAAAAAAAATE/1SMwgIpolFQ/image_thumb%5B2%5D.png?imgmax=800" width="526" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Description of every part in the page:&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SH7nSKC0rwI/AAAAAAAAATI/Jyp0xxBrcJI/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="516" alt="image" src="http://lh6.ggpht.com/Jenvor/SH7nSuEpwfI/AAAAAAAAATM/wGEIDjwFeBo/image_thumb%5B4%5D.png?imgmax=800" width="690" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;When a user clicks the time range selection text box, a data picker will be displayed so that the user can easily select time period. It is shown below:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SH7nTZTBz4I/AAAAAAAAATQ/mzu9BEINAz0/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="460" alt="image" src="http://lh6.ggpht.com/Jenvor/SH7nUH3HkUI/AAAAAAAAATU/cdWysf_C2Bw/image_thumb%5B6%5D.png?imgmax=800" width="510" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;When a user selects his/her time range and clicks "Go" button, information of events within the specific time perios will be retrieved. And when the user clicks the drop-down box with label "Select...", a list of events will be displayed. See below screenshot:&lt;br&gt;&amp;nbsp;&lt;a href="http://lh5.ggpht.com/Jenvor/SH7nU6cvxjI/AAAAAAAAATY/DNMoSyAiRGM/s1600-h/image%5B21%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="488" alt="image" src="http://lh6.ggpht.com/Jenvor/SH7nVLF_02I/AAAAAAAAATc/03stNPEdwHo/image_thumb%5B11%5D.png?imgmax=800" width="538" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;When the user selects an event, detailed information will be displayed in corresponding fields.&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SH7nVjo4YEI/AAAAAAAAATg/xfDJWWZjEEY/s1600-h/image%5B25%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="476" alt="image" src="http://lh4.ggpht.com/Jenvor/SH7nV6F66bI/AAAAAAAAATk/dCVGISLq2w8/image_thumb%5B13%5D.png?imgmax=800" width="514" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The user can modify information of an event and save it back in Google Calendar by clicking button "Save to Google Calendar". &lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SH7nWeXGgvI/AAAAAAAAATo/Oc1mG2xw-MY/s1600-h/image%5B29%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="476" alt="image" src="http://lh5.ggpht.com/Jenvor/SH7nWt6APII/AAAAAAAAATs/77UN6wzLKRw/image_thumb%5B15%5D.png?imgmax=800" width="514" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;(3) Google calendar gadget which allowes users to log in&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;This gadget is different from &lt;a href="#app1" target="_self"&gt;the first gadget&lt;/a&gt; mentioned above because this gadget allowes users to log in so that all events(public and private) can be retrieved and displayed. This gadget is based on the &lt;a href="#app2" target="_self"&gt;app(2)&lt;/a&gt; which is described above. The user interface is the same as that of &lt;a href="#app2" target="_self"&gt;app(2)&lt;/a&gt;. &lt;br&gt;I deployed it on Ringside and Orkut sandbox successfully.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6147272283254023612?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6147272283254023612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6147272283254023612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6147272283254023612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6147272283254023612'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/google-calendar-demo-gadgets.html' title='Google Calendar Demo Gadgets'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/Jenvor/SH-G8SL24UI/AAAAAAAAAT0/2ergtg6uF9c/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4041659462131801339</id><published>2008-07-09T14:23:00.001-04:00</published><updated>2008-07-09T14:23:39.464-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='ringside'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>Demo Apps</title><content type='html'>&lt;p&gt;I have written several demo apps.&lt;br&gt;&lt;strong&gt;&lt;a name="app1"&gt;(1) A regular gadget with gadgets.* API&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;This is based on official youtube gadget presented &lt;a href="http://www.google.com/ig/directory?synd=open&amp;amp;num=24&amp;amp;url=http://www.google.com/ig/modules/youtube_videos.xml&amp;amp;output=html" target="_blank"&gt;here&lt;/a&gt;. Official youtube gadget uses traditional gadget API, which means it can not be run in open social containers. &lt;br&gt;I modified the source of official youtube gadget to make it compatible with open social API. Source is hosted &lt;a href="http://hosting.gmodules.com/ig/gadgets/file/105322631994749779353/youtube_os.xml" target="_blank"&gt;here&lt;/a&gt;. &lt;br&gt;I run it on Ringside, and it works well. Screenshot is shown below:&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SHUCEgHPDGI/AAAAAAAAARo/oj0tAdxQcKs/s1600-h/ringside_youtube2_thumb1%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="310" alt="ringside_youtube2_thumb1" src="http://lh3.ggpht.com/Jenvor/SHUCFYegtxI/AAAAAAAAARs/2JLjOqkvG2Y/ringside_youtube2_thumb1_thumb%5B1%5D.jpg?imgmax=800" width="536" border="0"&gt;&lt;/a&gt; &lt;br&gt;&lt;strong&gt;Besides&lt;/strong&gt;, I run it on iGoogle sandbox and Orkut sandbox successfully. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a name="app2"&gt;(2) An open social gadget&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;This gadget is written with Open Social API so that it can be run in all standard compatible containers. This gadget lists all friends you have in a container. If you add it to your Orkut account, it will list your friends in your Orkut account. If you add it to your hi5 account, it will list your friends in your hi5 account.&lt;br&gt;Source is hosted &lt;a href="http://hosting.gmodules.com/ig/gadgets/file/105322631994749779353/friends_os.xml" target="_blank"&gt;here&lt;/a&gt;.&lt;br&gt;I run it on Ringside, and screenshot is shown below:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SHUCFpD1k0I/AAAAAAAAARw/knS28-ZsDUg/s1600-h/image_thumb1%5B3%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="284" alt="image_thumb1" src="http://lh3.ggpht.com/Jenvor/SHUCIKCdIcI/AAAAAAAAAR0/PcPngRm911w/image_thumb1_thumb%5B1%5D.png?imgmax=800" width="750" border="0"&gt;&lt;/a&gt; &lt;br&gt;&lt;strong&gt;Besides&lt;/strong&gt;, I run it on iGoogle sandbox and Orkut sandbox successfully. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a name="app3"&gt;(3) A Facebook application.&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;This application gets your friend list on Facebook and displays related information including profile picture, last name, first name and birth date. You can see its information &lt;a href="http://www.facebook.com/apps/application.php?id=21740331581" target="_blank"&gt;here&lt;/a&gt;. Meanwhile you can add it to your Facebook account. &lt;br&gt;Screenshot is shown below:&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SHUCIJNitsI/AAAAAAAAAR4/unjjbmXXqPQ/s1600-h/image_thumb3%5B3%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="609" alt="image_thumb3" src="http://lh4.ggpht.com/Jenvor/SHUCIUzVeiI/AAAAAAAAAR8/EJjYPe3sJWc/image_thumb3_thumb%5B1%5D.png?imgmax=800" width="550" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a name="app4"&gt;(4) A port of application (3)(The facebook application).&amp;nbsp; &lt;/a&gt;&lt;br&gt;&lt;/strong&gt;Because Ringside implements Facebook API and FBML, application (3) should be able to be run on Ringside with minor modifications. New API key and secret should be used. Besides Ringside RESTful server (instead of Facebook server) address should be used.&lt;br&gt;Finally, I got it to run successfully on Ringside. &lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SHUCIirVeyI/AAAAAAAAASA/dfaKpfmzLLI/s1600-h/ringside_friend_thumb1%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="308" alt="ringside_friend_thumb1" src="http://lh5.ggpht.com/Jenvor/SHUCJE_DeYI/AAAAAAAAASE/VV2FBM7TvEc/ringside_friend_thumb1_thumb%5B1%5D.jpg?imgmax=800" width="736" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;(5) Make Facebook to use Ringside application&lt;/strong&gt;&lt;br&gt;I used the method described in &lt;a href="http://zhenhua-guo.blogspot.com/2008/07/interaction-between-facebook-and.html" target="_blank"&gt;this post&lt;/a&gt; and &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Getting+Started+Facebook+Application+Developers" target="_blank"&gt;this post&lt;/a&gt;. It should work. But unfortunately it did not work. Currently I don't know why. &lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;To try it in Ringside&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;First go to &lt;a title="http://gf1.ucs.indiana.edu:8080/" href="http://gf1.ucs.indiana.edu:8080/"&gt;http://gf1.ucs.indiana.edu:8080/&lt;/a&gt; to log in. &lt;br&gt;Then click tab "Applications":&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SHUCJF01DiI/AAAAAAAAASI/KBSB3v-yz5c/s1600-h/ringside_tab_thumb2%5B3%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="150" alt="ringside_tab_thumb2" src="http://lh4.ggpht.com/Jenvor/SHUCKXLxTuI/AAAAAAAAASM/lvg45aJvhxM/ringside_tab_thumb2_thumb%5B1%5D.png?imgmax=800" width="680" border="0"&gt;&lt;/a&gt; &lt;br&gt;Following page should be displayed:&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SHUCKsK8VgI/AAAAAAAAASQ/M5IOya8ucKQ/s1600-h/ringside_apps_thumb1%5B3%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="358" alt="ringside_apps_thumb1" src="http://lh6.ggpht.com/Jenvor/SHUCK1wRu-I/AAAAAAAAASU/oijQxdZrSSU/ringside_apps_thumb1_thumb%5B1%5D.png?imgmax=800" width="748" border="0"&gt;&lt;/a&gt; &lt;br&gt;Main panel displays a list of all applications you have added to your account. You can click any one to use it.&lt;br&gt;Or you can click button "Find More Apps" at top right corner to browse more available apps. &lt;br&gt;Application "youtube gadget" is the &lt;a href="#app1" target="_self"&gt;application (1)&lt;/a&gt; described above.&lt;br&gt;Application "Friend gadget(Open social)" is the &lt;a href="#app2" target="_self"&gt;application (2)&lt;/a&gt; described above.&lt;br&gt;Application "Your Friends Native" is the &lt;a href="#app4" target="_self"&gt;application(4)&lt;/a&gt; described above.&lt;br&gt;To run &lt;a href="#app3" target="_self"&gt;application (3)&lt;/a&gt;, you need a Facebook account and add it to your account by accessing &lt;a href="http://www.facebook.com/apps/application.php?id=21740331581" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4041659462131801339?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4041659462131801339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4041659462131801339' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4041659462131801339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4041659462131801339'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/demo-apps_09.html' title='Demo Apps'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/Jenvor/SHUCFYegtxI/AAAAAAAAARs/2JLjOqkvG2Y/s72-c/ringside_youtube2_thumb1_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4510056896337329176</id><published>2008-07-05T20:33:00.000-04:00</published><updated>2008-07-05T20:34:38.719-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><category scheme='http://www.blogger.com/atom/ns#' term='opensocial'/><title type='text'>Google Gadget and OpenSocial</title><content type='html'>&lt;p&gt;Opensocial API is an open set of APIs which can be used to access various social network applications. Currently, social network apps which support OpenSocial API are listed &lt;a href="http://code.google.com/apis/opensocial/gettingstarted.html" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Google Gadget:&lt;/strong&gt;&lt;br&gt;Official specification of Gadget server/container is here(&lt;a title="http://code.google.com/apis/gadgets/docs/spec.html" href="http://code.google.com/apis/gadgets/docs/spec.html"&gt;http://code.google.com/apis/gadgets/docs/spec.html&lt;/a&gt;). It includes abundant information about how gadget container handles gadget requests from clients. The basic idea is gadget container processes gadget .xml definition file and generates corresponding HTML+CSS+Javascript and then transferres the result to end users. Variety of functionalities gadget deveoper can utilize depends on gadget container. Different gadget containers may provide different set of features. However, some APIs are mandatory and must be supported by all compliant implementations. Javascript gadget specification is here(&lt;a title="http://code.google.com/apis/gadgets/docs/reference/" href="http://code.google.com/apis/gadgets/docs/reference/"&gt;http://code.google.com/apis/gadgets/docs/reference/&lt;/a&gt;). Gadget XML reference is here(&lt;a title="http://code.google.com/apis/gadgets/docs/reference.html" href="http://code.google.com/apis/gadgets/docs/reference.html"&gt;http://code.google.com/apis/gadgets/docs/reference.html&lt;/a&gt;). &lt;a href="http://code.google.com/apis/gadgets/docs/tools.html" target="_blank"&gt;This site&lt;/a&gt; contains many useful hints about how to develop and test Google Gadgets. &lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;There are two set of Gadget APIs:Legacy API and gadgets.* api(used by Open Social spec).&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;Gadget Host:&lt;/strong&gt;&lt;br&gt;If you don't have a web server to host the gadget XML file, &lt;strong&gt;Google Gadgets Editor&lt;/strong&gt; is a tool provided by Google which can be used to edit and host gadgets. You can test your gadgets in GGE withoug logging in Google. But you cannot save your gadgets without logging in. You can add Google Gadget Editor gadget to your iGoogle homepage by accessing &lt;a href="http://www.google.com/ig/adde?moduleurl=www.google.com/ig/modules/gge.xml" target="_blank"&gt;this site&lt;/a&gt;. It seems that only legacy gadget APIs are supported in preview mode by GGE. GGE just provides very simple functionalities. You can use it just as a hosting service which stores your gadget spec files. If you want more functionalities like version control, you can use Google Code Hosting(&lt;a title="http://code.google.com/hosting/" href="http://code.google.com/hosting/"&gt;http://code.google.com/hosting/&lt;/a&gt;) or other full-fledged hosting services.&amp;nbsp; &lt;a href="http://code.google.com/apis/gadgets/docs/tools.html#GGE" target="_blank"&gt;This site&lt;/a&gt; contains detailed information about how to use Google hosting services. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Legacy Gadget Container:&lt;/strong&gt;&lt;br&gt;Besides spec files, gadget container is necessary to run your gadgets. To test legacy Google Gadgets, you can GGE or iGoogle content directory. &lt;a href="http://code.google.com/apis/gadgets/docs/publish.html" target="_blank"&gt;Here&lt;/a&gt; contains instructions about how to publish your gadgets to iGoogle content directory. You can update your submitted gadgets using this &lt;a href="http://www.google.com/ig/aliasrequest" target="_blank"&gt;site&lt;/a&gt;. NOTE: iGoogle &lt;a href="http://www.google.com/ig/directory" target="_blank"&gt;content directory&lt;/a&gt; only applies to legacy gadgets. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Open Social Gadget container:&lt;/strong&gt;&lt;br&gt;To test new google gadgets(using gadgets.* API), you should use a certain container listed &lt;a href="http://code.google.com/apis/opensocial/gettingstarted.html" target="_blank"&gt;here&lt;/a&gt;. Note: two services from Google are in the list. However, to use them, you must sign up for sandbox access besides regular logging in. To sign up sandbox access of iGoogle, visit this site(&lt;a title="http://www.google.com/ig/sandbox" href="http://www.google.com/ig/sandbox"&gt;http://www.google.com/ig/sandbox&lt;/a&gt;). To sign up sandbox access of Orkut, visit &lt;a href="http://sandbox.orkut.com/" target="_blank"&gt;this site&lt;/a&gt;. These two services are still in beta phase and thus provide limited functionalities. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;br&gt;iGoogle Dev: &lt;a title="http://code.google.com/apis/igoogle/docs/igoogledevguide.html" href="http://code.google.com/apis/igoogle/docs/igoogledevguide.html"&gt;http://code.google.com/apis/igoogle/docs/igoogledevguide.html&lt;/a&gt;&lt;br&gt;Orkut Dev: &lt;a title="http://code.google.com/apis/orkut/docs/orkutdevguide.html" href="http://code.google.com/apis/orkut/docs/orkutdevguide.html"&gt;http://code.google.com/apis/orkut/docs/orkutdevguide.html&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4510056896337329176?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4510056896337329176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4510056896337329176' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4510056896337329176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4510056896337329176'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/google-gadget-and-opensocial.html' title='Google Gadget and OpenSocial'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5141848037304361160</id><published>2008-07-04T15:09:00.001-04:00</published><updated>2008-07-04T15:09:51.670-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='ringside'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Interaction between Facebook and Ringside</title><content type='html'>&lt;p&gt;&lt;strong&gt;(1) Can Ringside use applications of Facebook?&lt;/strong&gt;&lt;br&gt;Generally not. To use applications of Facebook, one of the two requirements must be satisfied:&lt;br&gt;&amp;lt;1&amp;gt; You know the callback URL of the application.&lt;br&gt;If you know the callback URL, you can create a new application on Ringside serve which points to the same callback URL. However, as far as I know, you have no way to figure out the callback URLs of Facebook applications developed by others. &lt;br&gt;&amp;lt;2&amp;gt; Facebook exposes a "proxy URL".&lt;br&gt;In this case, Facebook does not need to expose callback URL of an application. Instead, Facebook acts as a Proxy server and sits between Ringside server and your app. Then you points "Callback URL" of your Ringside app at the Facebook "proxy URL". So the communication style is:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; your Ringside app &amp;lt;=&amp;gt; Ringside server &amp;lt;=&amp;gt; Facebook &amp;lt;=&amp;gt; Facebook App.&lt;br&gt;Facebook is a relay station which connects Ringside server with Facebook applications. However, as far as I know, currently Facebook does not support the "proxy URL".&lt;/p&gt; &lt;p&gt;&lt;strong&gt;(2) Can Facebook use applications of Ringside?&lt;/strong&gt;&lt;br&gt;Yes. Ringside supports the second method described above.&lt;br&gt;If you has built an application on a Ringside server and you want to that application to be accessed in Facebook, you should:&lt;br&gt;[*] add a new application in your Facebook account;&lt;br&gt;[*] copy configuration information of your Ringside app to the newly created app in Facebook.&lt;br&gt;[*] set Callback URL(in Facebook setting) to point to your Ringside app. Note: there is a specific format of "proxy URL" of apps in Ringside: http://ringside_server:port/trust.php/facebook/canvas_path. You should replace &lt;em&gt;canvas_path&lt;/em&gt; with your real value. It should be the canvas path you set in Ringside server rather than Facebook. &lt;br&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Note&lt;/font&gt;&lt;/strong&gt; that that app is run inside of backend Ringside server instead of Facebook. So the app generates all output based on information stored on backend Ringside server. For example, if the app returns a list of your friends, you will see friend list of the profile you set up on Ringside server. In other words, you will not see your Facebook friend list.&lt;br&gt;&lt;strong&gt;Architecture:&lt;/strong&gt;&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SG51eyCSkgI/AAAAAAAAAPI/FMxP1PXS4Ow/s1600-h/draw2%5B16%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="80" alt="draw2" src="http://lh6.ggpht.com/Jenvor/SG51fO4nNyI/AAAAAAAAAPM/XJhGjyMa2Yo/draw2_thumb%5B14%5D.png?imgmax=800" width="339" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;&amp;lt;1&amp;gt; browser sends request to Facebook&lt;br&gt;&amp;lt;2&amp;gt; Facebook sends request to "Callback URL" (format is: http://ringside_server:port/trust.php/facebook/canvas_path)&lt;br&gt;&amp;lt;3&amp;gt; Ringside server sends request to your app server&lt;br&gt;&amp;lt;4&amp;gt; Your app makes calls to Ringside server and integrates response into output&lt;br&gt;&amp;lt;5&amp;gt; Your app returns final output to Ringside server&lt;br&gt;&amp;lt;6&amp;gt; Ringside server passes the output to Facebook&lt;br&gt;&amp;lt;7&amp;gt; Facebook returns response to client.&lt;br&gt;&lt;strong&gt;One issue&lt;/strong&gt; is: if response in step &amp;lt;5&amp;gt; contains FBML segment, who will render the FBML? Ringside server or Facebook? I guess Facebook renders FBML into HTML. In other words, Ringside server just acts as a pure proxy and it does not render inbound messages. Maybe I am wrong, I am not 100% sure about my guess.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;(3) More possibilities&lt;/strong&gt;&lt;br&gt;Actually, your app can makes use of all resources that you have privilege to access. No matter where you deploy your app, your app can makes API calls to Facebook, Ringside server and open social containers(e.g. Orkut, hi5...). &lt;br&gt;&lt;strong&gt;Architecture:&lt;/strong&gt;&lt;br&gt;&amp;nbsp;&lt;a href="http://lh4.ggpht.com/Jenvor/SG51fdtUjfI/AAAAAAAAAPQ/xmd5lkv4wHM/s1600-h/draw3%5B15%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="185" alt="draw3" src="http://lh6.ggpht.com/Jenvor/SG51f_n00hI/AAAAAAAAAPU/l0QzTrho6_Q/draw3_thumb%5B9%5D.png?imgmax=800" width="348" border="0"&gt;&lt;/a&gt;&amp;nbsp; &lt;br&gt;In this way, you can integrate different resources and produce better result. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5141848037304361160?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5141848037304361160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5141848037304361160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5141848037304361160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5141848037304361160'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/interaction-between-facebook-and.html' title='Interaction between Facebook and Ringside'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/Jenvor/SG51fO4nNyI/AAAAAAAAAPM/XJhGjyMa2Yo/s72-c/draw2_thumb%5B14%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4863165800252440006</id><published>2008-07-03T22:35:00.000-04:00</published><updated>2008-07-03T22:40:32.426-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Facebook Application Development and Concepts</title><content type='html'>&lt;p&gt;Developing a simple application for Facebook platform is not as easy as developing a "hello,world" application in C/C++ or Java etc. &lt;br&gt;&lt;a href="http://developers.facebook.com/step_by_step.php" target="_blank"&gt;Here&lt;/a&gt; is a step-by-step tutorial about how to build a Facebook app. It is exhaustive and I just supplement two cents.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Resources:&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;Description about the basic architecture:&lt;br&gt;&lt;a title="http://wiki.developers.facebook.com/index.php/Random_questions" href="http://wiki.developers.facebook.com/index.php/Random_questions"&gt;http://wiki.developers.facebook.com/index.php/Random_questions&lt;/a&gt;&amp;nbsp;&lt;br&gt;More resources about how to build Facebook Apps:&lt;br&gt;&lt;a title="http://www.merchantos.com/makebeta/facebook/facebook-php-tutorial/" href="http://www.merchantos.com/makebeta/facebook/facebook-php-tutorial/"&gt;http://www.merchantos.com/makebeta/facebook/facebook-php-tutorial/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;First, it is necessary to introduce the basic concepts. These concepts confused me once upon a time. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Profile Action&lt;/font&gt;&lt;br&gt;&lt;/strong&gt;When you browse profile of a user, you should see following layout:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/SG2NXK7HeVI/AAAAAAAAAOA/bpQj-gMdcf4/s1600-h/image3.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="307" alt="image" src="http://lh6.ggpht.com/Jenvor/SG2NXWCHIoI/AAAAAAAAAOE/DYQITAaHj1Q/image_thumb1.png?imgmax=800" width="217" border="0"&gt;&lt;/a&gt; &lt;br&gt;The entries within red box are called profile actions. One way to set profile action of your app is through app setting interface provided by Facebook. Following entry "Default Action FBML" should be displayed:&lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SG2NYPOAmiI/AAAAAAAAAOI/pOjnw86LL1w/s1600-h/image7.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="119" alt="image" src="http://lh6.ggpht.com/Jenvor/SG2NYsFanmI/AAAAAAAAAOM/mLJ2OuNQI9A/image_thumb3.png?imgmax=800" width="551" border="0"&gt;&lt;/a&gt; &lt;br&gt;You can make use of &lt;em&gt;fb:profile-action&lt;/em&gt; to set profile action. &lt;br&gt;Another way to set profile action is use API: &lt;a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML" target="_blank"&gt;Profile.setFBML&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Profile Box&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;On your profile page, there is a small box for every application you have added. This small box is called profile box which is demonstrated below.&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SG2NZJSmFnI/AAAAAAAAAOQ/JCopBQZ4vG4/s1600-h/image11.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="357" alt="image" src="http://lh6.ggpht.com/Jenvor/SG2NZraKZLI/AAAAAAAAAOU/J_GU50Ih-Sw/image_thumb5.png?imgmax=800" width="413" border="0"&gt;&lt;/a&gt; &lt;br&gt;You can set content of profile box of your app by accessing app setting page:&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SG2NcpWcwyI/AAAAAAAAAOY/sSbt9xG4Rmw/s1600-h/image15.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="113" alt="image" src="http://lh5.ggpht.com/Jenvor/SG2NcxDwL6I/AAAAAAAAAOc/J21Osbpe5A4/image_thumb7.png?imgmax=800" width="505" border="0"&gt;&lt;/a&gt; &lt;br&gt;Moreover, you can set profile box by using API: &lt;a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML" target="_blank"&gt;Profile.setFBML&lt;/a&gt;.&lt;br&gt;Note: &lt;a href="http://wiki.developers.facebook.com/index.php/Profile.setFBML" target="_blank"&gt;Profile.setFBML&lt;/a&gt; can be used to set both profile box and profile action. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Cache in profile action and profile box:&lt;/font&gt;&lt;br&gt;&lt;/strong&gt;Setting of profile action and profile box is cached in Facebook server. See architecture &lt;a href="http://wiki.developers.facebook.com/index.php/Random_questions#Basic_Application_Architecture" target="_blank"&gt;here&lt;/a&gt;. &lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SG2NdDTM8AI/AAAAAAAAAOg/QIWP18M3ZLI/s1600-h/Clipboard042%5B3%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="85" alt="Clipboard042" src="http://lh4.ggpht.com/Jenvor/SG2NdvOsVCI/AAAAAAAAAOk/Tv3TOA0mJFk/Clipboard042_thumb%5B1%5D.png?imgmax=800" width="301" border="0"&gt;&lt;/a&gt; &lt;br&gt;&amp;lt;1&amp;gt; A user sends requests to Facebook through profile action or profile box.&lt;br&gt;&amp;lt;2&amp;gt; Facebook immediately returns cached response to the user. In other words, Facebook does not communicate with your app server instantly. The cache is for per user per application.&lt;br&gt;Update of profile action/box is done asynchronously. Usually, when a user requests your canvas page, profile action/box will be updated if related code is contained in your canvas page. &lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;Canvas Page&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;When a user click your app in the left navigation bar, your app will be put into canvas page which is shown below:&lt;br&gt;&amp;nbsp;&lt;a href="http://lh5.ggpht.com/Jenvor/SG2NeMSb27I/AAAAAAAAAOo/EXWI5pBZ6ks/s1600-h/image24.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="235" alt="image" src="http://lh5.ggpht.com/Jenvor/SG2Ne7jEN_I/AAAAAAAAAOs/k48zt26Hhes/image_thumb12.png?imgmax=800" width="644" border="0"&gt;&lt;/a&gt; &lt;br&gt;Facebook retrieves content of the page and renders it in canvas page. By setting Canvas Page URL, you tell Facebook that your app should be accessed through the specific URL. By setting "Callback URL", you tell Facebook where content should be retrieved. Facebook platform is like a proxy. When a user uses your app by accessing "Canvas Page URL", Facebook determines the true URL that should be visited. Then Facebook sends request to the URL and renders response in Canvas Page. &lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SG2NfMW-OgI/AAAAAAAAAOw/hHNfpCzHm8U/s1600-h/image29.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="117" alt="image" src="http://lh5.ggpht.com/Jenvor/SG2NfVACNKI/AAAAAAAAAO0/xG1bdUCtQjk/image_thumb15.png?imgmax=800" width="509" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;How does Facebook handle your app in canvas page?&lt;/strong&gt;&lt;br&gt;See &lt;a href="http://wiki.developers.facebook.com/index.php/Random_questions#Basic_Application_Architecture" target="_blank"&gt;here&lt;/a&gt;. I briefly describe the procedure:&lt;br&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SG2NhQdp_1I/AAAAAAAAAO4/8pafRoWwp0U/s1600-h/test3%5B1%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="67" alt="test3" src="http://lh5.ggpht.com/Jenvor/SG2Nj-VEMBI/AAAAAAAAAO8/2xn8B95kdhs/test3_thumb%5B1%5D.png?imgmax=800" width="315" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;&amp;lt;1&amp;gt; browser sends request to facebook platform.&lt;br&gt;&amp;lt;2&amp;gt; Facebook platform sends requests to your app server&lt;br&gt;&amp;lt;3&amp;gt; Your app makes API calls to Facebook and integrates response into output&lt;br&gt;&amp;lt;4&amp;gt; Your app returns output(html segment with or without FBML)&lt;br&gt;&amp;lt;5&amp;gt; After facebook gets response from your app server, Facebook renders FBML to HTML and displays result in client browser. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Add a new app&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;After you add &lt;em&gt;developer&lt;/em&gt; application into your facebook account, you should be able to create your own applications. There are many options you can set to customize your Facebook app, the interface looks like this:&lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SG2Nl29BU-I/AAAAAAAAAPA/P2TspgoXrPY/s1600-h/image14.png"&gt;&lt;img style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" height="480" alt="image" src="http://lh3.ggpht.com/Jenvor/SG2NngzH1fI/AAAAAAAAAPE/WGxdZ4Pinz8/image_thumb10.png?imgmax=800" width="511" border="0"&gt;&lt;/a&gt; &lt;br&gt;And this site contains detailed information about almost every field:&lt;br&gt;&lt;a title="http://www.marketing-ninja.com/facebook-app/starting-your-first-facebook-app-demystifying-application-form-field-by-field/" href="http://www.marketing-ninja.com/facebook-app/starting-your-first-facebook-app-demystifying-application-form-field-by-field/"&gt;http://www.marketing-ninja.com/facebook-app/starting-your-first-facebook-app-demystifying-application-form-field-by-field/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;You should have a server which will host your Facebook app. If you user Apache http server, you need to configure the server so that when a directory(not a file) is requested &lt;em&gt;index.php&lt;/em&gt; will be returned(if it exists). &lt;br&gt;In my Apache httpd server, related configuration is like this:&lt;/p&gt;&lt;pre&gt;&amp;lt;IfModule dir_module&amp;gt;&lt;br&gt;    DirectoryIndex index.html &lt;font color="#0000ff"&gt;index.php&lt;br&gt;&lt;/font&gt;&amp;lt;/IfModule&amp;gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4863165800252440006?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4863165800252440006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4863165800252440006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4863165800252440006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4863165800252440006'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/facebook-application-development-and.html' title='Facebook Application Development and Concepts'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/Jenvor/SG2NXWCHIoI/AAAAAAAAAOE/DYQITAaHj1Q/s72-c/image_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-853954136748552568</id><published>2008-07-02T18:03:00.000-04:00</published><updated>2008-07-02T18:04:20.466-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><category scheme='http://www.blogger.com/atom/ns#' term='ringside'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Ringside application development</title><content type='html'> &lt;style&gt;
.mylink{
/* text-decoration: none; */
color: blue;
font-size: 1.2em;
}
&lt;/style&gt;  &lt;h2 align="center"&gt;Table of Content&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;a class="mylink" href="#rsdoes"&gt;What Ringside server can do?&lt;/a&gt;  &lt;li&gt;&lt;a class="mylink" href="#rsclient1"&gt;Client app development&lt;/a&gt;  &lt;ul&gt; &lt;li&gt;&lt;a class="mylink" href="#rsclient1"&gt;How to add and set up a new app &lt;/a&gt; &lt;li&gt;&lt;a class="mylink" href="#rsclient2"&gt;Develop client apps in PHP&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;a class="mylink" href="#rsserver1"&gt;Ringside server extension development&lt;/a&gt;  &lt;ul&gt; &lt;li&gt;&lt;a class="mylink" href="#rsserver1"&gt;API extension (add more APIs you like)&lt;/a&gt;  &lt;li&gt;&lt;a class="mylink" href="#rsserver2"&gt;Tag extension (customize your own tags)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;Ringside Social Application Server seems a promising project. However, because it is still in beta development, online documents are not well organized. A better directory layout may help a lot. After reading the documents and trying Ringside server myself, I got some experience which is shared in this post. &lt;h3&gt;&lt;a name="rsdoes"&gt;What Ringside server can do?&lt;/a&gt;&lt;/h3&gt;(1) &lt;strong&gt;Open Social container&lt;/strong&gt;.&lt;br&gt;It means all open social applications can be run on Ringside server. Of course, the open social applications should not use extensions provided a specific container( e.g. iGoogle, Orkut ) if you want these apps to run on Ringside server. &lt;br&gt;Note: Gadgets in &lt;a href="http://www.google.com/ig/directory" target="_blank"&gt;Google content directory&lt;/a&gt;(repository of traditional gadgets) can not be used on Ringside server because traditional Gadget API is different from new Gadget spec used by Open Social API.&lt;br&gt;(2) &lt;strong&gt;Facebook platform mock&lt;br&gt;&lt;/strong&gt;It supports FBML and Facebook API and adds some extensions, which means you can use the same function names and markups of Facebook to write your Ringside apps. &lt;br&gt;(3) &lt;strong&gt;Extensibility&lt;/strong&gt;&lt;br&gt;Because Ringside server is open source, users can customize and extend Ringside server in the way they wish. For example, users can add their new APIs and extend XML tags to provide customized tags.  &lt;p&gt; &lt;h3&gt;&lt;a name="rsclient1"&gt;How to add and set up a new app?&lt;/a&gt;&lt;/h3&gt;Add a new app:&lt;br&gt;First click "Developer" tab, and in the main panel click "Create a New Application", following picture should be displayed:&lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SGv7YezBAgI/AAAAAAAAANw/jazW3b3io9Y/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="384" alt="image" src="http://lh6.ggpht.com/Jenvor/SGv7YVKRwVI/AAAAAAAAAN0/bHu2A_W7gwk/image_thumb%5B1%5D.png?imgmax=800" width="605" border="0"&gt;&lt;/a&gt; &lt;br&gt;When you create a new application in Ringside, the procedure is well similar to that of Facebook. The configuration options are almost the same as well. Look at below picture:&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SGv7Yu95wCI/AAAAAAAAAN4/tVXOlOsj4UY/s1600-h/image8.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="629" alt="image" src="http://lh3.ggpht.com/Jenvor/SGv7Y-I0ycI/AAAAAAAAAN8/iCKxW8Lf-0s/image_thumb4.png?imgmax=800" width="698" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;One big difference is highlighted in the picture. In Facebook, you can just choose your app type between "Use FBML" and "Use IFrame". However, in Ringside server, one more option("Use Open Social") is supported. The key thing you should configure is "Callback URL" which points to the location of your application. For option "Canvas URL", you just need to specify a unique name and you must not specify the full-path URL. Prefix is implicit which is &lt;em&gt;&lt;strong&gt;http://ringside_server_domain:port/canvas.php/&lt;/strong&gt;&lt;/em&gt;. So if you specify "&lt;em&gt;myapp&lt;/em&gt;" as your "Canvas URL", the URL to access your app becomes &lt;em&gt;&lt;strong&gt;&lt;a href="http://ringside_server_domain:port/canvas.php/myapp"&gt;http://ringside_server_domain:port/canvas.php/myapp&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;.&lt;br&gt;&lt;strong&gt;&lt;font color="#ff0606" size="3"&gt;Note!!!&lt;/font&gt;&lt;/strong&gt;&lt;font color="#ff8040"&gt; &lt;font size="3"&gt;W&lt;/font&gt;&lt;/font&gt;&lt;font color="#ff6f28" size="3"&gt;hen you set "Callback URL", you had better not use loopback domain or ip(e.g. localhost, 127.0.0.1) as host. If type of your app is "Use FBML", it may work well. In this mode, the output content is fully contained in the response. However, if type of your app is "Use IFrame", your app may not work. In this mode, a &lt;em&gt;frame&lt;/em&gt; element is embedded in returned html and &lt;em&gt;src&lt;/em&gt; attribute is set to point to the "Callback URL". As a result, the browser will send requests to its local host (the host a user is using to try your app) instead of the server which hosts your app. After you deploy and publish the app, using loopback address will definitely cause problems. To make your app work both in FBML mode and IFrame mode, loopback address should not be used!!!&lt;/font&gt;  &lt;p&gt;&lt;/p&gt; &lt;p&gt; &lt;h3&gt;&lt;a name="rsclient2"&gt;Develop your own Ringside applications in PHP&lt;/a&gt;&lt;/h3&gt;See instructions &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Writing+Hello+World" target="_blank"&gt;here&lt;/a&gt;. After you get PHP library, generally you need to modify your &lt;em&gt;php.ini&lt;/em&gt; and append path of the library to variable &lt;em&gt;include_path&lt;/em&gt; so that PHP interpreter knows where to look for Ringside PHP library.&lt;br&gt;You applications do not need to be hosted on the same host as Ringside server. Ringside provides a PHP client library which can be used to ease PHP development. Ringside PHP client library is based on Facebook PHP client library. But Ringside wraps the code in original Facebook PHP client library. In original Facebook PHP client library, the rest server which you send requests to is hard-coded in the source code as "&lt;a href="http://www.facebook.com"&gt;http://www.facebook.com&lt;/a&gt;". There is a class in Ringside library called "&lt;em&gt;RingsideApiClients&lt;/em&gt;" which is a subclass of class "Facebook" and overwrites most of the inherited functions. Besides, Ringside adds some extra APIs which are mainly contained in class "&lt;em&gt;RingsideApiClientsRest&lt;/em&gt;"(It is a subclass of class "&lt;em&gt;FacebookRestClient&lt;/em&gt;"). &lt;br&gt;So, you should use class "&lt;em&gt;RingsideApiClients&lt;/em&gt;" to send requests to backend Ringside server. One thing your must do is configure the Ringside server URL so that your app knows where requests should be sent. There are two ways that I know:&lt;br&gt;(1) When you create an instance of &lt;em&gt;RingsideApiClients&lt;/em&gt;, you can send weburl, serverurl and socialurl as parameters of contructor.&lt;br&gt;Prototype of the constructor is :&lt;br&gt;&lt;code&gt;public function __construct($api_key, $secret, $webUrl = null, $serverUrl = null, $socialUrl = null, $client = null ).&lt;/code&gt;&lt;br&gt;(2) Change static variable in class &lt;em&gt;RingsideApiClientsConfig&lt;/em&gt;.&lt;br&gt;Sample usage:&lt;br&gt;&lt;pre&gt;RingsideApiClientsConfig::$webUrl= ringside_web_url;&lt;br&gt;RingsideApiClientsConfig::$serverUrl = ringside_server_url;&lt;br&gt;RingsideApiClientsConfig::$socialUrl = ringside_social_url;&lt;/pre&gt;
&lt;p&gt;
&lt;h3&gt;&lt;a name="rsserver1"&gt;Extend API provided by Ringside Server&lt;/a&gt;&lt;/h3&gt;Good resource &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Getting+Started+Writing+APIs" target="_blank"&gt;(1)&lt;/a&gt;, &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Customizing+with+new+APIs" target="_blank"&gt;(2)&lt;/a&gt;. 
&lt;p&gt;
&lt;h3&gt;&lt;a name="rsserver2"&gt;Add your own tags to Ringside server&lt;/a&gt;&lt;/h3&gt;Good resources &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Getting+Started+Writing+TAGs" target="_blank"&gt;(1)&lt;/a&gt;, &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Customizing+with+my+own+TAGs" target="_blank"&gt;(2)&lt;/a&gt;.   &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-853954136748552568?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/853954136748552568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=853954136748552568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/853954136748552568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/853954136748552568'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/ringside-application-development.html' title='Ringside application development'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/Jenvor/SGv7YVKRwVI/AAAAAAAAAN0/bHu2A_W7gwk/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1316006389043772417</id><published>2008-07-01T17:14:00.000-04:00</published><updated>2008-07-01T17:15:24.170-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='ringside'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='socialnetwork'/><title type='text'>Ringside Networks Social Application Server on Linux</title><content type='html'>&lt;p&gt;&lt;br&gt;This post is based on official documents from Ringside, and describes steps to set up Ringside Networks Social Application Server.&lt;br&gt;&lt;strong&gt;(1) Download&lt;/strong&gt;&lt;br&gt;First, download the app server from &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Getting+Started+with+the+installers" target="_blank"&gt;here&lt;/a&gt;. In the distributed package, all dependent packages/libraries are included. Main additional components include: Apache2, PHP5 (core package and some extensions), Mysql and some unix/linux tools(e.g. curl, tidy and their libraries). So size of the whole package is sort of big. But it is an all-in-one package so that you can easily make it work without much configuration. Installation directory structure is explained &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Installation+Directory+Structure" target="_blank"&gt;here&lt;/a&gt;.&lt;br&gt;If you don't want the all-in-one package, check instructions &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Advanced+Developer+Setup" target="_blank"&gt;here&lt;/a&gt; to individually set up your environment.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;(2) Install&lt;/strong&gt;&lt;br&gt;A GUI installation wizard is provided. You can get instructions &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Getting+Started+with+the+installers" target="_blank"&gt;here&lt;/a&gt;. The process is easy.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;(3) Config&lt;/strong&gt;&lt;br&gt;You can change various apache setting by modifying following files:&lt;br&gt;(*)&lt;em&gt;%RNAS_ROOT%/apps/phpmyadmin/conf/phpmyadmin.conf&lt;/em&gt;&lt;br&gt;//This conf file is related to using of &lt;em&gt;phpmyadmin&lt;/em&gt;. By default, users can only access &lt;em&gt;phpmyadmin&lt;/em&gt; from IP &lt;em&gt;127.0.0.1&lt;/em&gt;. You can modify it&lt;br&gt;//if you want to use &lt;em&gt;phpmyadmin&lt;/em&gt; from remote client.&lt;br&gt;(*)&lt;em&gt;%RNAS_ROOT%/apps/ringside/conf/ringside.conf&lt;br&gt;//&lt;/em&gt;ringside related conf. It sets where the document root is... Generally, this file should not be modified.&lt;br&gt;(*)&lt;em&gt;%RNAS_ROOT%/apache2/conf/httpd.conf&lt;br&gt;&lt;/em&gt;//General apache http server configuration is in this file. If you want to change the port, set it here. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;(4) Run&lt;/strong&gt;&lt;br&gt;Let me assume you installed Ringside Networks Application Server into directory %&lt;em&gt;RNAS_ROOT%&lt;/em&gt;. Under directory &lt;em&gt;%RNAS_ROOT%&lt;/em&gt;, you should see a script called "&lt;em&gt;ctlscript.sh&lt;/em&gt;" which can be used to start/stop/restart server components. Sample commands are shown below:&lt;br&gt;&lt;em&gt;./ctlscript.sh start&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/em&gt;//start both apache and mysql&lt;br&gt;&lt;em&gt;./ctlscript.sh stop mysql&lt;/em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //stop mysql&lt;br&gt;&lt;em&gt;./ctlscript.sh status apache&lt;/em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //get status of apache server.&lt;br&gt;Official document is &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Starting+and+Stopping+Ringside+Servers" target="_blank"&gt;here&lt;/a&gt; which has more information.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;(5) Setup/Initialization&lt;/strong&gt;&lt;br&gt;First, you need to access &lt;a href="http://your_ip_or_domain:port/setup.php"&gt;http://your_ip_or_domain:port/setup.php&lt;/a&gt;. Default port is 8080. Then the server will carry out some setup work. For example, a database called &lt;em&gt;ringside&lt;/em&gt; is created... &lt;br&gt;You should see following page:&lt;br&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SGqeak-193I/AAAAAAAAANo/-jKnzG3weFc/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="484" alt="image" src="http://lh3.ggpht.com/Jenvor/SGqea6XduJI/AAAAAAAAANs/14_XWpVvTww/image_thumb%5B1%5D.png?imgmax=800" width="435" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;(6) Test/Using&lt;/strong&gt;&lt;br&gt;Main page: &lt;a href="http://your_ip_or_domain:port/phpmyadmin"&gt;http://your_ip_or_domain:port&lt;/a&gt;&lt;br&gt;Phpmyadmin access: &lt;a href="http://your_ip_or_domain:port/phpmyadmin"&gt;http://your_ip_or_domain:port/phpmyadmin&lt;/a&gt;. &lt;br&gt;Login: &lt;a href="http://your_ip_or_domain:port/login.php"&gt;http://your_ip_or_domain:port/login.php&lt;/a&gt;. When you run initial setup in step (5), a user is automatically generated for you. See content in the green box in last picture. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;(7) upgrades&lt;/strong&gt;&lt;br&gt;[*] Upgrade via PEAR:&lt;br&gt;You can update Ringside source via PEAR. Instructions are described &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Installation+and+Update+with+Pear" target="_blank"&gt;here&lt;/a&gt;.&lt;br&gt;[*] Check out latest code:&lt;br&gt;You can checkout latest Ringside code and build your own development/deployment environment. You should install the all-in-one package first. By following instructures &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Develop+and+Run+from+SVN+checkout" target="_blank"&gt;here&lt;/a&gt;, you substitute new version of Ringside for the original one which is included in the all-in-one package. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;(8) Remove&lt;/strong&gt;&lt;br&gt;Use executable &lt;em&gt;uninstall. &lt;/em&gt;Check instructions &lt;a href="http://wiki.ringsidenetworks.org/display/ringside/Installer+Removal" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1316006389043772417?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1316006389043772417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1316006389043772417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1316006389043772417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1316006389043772417'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/07/ringside-networks-social-application.html' title='Ringside Networks Social Application Server on Linux'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/Jenvor/SGqea6XduJI/AAAAAAAAANs/14_XWpVvTww/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-7815026896961475616</id><published>2008-06-19T23:30:00.000-04:00</published><updated>2008-06-19T23:57:16.009-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>Client side techniques</title><content type='html'>Namespace mimic in Javascript (similar to technique used by YUI): &lt;pre&gt;namespace:   function(   sNameSpace, obj   )   {  
    if   (!sNameSpace   ||   !sNameSpace.length)   {  
        return   null;  
    }  
    var   levels   =   sNameSpace.split(".");  
    var   currentNS   =   CGL;  
    //   CGL   is   implied,   so   it   is   ignored   if   it   is   included  
    for   (var   i=(levels[0]   ==   "CGL")   ?   1   :   0;   i&amp;lt;levels.length;   ++i)   { 
        if( arguments.length == 2 &amp;amp;&amp;amp; i == levels.length - 1)
	    currentNS[levels[i]]   =   obj;
	else
	    currentNS[levels[i]]   =   currentNS[levels[i]]   ||   {};  
	currentNS   =   currentNS[levels[i]];  
    }
    return   currentNS;  
}&lt;/pre&gt;By default, following namespaces are supported: &lt;br&gt;&lt;strong&gt;CGL.mashup.resourcetype:&lt;/strong&gt;&lt;br&gt;This object maintains resource types we support. Currently, text, image and video are supported.&lt;br&gt;&lt;strong&gt;CGL.mashup.addr:&lt;/strong&gt;&lt;br&gt;This object maintains base path for our applications.&lt;br&gt;&lt;strong&gt;CGL.mashup.sites:&lt;br&gt;&lt;/strong&gt;This object maintains all backend sites we support. Currently, Youtube and Flickr are supported.&lt;br&gt;&lt;strong&gt;CGL.mashup.log:&lt;/strong&gt;&lt;br&gt;This object maintains request history so that in the future we can reinvoke a certain old request.&lt;br&gt;&lt;strong&gt;CGL.mashup.init:&lt;/strong&gt;&lt;br&gt;All initialization work is done here.&lt;br&gt;&lt;strong&gt;CGL.mashup.urlbuilder:&lt;/strong&gt;&lt;br&gt;This object provides functions which can ease construction of request URL to access various resources.&lt;br&gt;&lt;strong&gt;CGL.mashup.service:&lt;/strong&gt;&lt;br&gt;This object provides functions which send various requests (e.g. get user information) to server side.&lt;br&gt;&lt;strong&gt;CGL.mashup.helper:&lt;/strong&gt;&lt;br&gt;This object includes some utility functions.&lt;br&gt;&lt;strong&gt;GL.mashup.htmlformatter:&lt;/strong&gt;&lt;br&gt;This object contains functions that can be used to display response in a specific format .&lt;br&gt;&lt;strong&gt;CGL.mashup.jsonresponse:&lt;/strong&gt;&lt;br&gt;This object handls JSON responses from server and parses the content.&lt;br&gt;&lt;strong&gt;CGL.mashup.opmapper:&lt;/strong&gt;&lt;br&gt;This object maps operation names to concrete function implementations. Callback can be specified as well.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-7815026896961475616?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/7815026896961475616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=7815026896961475616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7815026896961475616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7815026896961475616'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/06/client-side-techniques.html' title='Client side techniques'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-499211054321817674</id><published>2008-06-19T22:21:00.001-04:00</published><updated>2008-06-19T23:52:15.701-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openid'/><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>Web2.0 Integration Summary</title><content type='html'>&lt;p&gt;The server-side architecture is described here:&lt;br&gt;&lt;a title="http://zhenhua-guo.blogspot.com/2008/05/mashup-architecture.html" href="http://zhenhua-guo.blogspot.com/2008/05/mashup-architecture.html"&gt;http://zhenhua-guo.blogspot.com/2008/05/mashup-architecture.html&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Authentication: OpenID which is described here (&lt;a title="http://zhenhua-guo.blogspot.com/2008/05/openid.html" href="http://zhenhua-guo.blogspot.com/2008/05/openid.html"&gt;http://zhenhua-guo.blogspot.com/2008/05/openid.html&lt;/a&gt;).&lt;br&gt;Authorization: Although &lt;a href="http://zhenhua-guo.blogspot.com/2008/05/oauth.html" target="_blank"&gt;OAuth&lt;/a&gt; seems promising, it has not been supported by large web 2.0 applications. So, I make use of various authorization mechanisms of different applications.&lt;/p&gt; &lt;p&gt;RESTful web services are used instead of SOAP-based web services. URL pattern used to access various resources is described here(&lt;a title="http://zhenhua-guo.blogspot.com/2008/05/url-pattern-in-mashup.html" href="http://zhenhua-guo.blogspot.com/2008/05/url-pattern-in-mashup.html"&gt;http://zhenhua-guo.blogspot.com/2008/05/url-pattern-in-mashup.html&lt;/a&gt;). &lt;/p&gt; &lt;p&gt;At client side, Ajax is used to enhance user experience. Client side functionality is described here(&lt;a title="http://zhenhua-guo.blogspot.com/2008/06/client-side-techniques.html" href="http://zhenhua-guo.blogspot.com/2008/06/client-side-techniques.html"&gt;http://zhenhua-guo.blogspot.com/2008/06/client-side-techniques.html&lt;/a&gt;).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-499211054321817674?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/499211054321817674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=499211054321817674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/499211054321817674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/499211054321817674'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/06/web20-integration-summary.html' title='Web2.0 Integration Summary'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-8236483050575623704</id><published>2008-05-25T23:32:00.001-04:00</published><updated>2008-05-25T23:32:57.461-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openid'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>OAuth</title><content type='html'>&lt;p&gt;In my mashup framework, OpenID is used to do authentication which provides a way to make sure the users are really who they claim to be. The mechanism is that the users prove that they own/control the OpenID they provides. &lt;a href="http://zhenhua-guo.blogspot.com/2008/05/openid.html" target="_blank"&gt;Here&lt;/a&gt; is what I wrote about OpenID.&lt;/p&gt; &lt;p&gt;However, OpenID just solves authentication. After users are authenticated, OpenID does not specify how the third-party apps access the protected data on service providers. And the requirement that third-party apps can access protected data stored on service providers on behalf of users is not imaginary, but real. In my mashup framework, I need to manipulate data on behalf of users which needs authorization besides authentication. Youtube and Flickr both provide ways for third-party integration. They provide similar authorization procedures (I am using this mechanism right now) which fundamentally match principles of &lt;a href="http://oauth.net/" target="_blank"&gt;OAuth&lt;/a&gt; &lt;a href="http://oauth.net/core/1.0/" target="_blank"&gt;specification&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;OAuth provides a way for users to grant access to third-party apps. The procedure is pretty much the same as OpenID. What is different are parameters in requests and responses. OAuth is an independent specification which means it is not an extension of OpenID. But, in my opinion, it may be better to combine these two together because they are similar to each other. In this way, user experience can be improved because authentication and authorization can be done in the same pass instead of two. However, some sites may just support authentication service or authorization service (in terms of support of open standards like OpenID, OAuth). So how to combine them together without losing flexibility is an issue. &lt;/p&gt; &lt;p&gt;One problem that OAuth does not address is fine-grained access control. I think this issue must be addressed in the long run. However, nowadays, the goal is too far to reach. Actually, current version of OAuth is not supported widely.&lt;/p&gt; &lt;p&gt;&lt;a href="http://dataportability.org/" target="_blank"&gt;DataPortability&lt;/a&gt; is a new organization which aims to promote data portability. Of course, it includes OpenID and OAuth with respect to authentication and authorization data portability. I am not sure which ones will survive and stand out&amp;nbsp; eventually, but this is a good signal that data portability is being considered as a critical issue and I hope it will be addressed in the near future. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-8236483050575623704?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/8236483050575623704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=8236483050575623704' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/8236483050575623704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/8236483050575623704'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/oauth.html' title='OAuth'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6116521646081097887</id><published>2008-05-24T01:27:00.000-04:00</published><updated>2008-05-24T01:28:18.571-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='youtube'/><title type='text'>Authentication and Authorization in Mashup</title><content type='html'>&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;br&gt;Currently, I don't build my own independent user authentication system. I make use of &lt;a href="http://openid.net/" target="_blank"&gt;OpenID&lt;/a&gt; to utilize existing authentication systems, such as Yahoo Flickr, Google Blogspot, LiveJournal... You can check whether you have already had an OpenID &lt;a href="http://openid.net/get/" target="_blank"&gt;here&lt;/a&gt;. I wrote a simple &lt;a href="http://zhenhua-guo.blogspot.com/2008/05/openid.html" target="_blank"&gt;introduction&lt;/a&gt;. In essence, we delegate the task to existing authentication systems.&lt;br&gt;After a user is authenticated successfully, OpenID is used to track the user. Servlet session technique is used to associate session id and user information.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt;&lt;br&gt;Currently, I don't ask end users for their usernames and passwords in existing services (e.g. youtube, flickr) because it requires deep trust of end users. The user id redirected to an authorization web page hosted by the destination service(e.g. youtube). If the user accepts the request, then the user browser will be redirected to my mashup application. Generally, an auth token is appended to the URL which will be used in following requests. &lt;br&gt;Currently, for every backend service, I request the user to authorize the most powerful privilege level. For example, if the service supports READ and WRITE permission control, my application will request WRITE permission. If the service supports READ, WRITE and DELETE permission control, my application will request DELETE permission. This is not always a good strategy. But because of diversity of permission control systems, I must choose the mechanism which can be used in every possible service. &lt;br&gt;Maybe in the future, I can come up with a better framework with fine-grained access control.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6116521646081097887?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6116521646081097887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6116521646081097887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6116521646081097887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6116521646081097887'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/authentication-and-authorization-in.html' title='Authentication and Authorization in Mashup'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4060965251227860733</id><published>2008-05-24T00:33:00.001-04:00</published><updated>2008-05-24T00:33:39.331-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>URL Pattern In Mashup</title><content type='html'>&lt;strong&gt;&lt;font size="3"&gt;URL Pattern&lt;/font&gt;&lt;/strong&gt;  &lt;table class="MsoTableGrid" style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse; mso-table-layout-alt: fixed; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0pt 5.4pt 0pt 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1"&gt; &lt;tbody&gt; &lt;tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 1"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;Note: All variables enclosed in ‘&lt;?xml:namespace prefix = st1 /&gt;&lt;st1:citation w:st="on"&gt;{’ and ‘}&lt;/st1:citation&gt;’ must be substituted with real values. &lt;br&gt;GET means HTTP GET request type and POST means HTTP POST type.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 2"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/users/&lt;st1:citation w:st="on"&gt;{userid}&lt;/st1:citation&gt;&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get information of a user.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 3"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/login&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Login the service.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 4"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/users/&lt;st1:citation w:st="on"&gt;{userid}&lt;/st1:citation&gt;/resources&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get all resources of the user.&lt;br&gt;POST:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add a new resource.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 5"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/users/&lt;st1:citation w:st="on"&gt;{userid}&lt;/st1:citation&gt;/resources/resourceid&lt;br&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/resources/resourceid&lt;br&gt;GET:&lt;br&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get information of a specific resource.&lt;br&gt;DELETE:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Delete the corresponding resource.&lt;br&gt;PUT: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Update the corresponding resource.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 6"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/resources/resourceid/comments&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get all comments of the resource.&lt;br&gt;POST:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add a new comment.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 7"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/resources/resourceid/rating&lt;br&gt;GET:&lt;br&gt;Get rating of the resource.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 8"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/tag/&lt;st1:citation w:st="on"&gt;{tag}&lt;/st1:citation&gt;?perpage=&lt;st1:citation w:st="on"&gt;{perpage}&lt;/st1:citation&gt;&amp;amp;page=&lt;st1:citation w:st="on"&gt;{page}&lt;/st1:citation&gt;&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get records by tag. Parameter &lt;i style="mso-bidi-font-style: normal"&gt;perpage&lt;/i&gt; indicates how many resources you want to retrieve.Parameter &lt;i style="mso-bidi-font-style: normal"&gt;page&lt;/i&gt; indicates which page you want to retrieve.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 9; mso-yfti-lastrow: yes"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 419.4pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="559"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;/cgl/feeds/api/&lt;st1:citation w:st="on"&gt;{category}&lt;/st1:citation&gt;/&lt;st1:citation w:st="on"&gt;{service}&lt;/st1:citation&gt;/statistics/&lt;st1:citation w:st="on"&gt;{standard}&lt;/st1:citation&gt;? perpage=&lt;st1:citation w:st="on"&gt;{perpage}&lt;/st1:citation&gt;&amp;amp;page=&lt;st1:citation w:st="on"&gt;{page}&lt;/st1:citation&gt;&lt;br&gt;GET:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get records by standards.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; E.g. most viewed, most recent…&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;&lt;font size="3"&gt;Example:&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: en-us; mso-fareast-language: zh-cn; mso-bidi-language: ar-sa"&gt;/cgl/feeds/api/videos/youtube/tag/soccer&lt;br&gt;get resources tagged as soccer.&lt;br&gt;/cgl/feeds/api/videos/youtube/statistics/most_viewed&lt;br&gt;get resources that are most viewed.&lt;br&gt;/cgl/feeds/api/pictures/flickr/users/testuser/resources&lt;br&gt;get resources belonging to user &lt;em&gt;testuser&lt;/em&gt;.&lt;/span&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4060965251227860733?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4060965251227860733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4060965251227860733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4060965251227860733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4060965251227860733'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/url-pattern-in-mashup.html' title='URL Pattern In Mashup'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-763527869152765302</id><published>2008-05-23T17:01:00.000-04:00</published><updated>2008-05-23T17:05:29.031-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='template'/><title type='text'>Javascript Templates</title><content type='html'>Javascript Templates(&lt;a title="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates" href="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates"&gt;http://code.google.com/p/trimpath/wiki/JavaScriptTemplates&lt;/a&gt;) is a sub project of project Trimpath. It is a client-side template engine whose functionality is similar to server-side Velocity and Smarty engines. It uses special markup syntax. Besides simple template matching and replacing, it also supports simple control flow, loop and variable declarations... Now I summarize the syntax:&lt;br&gt;&lt;strong&gt;Statements:&lt;/strong&gt;&lt;br&gt;(1) Variable Declaration&lt;br&gt; &lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;Syntax&lt;/td&gt; &lt;td valign="top" width="200"&gt;Example&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;{var variable}&lt;br&gt;{var variable = value}&lt;/td&gt; &lt;td valign="top" width="200"&gt;{var price}&lt;br&gt;{var price = 10}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Note: No ending ';' is needed.  &lt;p&gt;(2) Control Flow&lt;br&gt;&lt;/p&gt; &lt;table cellspacing="0" cellpadding="5" border="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top"&gt;Syntax&lt;/td&gt; &lt;td valign="top"&gt;Example:&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top"&gt;{if expression}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {elseif expression} ...&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {else} ...&lt;br&gt;{/if}&lt;/td&gt; &lt;td valign="top"&gt;{if price &amp;gt; 10}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {elseif price &amp;lt;20}...&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {else}...&lt;br&gt;{/if}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Note: No surrounding brackets are needed in test expression. No white space between first '{' and 'if'.  &lt;p&gt;(3) Loop&lt;br&gt;&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;Syntax&lt;/td&gt; &lt;td valign="top" width="200"&gt;Example&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="200"&gt;{for varariable in list}&lt;br&gt;&amp;nbsp;&amp;nbsp; statements go here&lt;br&gt;{/for}&lt;/td&gt; &lt;td valign="top" width="200"&gt;{for price in pricelist}&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ${alert(price)}&lt;br&gt;{/for}&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;(4) Expression&lt;br&gt;&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="509" border="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="253"&gt;Syntax&lt;/td&gt; &lt;td valign="top" width="254"&gt;Example&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="249"&gt;${expression}&lt;/td&gt; &lt;td valign="top" width="254"&gt;${car.brand}&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="247"&gt;${expression|modifier}&lt;/td&gt; &lt;td valign="top" width="254"&gt;${car.brand|capitalize}&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="245"&gt;${expression|modifier1|modifer2}&lt;/td&gt; &lt;td valign="top" width="254"&gt;${car.brand|default:"chevy"|capitalize}&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" width="245"&gt;...&lt;/td&gt; &lt;td valign="top" width="254"&gt;...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt; &lt;p&gt;Value of the expression will be returned.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;Statement &lt;em&gt;for( ; ; )&lt;/em&gt; is not supported.&lt;br&gt;These statements are parsed and processed by Javascript Template Library instead of javascript itself. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;More:&lt;/strong&gt;&lt;br&gt;(5) CDATA Text. Tag is &lt;em&gt;cdata&lt;/em&gt;.&lt;br&gt;CDATA Text will be ignored and will not be processed.&lt;br&gt;(6) In-line javascript block. Tag is &lt;em&gt;eval&lt;/em&gt;.&lt;br&gt;Multiple line javascript code can be put in a single block to evaluate.&lt;br&gt;(7) If you have multiple-line js code, you can use &lt;em&gt;minify&lt;/em&gt; to tell processor to treat them as a whole.&lt;br&gt;For example:&lt;br&gt;&lt;em&gt;&amp;lt;input type="button" onClick="{minify} Javascript event&lt;br&gt;handling code...&lt;br&gt;{/minify}"&amp;gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Note: &lt;em&gt;eval&lt;/em&gt; and &lt;em&gt;minify&lt;/em&gt; are different althought they are sort of similar.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;How to process templates?&lt;br&gt;&lt;/strong&gt;API: &lt;a title="http://code.google.com/p/trimpath/wiki/JavaScriptTemplateAPI" href="http://code.google.com/p/trimpath/wiki/JavaScriptTemplateAPI"&gt;&lt;strong&gt;http://code.google.com/p/trimpath/wiki/JavaScriptTemplateAPI&lt;/strong&gt;&lt;/a&gt;.&lt;br&gt;Commonly used functions:&lt;br&gt;(1) &lt;a href="http://code.google.com/p/trimpath/wiki/TrimPath"&gt;TrimPath&lt;/a&gt;.parseDOMTemplate ( elementId, contextObject )&lt;br&gt;This function retrieves content of the element corresponding to the first parameter. It should be a &lt;em&gt;textarea&lt;/em&gt; element and its should be hidden. &lt;br&gt;The second parameter is a context object and it will be "merged" with the template. For example, if a template refers to &lt;em&gt;${car}&lt;/em&gt;, then the processor tries to access &lt;em&gt;contextObject.car&lt;/em&gt;. &lt;br&gt;(2) &lt;a href="http://code.google.com/p/trimpath/wiki/TrimPath"&gt;TrimPath&lt;/a&gt;.parseTemplate ( templateContentStr )&lt;br&gt;This function accepts a &lt;em&gt;string&lt;/em&gt; as template instead of a dom element id. &lt;br&gt;You can parse a string template in this way:&lt;br&gt;TrimPath.parseTemplate( &lt;em&gt;stringvariable &lt;/em&gt;).process( &lt;em&gt;contextObject&lt;/em&gt; ).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Variable Resolvation Precedence:&lt;/strong&gt;&lt;br&gt;There are three kinds of scopes:&lt;br&gt;(1) Processor scope: it consists of all template statements.&lt;br&gt;(2) Context object scope: All properties of the context object.&lt;br&gt;(3) Local scope: local variables whic are not defined in template.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Case 1:&lt;/strong&gt; In template expression and &lt;em&gt;{eval}&lt;/em&gt;:&lt;br&gt;Processor scope is checked first, then context object is checked. At alst, local scope is checked.&lt;br&gt;For example:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;em&gt;var data={car : "chevy"};&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var str = '${alert(car)}';&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; str.process(data);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //alert "chevy"&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var str2 = '{var car = "ford"} ${alert(car)}''&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; str2.process(data);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //alert "ford"&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var car = "toyota";&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var str3 = '${alert(car)}';&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; str3.process();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //alert "toyota"&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Case 2:&lt;/strong&gt; All variables defined in template do not have effect in local scope.&lt;br&gt;For example:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var str = '{var car="chevy"}${alert(car)}';&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; str.process(data);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //alert "chevy"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; alert(car);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //variable 'car' is not defined.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-763527869152765302?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/763527869152765302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=763527869152765302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/763527869152765302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/763527869152765302'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/javascript-templates.html' title='Javascript Templates'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2523100765197608314</id><published>2008-05-18T18:22:00.001-04:00</published><updated>2008-05-18T18:22:57.363-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='template'/><title type='text'>Template</title><content type='html'>&lt;p&gt;Here is link which suverys browser-side templating: &lt;a title="http://ajaxpatterns.org/Browser-Side_Templating" href="http://ajaxpatterns.org/Browser-Side_Templating"&gt;http://ajaxpatterns.org/Browser-Side_Templating&lt;/a&gt;.&lt;br&gt;The goal of browser-side templating is to separate presentation and logic. And in my application, I think it will be helpful to use browser-side templating to ease the development. Currently, JSON messages are received from server and then formatted accordingly to display them to end users. &lt;/p&gt; &lt;p&gt;In next step, I would like to try JTL(Javascript Template Library) &lt;a title="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates" href="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates"&gt;http://code.google.com/p/trimpath/wiki/JavaScriptTemplates&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2523100765197608314?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2523100765197608314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2523100765197608314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2523100765197608314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2523100765197608314'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/template.html' title='Template'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6720706242257986818</id><published>2008-05-12T18:12:00.002-04:00</published><updated>2008-05-12T18:18:24.265-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='openid'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><title type='text'>OpenID</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;Some text is excerpted from Official Specification.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[Resources]&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;Official web site: &lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;&lt;a href="http://openid.net/"&gt;&lt;span style="font-weight: normal; font-size: 10.5pt; mso-bidi-font-size: 12.0pt"&gt;http://openid.net&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;br&gt;Authentication specification: &lt;a href="http://openid.net/specs/openid-authentication-2_0.html"&gt;http://openid.net/specs/openid-authentication-2_0.html&lt;/a&gt;&lt;br&gt;Following is a very good and detailed tutorial about how to develop a web site which makes use of OpenID: &lt;a href="http://www.plaxo.com/api/openid_recipe"&gt;http://www.plaxo.com/api/openid_recipe&lt;/a&gt;.&lt;br&gt;Libraries written in various languages: &lt;a href="http://wiki.openid.net/Libraries"&gt;http://wiki.openid.net//Libraries&lt;/a&gt;.&lt;br&gt;This web site lists many web sites which support OpenID: &lt;a href="http://openiddirectory.com/"&gt;http://openiddirectory.com/&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[Introduction]&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Previously, when we visit some web sites and want to leave comments, generally we need to sign up an account at first. This is kind of annoying because we might just surf the web and we might not visit the website again in the future. Applying for a new account is not a big deal. &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;By using OpenID, we can be authenticated in a new web site by signing in an OpenID provider (e.g. Blogger, Flickr, Youtube…) with existing account. In other words, we could use the same account to log in to multiple web sites/applications. Generally, most of users have account in prevailing OpenID providers. These providers (e.g. Flickr, Youtube ...) provide their own core compelling services (e.g. video sharing, picture share…) besides OpenID support. Besides, there are some new sites which mainly provide OpenID support (e.g. myopenid.com,). &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;An &lt;b style="mso-bidi-font-weight: normal"&gt;assumption&lt;/b&gt; is that OpenID providers are trusted by various OpenID-aware web applications. &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;The &lt;b style="mso-bidi-font-weight: normal"&gt;advantage&lt;/b&gt; of OpenID is that:&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;i style="mso-bidi-font-style: normal"&gt;Users can use OpenID to log in to multiple web sites which support OpenID without having to apply for an account. As a result, users don’t need to remember large number of usernames and passwords, which improves user experience greatly.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;The &lt;b style="mso-bidi-font-weight: normal"&gt;mechanisms &lt;/b&gt;used to achieve the goal are: redirection and callback.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[Architecture]&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SCjA5WwpXhI/AAAAAAAAAK8/O1d_NGiMlFo/s1600-h/image%5B7%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="413" alt="image" src="http://lh4.ggpht.com/Jenvor/SCjA5mwpXiI/AAAAAAAAALE/jgHVJAkem0w/image_thumb%5B3%5D.png?imgmax=800" width="857" border="0"&gt;&lt;/a&gt; &lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;1) Background&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;There are two kinds of communication: direct request and indirect request.&lt;br&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;Direct request:&lt;/i&gt;&lt;/b&gt; one party sends request directly to another party to get response. The message must be encoded as a POST body. &lt;br&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;Indirect request:&lt;/i&gt;&lt;/b&gt; one party sends request to another party by redirecting user agent to the destination party with request data (query string or POST body). &lt;br&gt;There are two mechanisms which can be used to send indirect request: HTTP indirection or form redirection. &lt;br&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;HTTP redirec:&lt;br&gt;&lt;/i&gt;&lt;/b&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;“Data can be transferred by issuing a 302, 303 or 307 HTTP redirect to the end user’s agent. The redirect URL is the &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="color: red"&gt;URL of the receiver with the OpenID authentication message appended to the query string&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;.” &lt;br&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;HTTP Form redirection&lt;br&gt;&lt;/i&gt;&lt;/b&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A HTML page which contains an HTML form element can be returned to user. And the form contains a mapping of keys to values. Javascript can be used to automate submission of the form to implement redirection.&lt;br&gt;More info: &lt;a href="http://openid.net/specs/openid-authentication-2_0.html#anchor6"&gt;http://openid.net/specs/openid-authentication-2_0.html#anchor6&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;2) Procedure&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;First, the Relying Party presents the user with a form that has a field for entering User-Supplied Identifier. The form field’s name should be “openid_identifier” so that user agents can detect it automatically and provide some extra functionality. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;The user submits the from to Relying Party&lt;br&gt;After receiving data submitted by user, Relying Party normalizes the input data and then discovers OP endpoint URL based on user-supplied identifier. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(2)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;This step is optional. Relying Party can build an association with OP. &lt;br&gt;An association establishes a shared secret between them which is used to verify subsequent protocol messages and reduce round trips. &lt;br&gt;More info: &lt;a href="http://openid.net/specs/openid-authentication-2_0.html#associations"&gt;http://openid.net/specs/openid-authentication-2_0.html#associations&lt;/a&gt; &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(3)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;Relying Party sends authentication request to user agent.&lt;br&gt;User agent sends authentication request to OP. Then user is authenticated by the OP. &lt;br&gt;These two sub steps jointly do this: Relying Party send an authentication request to the OP to obtain an assertion. This is an indirect request. So the request actually is sent by Relying Party to user agent and then redirected to OP. &lt;br&gt;Generally, OP will display a web page which enable user to accept or deny access request from Relying Party. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(4)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;OP sends authentication response to user agent and then user agent sends response to Relying Party. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(5)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;After receiving authentication response from OP (indirect communication), Relying Party verifies it and judge whether it is a positive assertion or negative assertion. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;More info: &lt;a href="http://openid.net/specs/openid-authentication-2_0.html#responding_to_authentication"&gt;http://openid.net/specs/openid-authentication-2_0.html#responding_to_authentication&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[More]&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Besides authentication, personal information (e.g. gender, location, age …) can be transferred between Relying Party and OpenID provider as well. Then Relying Party can pre-fill some registration fields so that users don’t need to type the same information many times. Of course, Relying Party needs to convert information from OpenID provider to its own format. &lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[Delegation]&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;Delegation is also possible: &lt;a href="http://simonwillison.net/2006/Dec/19/openid/"&gt;http://simonwillison.net/2006/Dec/19/openid/&lt;/a&gt;. It means users may want to delegate their OpenID to another provider behind-the-scenes. An example from &lt;a href="http://www.plaxo.com/api/openid_recipe"&gt;http://www.plaxo.com/api/openid_recipe&lt;/a&gt;:&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;“If I try to sign up with the OpenID josephsmarr.com, I may have actually delegated that URL to a different OpenID like jsmarr.myopenid.com, and when the provider returns to you to complete authentication, you need to remember that I wanted to sign up as josephsmarr.com and not jsmarr.myopenid.com.”&lt;br&gt;Key thing is that you add following two lines of HTML code to your delegation HTML page:&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New'"&gt;&amp;lt;link rel="openid.server" href="http://openid.server"&amp;gt;&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;link rel="openid.delegate" href="http://delegation.site"&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;You should replace the value of &lt;i style="mso-bidi-font-style: normal"&gt;href&lt;/i&gt; attributes accordingly. &lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;This mechanism actually adds an additional layer which separates Relying party and OpenID provider. Relying Party gets OpenID endpoint URL by accessing your delegation HTML page. After getting value of &lt;i style="mso-bidi-font-style: normal"&gt;open.server&lt;/i&gt; and &lt;i style="mso-bidi-font-style: normal"&gt;openid.delegate&lt;/i&gt;, Relying Party can sends authentication request to corresponding OpenID provider. You can easily switch your preferred OpenID provider by modifying value of attribute &lt;i style="mso-bidi-font-style: normal"&gt;href&lt;/i&gt; in &lt;i style="mso-bidi-font-style: normal"&gt;link&lt;/i&gt; elements.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;[Myth]&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;OpenID is a mechanism which can authenticate users by delegating it to corresponding OpenID provider. So it is not appropriate to use it directly in a third-party application which sits on top of an existing service and wants to access the backend service on behalf of the user. For example, if a web site makes use of Youtube API to do some cool things, it necessarily needs users’ information to utilize Youtube on behalf of the user. OpenID does not solve this problem. &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;But, in my opinion, this can be done by extending OpenID specification. In authentication response, OpenID provide can include an auth token which can be used as a handle by Relying Party to access service provided by the OpenID provider on behalf of the user. In addition, access level (Read, Write, Delete …) must be negotiated as well. &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;However, the extension deviates from gist of OpenID because authorization delegation is involved besides authentication. &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6720706242257986818?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6720706242257986818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6720706242257986818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6720706242257986818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6720706242257986818'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/openid.html' title='OpenID'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/Jenvor/SCjA5mwpXiI/AAAAAAAAALE/jgHVJAkem0w/s72-c/image_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2943909220565987698</id><published>2008-05-10T16:14:00.002-04:00</published><updated>2008-05-10T16:15:45.090-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><category scheme='http://www.blogger.com/atom/ns#' term='youtube'/><title type='text'>Youtube API usage</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;Authentication&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;a href="http://code.google.com/apis/youtube/developers_guide_protocol.html"&gt;http://code.google.com/apis/youtube/developers_guide_protocol.html&lt;/a&gt;&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;It is recommended that you include the proper authentication headers in all of your requests even if those requests do not explicitly require authentication.&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A request must include the &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;X-GData-Key&lt;/i&gt;&lt;/b&gt; and &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;Authorization&lt;/i&gt;&lt;/b&gt; headers. &lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;The &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;X-GData-Key&lt;/i&gt;&lt;/b&gt; header specifies your &lt;a href="http://code.google.com/apis/youtube/developers_guide_protocol.html#Developer_Key"&gt;&lt;span style="color: windowtext; text-decoration: none; text-underline: none"&gt;developer key&lt;/span&gt;&lt;/a&gt;, a value that uniquely identifies your application(s). The &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;Authorization&lt;/i&gt;&lt;/b&gt; header specifies a token that you obtain for each user using one of two authentication schemes, &lt;a href="http://code.google.com/apis/youtube/developers_guide_protocol.html#AuthSub_Authentication"&gt;&lt;span style="color: windowtext; text-decoration: none; text-underline: none"&gt;AuthSub&lt;/span&gt;&lt;/a&gt; or &lt;a href="http://code.google.com/apis/youtube/developers_guide_protocol.html#ClientLogin_Authentication"&gt;&lt;span style="color: windowtext; text-decoration: none; text-underline: none"&gt;ClientLogin&lt;/span&gt;&lt;/a&gt;. Headers are like this:&lt;/span&gt;&lt;/p&gt; &lt;table class="MsoTableGrid" style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0pt 5.4pt 0pt 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1"&gt; &lt;tbody&gt; &lt;tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 213.05pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt" valign="top" width="284"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;AuthSub&lt;/span&gt;&lt;/p&gt;&lt;/td&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0pt; border-left: medium none; width: 213.05pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="284"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;ClientLogin&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes"&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: windowtext 1pt solid; width: 213.05pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="284"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;Authorization:&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;AuthSub&lt;/i&gt;&lt;/b&gt; token=&amp;lt;authentication_token&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;X-GData-Key: key=&amp;lt;developer_key&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt; &lt;td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0pt; border-left: medium none; width: 213.05pt; padding-top: 0pt; border-bottom: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="284"&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;Authorization:&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;GoogleLogin&lt;/i&gt;&lt;/b&gt; auth=&amp;lt;authentication_token&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;X-GData-Key: key=&amp;lt;developer_key&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Functions supported in &lt;b style="mso-bidi-font-weight: normal"&gt;AuthSub&lt;br&gt;&lt;span style="mso-tab-count: 1"&gt;&lt;/span&gt;&lt;/b&gt;&lt;a href="http://code.google.com/apis/accounts/docs/AuthForWebApps.html"&gt;http://code.google.com/apis/accounts/docs/AuthForWebApps.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; mso-list: l0 level2 lfo3"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1.1)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;AuthSubRequest&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A call to this method sends the user to a Google Accounts web page, where the user is given the opportunity to log in and grant Google account access to the web application. If successful, Google provides a single-use authentication token, which the web application can use to access the user's Google service data. This is done by using GET to a specific formatted URL.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample URL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;a href="https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fgdata.youtube.com&amp;amp;next=http%3A%2F%2Fzhguo.blogspot.com"&gt;&lt;span style="font-weight: normal; color: windowtext; text-decoration: none; text-underline: none"&gt;https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fgdata.youtube.com&amp;amp;next=http%3A%2F%2Fzhguo.blogspot.com&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; mso-list: l0 level2 lfo3"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1.2)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;AuthSubSessionToken&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A call to this method allows the web application to &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;exchange&lt;/i&gt;&lt;/b&gt; a single-use token for a session token.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample request&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;curl https://www.google.com/accounts/AuthSubSessionToken --header ‘Authorization: AuthSub token="token"’&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Response&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Token=DQAA...7DCTN&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Expiration=20061004T123456Z&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; mso-list: l0 level2 lfo3"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1.3)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;AuthSubRevokeToken&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A call to this method revokes a session token. Once a token is revoked it is no longer valid.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample Request&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;curl https://www.google.com/accounts/AuthSubRevokeToken --header ‘Authorization: AuthSub token="token"’&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; mso-list: l0 level2 lfo3"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1.4)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;AuthSubTokenInfo. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;A call to this method &lt;b style="mso-bidi-font-weight: normal"&gt;verifies&lt;/b&gt; whether a specified session token is valid and returns data associated with the token. This operation applies to both one-time-use and session keys.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample request&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;curl &lt;a href="https://www.google.com/accounts/AuthSubTokenInfo%20/"&gt;&lt;span style="color: windowtext; text-decoration: none; text-underline: none"&gt;https://www.google.com/accounts/AuthSubTokenInfo &lt;/span&gt;&lt;/a&gt;--header 'Authorization: AuthSub token="CO7xhO-6GhDT5f2tAwd"'&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample response&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Target=http://www.yourwebapp.com&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Scope=http://www.google.com/calendar/feeds/&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Secure=true&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(2)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;ClientLogin&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;a href="http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html"&gt;http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Before using ClientLogin, you must have an existing Google account. The POST request should be structured as a form post with the default encoding &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;application/x-www-form-urlencoded&lt;/i&gt;&lt;/b&gt;. Parameters should be included in the body of the post.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;Action URL parameter: &lt;a href="https://www.google.com/accounts/ClientLogin"&gt;https://www.google.com/accounts/ClientLogin&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample request format:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;POST /accounts/ClientLogin HTTP/1.0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;Content-type: application/x-www-form-urlencoded&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;accountType=HOSTED_OR_GOOGLE&amp;amp;Email=jondoe@gmail.com&amp;amp;Passwd=north23AZ&amp;amp;service=cl&amp;amp;source=Gulp-CalGulp-1.05&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="text-align: left" align="left"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;CURL command&lt;br&gt;&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;curl &lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;--location &lt;a href="https://www.google.com/youtube/accounts/ClientLogin"&gt;https://www.google.com/youtube/accounts/ClientLogin&lt;/a&gt;&amp;nbsp;&lt;br&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;--data 'Email=username&amp;amp;Passwd=password&amp;amp;service=youtube&amp;amp;source=Test' &lt;br&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 7.5pt"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;--header 'Content-Type:application/x-www-form-urlencoded' -i&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US"&gt;Sample Response:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;SID=DQAAAGgA...7Zg8CTN&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;LSID=DQAAAGsA...lk8BBbG&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;Auth=DQAAAGgA...dk3fA5N&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(3)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Difference of two mechanisms&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;To use &lt;i style="mso-bidi-font-style: normal"&gt;ClientLogin&lt;/i&gt;, a third-party application must own Youtube’s username and password of every user. Then the third-party application can do anything the end user can do. This mechanism is convenient for third-party apps to use because it does not require much intervening from users. However, it requires trust of users who may be afraid that their person information is not stored appropriately. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;To use &lt;i style="mso-bidi-font-style: normal"&gt;AuthSub&lt;/i&gt;, a third-party does not need to own Youtube’s username and password of user. Instead, the user will be redirected to a web site from google to authorize third-party app’s access to user’s account. At first, third-party app is given a one-time access key which can be used to exchange a session key that can be used longer. This method is more secure for users at the cost of manually authorizing access requests. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span lang="EN-US" style="font-size: 14pt"&gt;Some development detail&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Some videos are not allowed to be embedded in third-party applications.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;In the feed of these videos, &lt;i style="mso-bidi-font-style: normal"&gt;mediagroup::content&lt;/i&gt; element does not exist!!! I manually construct URL by concatenating &lt;i style="mso-bidi-font-style: normal"&gt;http://gdata.youtube.com/feeds/api/videos/&lt;/i&gt; and &lt;i style="mso-bidi-font-style: normal"&gt;video id&lt;/i&gt; and try to embed it into my app. As I expect, it does not work. However, I figured out a method which can work around this problem. I concatenate &lt;i style="mso-bidi-font-style: normal"&gt;http://www.youtube.com/swf/l.swf?video_id&lt;/i&gt;= and video id and it works. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(2)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Some videos are not allowed to be commented by some users. These videos should be handled carefully. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;a href="http://gdata.youtube.com/feeds/api/videos/gmNbl5ZTBZE"&gt;http://gdata.youtube.com/feeds/api/videos/gmNbl5ZTBZE&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(3)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Duplicate elimination&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;If you upload the same video clip more then once using different metadata, Youtube can figure it out and all uploads but the first one will be rejected. I am not sure how they compare two different video clips, maybe using MD5 to calculate a signature. The duplicate uploads are still displayed in your account. And all metadata is preserved except the video clip itself. The only difference between original upload and following duplicate uploads is that you can not play duplicate video clips. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/SCYCN62WtxI/AAAAAAAAAKs/6JqAQJCsca0/s1600-h/clip_image002%5B9%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="310" alt="clip_image002" src="http://lh6.ggpht.com/Jenvor/SCYCOa2WtyI/AAAAAAAAAK0/Otr8cchSREY/clip_image002_thumb%5B3%5D.jpg?imgmax=800" width="701" border="0" v:shapes="_x0000_i1025"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;As shown in above picture, metadata (e.g. description, tags, views, published time…) are still there. But the video clip itself is rejected &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(4)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;OpenSearch support&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;If you search videos on Youtube, in returned feed &lt;i style="mso-bidi-font-style: normal"&gt;openSearch&lt;/i&gt; extension is supported:&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;&amp;lt;openSearch:totalResults&amp;gt;274842&amp;lt;/openSearch:totalResults&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;&amp;lt;openSearch:startIndex&amp;gt;1&amp;lt;/openSearch:startIndex&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;&amp;lt;openSearch:itemsPerPage&amp;gt;25&amp;lt;/openSearch:itemsPerPage&amp;gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 18.0pt"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(5)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Navigation of many returned results.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;In returned feeds, if not all results are returned, there should be a &lt;i style="mso-bidi-font-style: normal"&gt;link&lt;/i&gt; element in the feed. It is like this:&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;&amp;lt;link rel="&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;next&lt;/i&gt;&lt;/b&gt;" type="application/atom+xml" href="http://... "/&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin-left: 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;&amp;lt;link rel="&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;previous&lt;/i&gt;&lt;/b&gt;" type="application/atom+xml" href="http://... "/&amp;gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2943909220565987698?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2943909220565987698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2943909220565987698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2943909220565987698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2943909220565987698'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/youtube-api-usage.html' title='Youtube API usage'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/Jenvor/SCYCOa2WtyI/AAAAAAAAAK0/Otr8cchSREY/s72-c/clip_image002_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-3835626653613605063</id><published>2008-05-10T14:50:00.001-04:00</published><updated>2008-05-10T14:52:36.343-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='mashup'/><title type='text'>Mashup Architecture</title><content type='html'>&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt;&lt;br&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/SCXus62WttI/AAAAAAAAAJ0/wrFTuqFuY-g/s1600-h/image%5B15%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="494" alt="image" src="http://lh5.ggpht.com/Jenvor/SCXuta2WtuI/AAAAAAAAAJ8/spjpyoV92qE/image_thumb%5B11%5D.png?imgmax=800" width="677" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Adapter:&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/Jenvor/SCXutq2WtvI/AAAAAAAAAKE/NneQUNZIOFY/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="370" alt="image" src="http://lh3.ggpht.com/Jenvor/SCXut62WtwI/AAAAAAAAAKM/EOWwxpD2aQE/image_thumb%5B2%5D.png?imgmax=800" width="671" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;TODO:&lt;br&gt;Integrate authentication architecture.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-3835626653613605063?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/3835626653613605063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=3835626653613605063' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3835626653613605063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3835626653613605063'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/05/mashup-architecture.html' title='Mashup Architecture'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/Jenvor/SCXuta2WtuI/AAAAAAAAAJ8/spjpyoV92qE/s72-c/image_thumb%5B11%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1626067230943433692</id><published>2008-04-10T23:36:00.002-04:00</published><updated>2008-04-10T23:38:20.668-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><title type='text'>Add image support in web2.0 app</title><content type='html'>&lt;p&gt;I added image support in the web2.0 app. It means that users can uploads image files besides regular text files. Users can attach tags, description and name when uploading an image. Other users can post comment/rating about the image.&lt;/p&gt; &lt;p&gt;When an image is uploaded, it will be stored somewhere at server side. Moreover, it can be retrieved by accessing a URL. In other words, the server generates a URL which can be used to access that image. When a user tries to retrieve the image, it will be displayed in browser by using &lt;em&gt;img&lt;/em&gt; elment. &lt;/p&gt; &lt;p&gt;Currently, I am using suffix of file name to judge type of record (image or text). The advantage is that user intervening is not needed. Drawback is that sometimes suffixes are not accurate. It may be better to use MIME type which is specified when user uploads an object. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1626067230943433692?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1626067230943433692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1626067230943433692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1626067230943433692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1626067230943433692'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/04/add-image-support-in-web20-app.html' title='Add image support in web2.0 app'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5574678779898977661</id><published>2008-04-10T21:03:00.002-04:00</published><updated>2008-04-10T21:04:47.579-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Tomcat virtual/physical path mapping</title><content type='html'>&lt;p&gt;In my web2.0 application, users can upload files to server. I want to build mapping from virtual path to physical path. It means that the resources accessed are located in a separate directory instead of tomcat sub directory. &lt;/p&gt; &lt;p&gt;&lt;em&gt;Context&lt;/em&gt; container can be used to achieve that goal. Official document is here &lt;a title="http://tomcat.apache.org/tomcat-6.0-doc/config/context.html" href="http://tomcat.apache.org/tomcat-6.0-doc/config/context.html"&gt;http://tomcat.apache.org/tomcat-6.0-doc/config/context.html&lt;/a&gt;. &lt;br&gt;In my case, I modified configuration file &lt;em&gt;server.xml&lt;/em&gt; and insert following text into &lt;em&gt;Host&lt;/em&gt; element:&lt;pre&gt;&amp;lt;context crosscontext="true" docbase="E:\\temp\imgService" path="/imgService"&amp;gt;&amp;lt;/context&amp;gt;&lt;/pre&gt;
&lt;p&gt;Actually, at first, I tried to modify &lt;em&gt;context.xml&lt;/em&gt; instead of &lt;em&gt;service.xml&lt;/em&gt; because it is less invasive. However, it didn't work and I don't know why. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5574678779898977661?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5574678779898977661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5574678779898977661' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5574678779898977661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5574678779898977661'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/04/tomcat-virtualphysical-path-mapping.html' title='Tomcat virtual/physical path mapping'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-7140281008569146673</id><published>2008-04-10T00:41:00.001-04:00</published><updated>2008-04-10T00:43:22.941-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='web2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='xml-rpc'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>A Simple Web 2.0 Framework</title><content type='html'>&lt;p&gt;I have completed a simple application which supports common web 2.0 features: rating, commenting, tagging. &lt;br&gt;Demo address is: &lt;a title="http://156.56.104.196:8080/tagService/index_ui.html" href="http://156.56.104.196:8080/tagService/index_ui.html"&gt;http://156.56.104.196:8080/tagService/index_ui.html&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;The basic unit in my system is called &lt;em&gt;record&lt;/em&gt;. A record is abstraction of an object. Theoretically, it can be of any type: image, text, presentation... However, the key issue is how to present different types of records to end users. Text is easy to present and it can be displayed to users directly. For image, &lt;em&gt;img&lt;/em&gt; element can be used but it requires that the image be stored somewhere on the website so that it can be accessed by visiting a URL. Currently, only text is supported. When a user retrieves some record, text content of that record is displayed directly in browser. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Operations:&lt;/strong&gt;&lt;br&gt;(1) Add a new record&lt;br&gt;Users add a new record by uploading a file to server and specifying name, description and tags. Then a unique id is generated for this new record at server side. &lt;br&gt;(2) List all records&lt;br&gt;Get all records in the system.&lt;br&gt;(3) Get a record based on its id&lt;br&gt;According to record id, get corresponding id.&lt;br&gt;(4) Get records according to tag&lt;br&gt;According to user-specified tag, corresponding records are returned. Currently, users can only specify a single tag. &lt;br&gt;(5) Post comment and rating of a certain record&lt;br&gt;Users can post comments and ratings about records.&lt;br&gt;(6) Comment and rating of comment.&lt;br&gt;Besides comments of records, comments of comments are supported. It means that users can post comments about existing comments besides records. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt;:&lt;br&gt;&lt;a href="http://lh5.ggpht.com/Jenvor/R_2alTxSmlI/AAAAAAAAAI0/XNPhy9aAR0U/web20_arch_ws%5B4%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="225" alt="web20_arch_ws" src="http://lh3.ggpht.com/Jenvor/R_2alzxSmmI/AAAAAAAAAI8/8wHZTOW-9CI/web20_arch_ws_thumb%5B2%5D.jpg" width="479" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;Client sends request to a server which uses servlet to handles it. Then the servlet accesses a web service which provides web 2.0 functionalities. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Presentation location:&lt;/strong&gt;&lt;br&gt;What is stored in backend database is raw data. And it does not contain information about how to present it to end users. E.g. layout, font-size... &lt;br&gt;There are two strategies to transform raw data into final presentation data: server-side servlet and client-side javascript.&lt;br&gt;(1) Server-side servlet&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/Jenvor/R_2amDxSmnI/AAAAAAAAAJE/aSvzF2ft9iM/web20_arch_html_ws%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="289" alt="web20_arch_html_ws" src="http://lh6.ggpht.com/Jenvor/R_2amjxSmoI/AAAAAAAAAJM/v8KY3uuLDNE/web20_arch_html_ws_thumb%5B1%5D.jpg" width="583" border="0"&gt;&lt;/a&gt; &lt;br&gt;When servlet responds to user's request, a HTML document is returned. The HTML document does not only contains data but also contains presentation information. So it can be displayed directly. In this method, servlet formats the raw data received from web service into a corresponding HTML document.&lt;/p&gt; &lt;p&gt;(2) Client-side javascript&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/Jenvor/R_2amzxSmpI/AAAAAAAAAJU/30M5lRDOHuI/web20_arch_json_ws%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="285" alt="web20_arch_json_ws" src="http://lh5.ggpht.com/Jenvor/R_2anTxSmqI/AAAAAAAAAJc/he9f8qGXQ5o/web20_arch_json_ws_thumb%5B1%5D.jpg" width="581" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;In this method, servlet just returns raw data in JSON format. It means returned data does not contain any presentation information. And client side javascript displays the raw data in a specific manner. Actually, to use this method, AJAX should be used. Object X&lt;em&gt;mlHttpRrequest&lt;/em&gt; can be used to make asynchronous request without refreshing whole page.&lt;/p&gt; &lt;p&gt;Personally, I prefer the second method. &lt;br&gt;I remember there are some server-side Java libraries which can be used to make transformation execute with ease.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AJAX&lt;/strong&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AJAX is used frequently. However, the format of request is not XML. I manually compose POST query in Javascript and then send it by using XmlHttpRequest. Actually, I use &lt;em&gt;application/x-www-form-urlencoded&lt;/em&gt; which is the default data encoding of form submission. I chose this encoding because it is simple compared to the other encoding - &lt;em&gt;multipart/form-data. &lt;/em&gt;To make it work well, the data must be escaped. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Responses from server are in JSON format. So javascript decodes JSON string and dynamically modifies web page accordingly. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; An alternative method is to use XML-RPC.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Possible future work:&lt;/strong&gt;&lt;br&gt;(1) User management&lt;br&gt;Currently, the system is open and everyone can use it anonymously. &lt;br&gt;(2) RESTful access&lt;br&gt;(3) Support image type in presentation layer. &lt;br&gt;(4) Persistence of server data.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-7140281008569146673?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/7140281008569146673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=7140281008569146673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7140281008569146673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7140281008569146673'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/04/simple-web-20-framework.html' title='A Simple Web 2.0 Framework'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/Jenvor/R_2alzxSmmI/AAAAAAAAAI8/8wHZTOW-9CI/s72-c/web20_arch_ws_thumb%5B2%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-490531531281043236</id><published>2008-04-09T19:05:00.002-04:00</published><updated>2008-04-09T19:06:25.062-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>Dynamic web page development</title><content type='html'>&lt;p&gt;Recently, I am working on creating a simple web2.0 framework which enables commenting, rating and tagging. Of course, there are two parts: client side and server side. Client side programming using Javascript almost kills me because of incompatibility among different browsers.&lt;/p&gt; &lt;p&gt;(1) When content of a &lt;em&gt;div&lt;/em&gt; element exceeds size of the &lt;em&gt;div&lt;/em&gt; box, different browsers responde in different ways.&lt;br&gt;In IE, you can use &lt;em&gt;white-space&lt;/em&gt; and &lt;em&gt;word-break&lt;/em&gt; to force word wrap. &lt;br&gt;in FireFox, unfortunately there is not an easy way to do it. You can use &lt;em&gt;overflow&lt;/em&gt; property to force a scroll bar. However, this is not what I want. I want the text wrapped automatically.&lt;/p&gt; &lt;p&gt;(2) Following is a piece of javascript:&lt;pre&gt;var inputele = document.createElement('input');
inputele.setAttribute('type', 'button');
inputele.setAttribute('name', 'testbutton');
inputele.setAttribute('value', 'click me');
inputele.setAttribute('onClick','javascript:alert(\'hello,world\');return false;');&lt;/pre&gt;
&lt;p&gt;In FF, it works well. But in IE, it does not work. It seems that &lt;em&gt;setAttribute&lt;/em&gt; can not be used set event handlers. &lt;br&gt;Instead, you should use &lt;em&gt;attachEvent&lt;/em&gt;.&lt;pre&gt;inputele.attachEvent('onclick', function(){ ... });&lt;/pre&gt;Or:&lt;pre&gt;invokeStr = "calculate(1,2)";
inputele.attachEvent(onclick', function(){ eval(invokeStr); }&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Besides, you can not use &lt;em&gt;setAttribute&lt;/em&gt; to modify &lt;em&gt;style&lt;/em&gt; property in IE.&lt;br&gt;In IE:&lt;pre&gt;element.style.display = "block";
element.style.position ="relative";
...&lt;/pre&gt;In FF:&lt;pre&gt;style = 'display:block; position:relative;';
element.setAttribute('style', style); &lt;/pre&gt;
&lt;p&gt;Moreover, &lt;em&gt;name&lt;/em&gt; property of a newly built &lt;em&gt;input&lt;/em&gt; element can not be modified after the element is created. Official description is here &lt;a title="http://msdn2.microsoft.com/en-us/library/ms536389(VS.85).aspx" href="http://msdn2.microsoft.com/en-us/library/ms536389(VS.85).aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms536389(VS.85).aspx&lt;/a&gt;. Stupid, right?&lt;br&gt;It means in IE you must use:&lt;pre&gt;var inputele = document.createElement('&amp;lt;input type="button" name="buttonname" value="click me"&amp;gt;&amp;lt;/input&amp;gt;');&lt;/pre&gt;
&lt;p&gt;Many many others...... &lt;/p&gt;
&lt;p&gt;Currently, I make use of object &lt;em&gt;navigator&lt;/em&gt; to judge type of browser. For IE, &lt;em&gt;navigator.appName&lt;/em&gt; is "Microsoft Internet Explorer". Actually, &lt;em&gt;navigator.userAgent&lt;/em&gt; provides detailed information about browser. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-490531531281043236?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/490531531281043236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=490531531281043236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/490531531281043236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/490531531281043236'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/04/dynamic-web-page-development.html' title='Dynamic web page development'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5953676925623680228</id><published>2008-04-06T16:44:00.001-04:00</published><updated>2008-04-06T20:53:11.837-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>HTTP Form POST Encoding</title><content type='html'>&lt;p&gt;Form is a common way to submit requests to server with various parameters. In W3C HTML4(&lt;a title="http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4" href="http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4"&gt;http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4&lt;/a&gt;), &lt;em&gt;form&lt;/em&gt; element has a special attribute "&lt;em&gt;enctype&lt;/em&gt;" to indicate how to encode form data for submission. &lt;/p&gt; &lt;p&gt;(1)&lt;strong&gt; application/x-www-form-urlencoded (default type)&lt;/strong&gt;&lt;/p&gt; &lt;ol&gt;from W3C specification:  &lt;li&gt;Control names and values are escaped. Space characters are replaced by &lt;samp&gt;`+'&lt;/samp&gt;, and then reserved characters are escaped as described in &lt;a href="http://www.w3.org/TR/html4/references.html#ref-RFC1738"&gt;[RFC1738]&lt;/a&gt;, section 2.2: Non-alphanumeric characters are replaced by &lt;samp&gt;`%HH'&lt;/samp&gt;, a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., &lt;samp&gt;`%0D%0A'&lt;/samp&gt;).  &lt;li&gt;The control names/values are listed in the order they appear in the document. The name is separated from the value by &lt;samp&gt;`='&lt;/samp&gt; and name/value pairs are separated from each other by &lt;samp&gt;`&amp;amp;'&lt;/samp&gt;. &lt;/li&gt;&lt;/ol&gt;Examples &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; home=Cosby&amp;amp;favorite+flavor=flies&amp;nbsp; &lt;p&gt;(2) &lt;strong&gt;multipart/form-data&lt;/strong&gt;&lt;br&gt;From W3C specification:&lt;br&gt;"he content type "application/x-www-form-urlencoded" is inefficient for sending large quantities of binary data or text containing non-ASCII characters. The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.  &lt;p&gt;The content "multipart/form-data" follows the rules of all multipart MIME data streams as outlined in &lt;a href="http://www.w3.org/TR/html4/references.html#ref-RFC2045"&gt;[RFC2045]&lt;/a&gt;. The definition of "multipart/form-data" is available at the &lt;a href="http://www.w3.org/TR/html4/references.html#ref-IANA"&gt;[IANA]&lt;/a&gt; registry.  &lt;p&gt;A "multipart/form-data" message contains a series of parts, each representing a &lt;a href="http://www.w3.org/TR/html4/interact/forms.html#successful-controls"&gt;successful control&lt;/a&gt;. The parts are sent to the processing agent in the same order the corresponding controls appear in the document stream. Part boundaries should not occur in any of the data; how this is done lies outside the scope of this specification.  &lt;p&gt;As with all multipart MIME types, each part has an optional "Content-Type" header that defaults to "text/plain". User agents should supply the "Content-Type" header, accompanied by a "charset" parameter.  &lt;p&gt;Each part is expected to contain:  &lt;ol&gt; &lt;li&gt;a "Content-Disposition" header whose value is "form-data".  &lt;li&gt;a name attribute specifying the &lt;a href="http://www.w3.org/TR/html4/interact/forms.html#control-name"&gt;control name&lt;/a&gt; of the corresponding control. Control names originally encoded in non-ASCII &lt;a href="http://www.w3.org/TR/html4/charset.html"&gt;character sets&lt;/a&gt; may be encoded using the method outlined in &lt;a href="http://www.w3.org/TR/html4/references.html#ref-RFC2045"&gt;[RFC2045]&lt;/a&gt;. "&lt;/li&gt;&lt;/ol&gt;"  &lt;p&gt;Examples:&lt;pre&gt;    Content-Type: multipart/form-data; boundary=AaB03x
   --AaB03x
   Content-Disposition: form-data; name="submit-name"

   Larry
   --AaB03x
   Content-Disposition: form-data; name="files"; filename="file1.txt"
   Content-Type: text/plain

   ... contents of file1.txt ...
   --AaB03x--&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5953676925623680228?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5953676925623680228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5953676925623680228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5953676925623680228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5953676925623680228'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/04/http-form-post-encoding.html' title='HTTP Form POST Encoding'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6046143391140943211</id><published>2008-03-27T00:27:00.001-04:00</published><updated>2008-03-27T00:34:02.570-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='db4o'/><category scheme='http://www.blogger.com/atom/ns#' term='axis2'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><title type='text'>Workaround of bug in integration of db4o and axis2</title><content type='html'>&lt;p&gt;I have been trying to solve the problem described in my last post. &lt;/p&gt; &lt;p&gt;I tried different versions of tomcat and Db4o which did not help me out. I posted this problem in forum of Db4o to ask for help. However, no one supplied right solution. I tried countless possible solutions. Finally, I got it to work. Following is the procedure how I discovered my solution.&lt;/p&gt; &lt;p&gt;To enhance speed of development , I tried to find some software support. I have been using Eclipse as my IDE. So naturally &lt;a href="http://www.eclipse.org/webtools/"&gt;WTP&lt;/a&gt;(Web Tool Platform) is a great plug-in to support development of web applications in Eclipse. WTP provides support for Tomcat and Axis2 which are being used in my project. Here(&lt;a title="http://www.eclipsecon.com/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html" href="http://www.eclipsecon.com/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html"&gt;http://www.eclipsecon.com/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html&lt;/a&gt;) is a great tutorial about how to deploy and start Axis2 web service in Eclipse. &lt;/p&gt; &lt;p&gt;Then I doubt that the problem maybe results from Axis2. So I decided to write a simple servlet to do similar job. In other words, Axis2 was not used. And test result showed that everything worked correctly with Db4o. So this meaned that it is highly possible that Axis2 is cause of the problem. I did further investigation to uncover what is wrong under the hood. I built the same Axis2 service in Eclipse and deployed the service to Eclipse's temporary publish directory. Surprisingly, it worked!!! However, if I built web service using ADB(Apache Databinding) in Axis2, wrapped it to a .aar archive file and deployed it into specific directory (services), it did not work!!! So, I made sure that the procedure of deployment of Axis2 web service in Eclipse MUST be different from what I did before. Finally, I found that Eclipse does not wrap web service implementation into a .aar archive file. Instead the deployment directory layout is:&lt;/p&gt; &lt;p&gt;axis2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - WEB-INF&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - lib&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - conf&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - services&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;Sample &lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Sample is the name of this web service&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;META-INF&lt;/font&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;services.xml&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //this file describes the information of this web service.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - classes&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;package&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //this is path corresponding to package&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;*.class&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //These .class files are implementation of web service.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - META-INF&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - axis2-web&lt;/p&gt; &lt;p&gt;The original layout is:&lt;br&gt;axis2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - WEB-INF&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - lib&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - conf&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - services&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - &lt;font color="#0000ff"&gt;Sample.aar&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //the .aar archive file&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -classes&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - META-INF&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; - axis2-web&lt;/p&gt; &lt;p&gt;Difference is highlighted in blue. &lt;br&gt;The services.xml is also different. The new services.xml is:&lt;pre&gt;&amp;lt;service name="Sample" &amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;description&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please Type your service description here&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/description&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;messageReceivers&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;messageReceiver mep="&lt;a href="http://www.w3.org/2004/08/wsdl/in-only&amp;quot;"&gt;http://www.w3.org/2004/08/wsdl/in-only"&lt;/a&gt; class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;messageReceiver&amp;nbsp; mep="&lt;a href="http://www.w3.org/2004/08/wsdl/in-out&amp;quot;"&gt;http://www.w3.org/2004/08/wsdl/in-out"&lt;/a&gt;&amp;nbsp; class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/messageReceivers&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;parameter name="ServiceClass" locked="false"&amp;gt;package.Sample&amp;lt;/parameter&amp;gt;&lt;br&gt;&amp;lt;/service&amp;gt;&lt;/pre&gt;
&lt;p&gt;Besides, in my previous using of Axis2, I used tool provided by Axis2 to construct automatically a stub class and some other auxiliary classes of client side. Then I added my implementation code to that stub class (this stub class contains Axis2-specific stuff). In this new deployment, I did not rely on any Axis2-specific functionality. I just wrote my implementation and compiled it into .class files. And then copied these .class files to directory &lt;strong&gt;&lt;em&gt;${TOMCAT_ROOT}/axis2/classes/package-path/&lt;/em&gt;&lt;/strong&gt;. In addition, I needed to manually create and edit corresponding &lt;strong&gt;&lt;em&gt;services.xml&lt;/em&gt;&lt;/strong&gt; file. In my previous deployment, this file is generated automatically by Axis2 tool. &lt;br&gt;To sum up, this new deployment method eases development of web service because no Axis2-specific stuff is involved during development. The drawback is it is not compact considering that those files are scattered in different places. With regard to this deployment, I did not find much useful information on web. Maybe this method is not recommended, who knows...&lt;/p&gt;
&lt;p&gt;However, I have no choice because only one of them works well. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6046143391140943211?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6046143391140943211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6046143391140943211' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6046143391140943211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6046143391140943211'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/03/workaround-of-bug-in-integration-of.html' title='Workaround of bug in integration of db4o and axis2'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1648223952867983546</id><published>2008-03-24T16:21:00.002-04:00</published><updated>2008-03-24T16:22:26.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='db4o'/><category scheme='http://www.blogger.com/atom/ns#' term='axis2'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>DB4O corrupts in Tomcat with Axis2</title><content type='html'>&lt;p&gt;I integrated Db4o in our project. Db4o is used to persist state information of workflow. After I integrated it, it seemed to work OK. State information can be successfully stored into its object database. And information can be retrieved successfully. However, after I restarted Tomcat, Db4o corrupted during retrieval of data from database. I tried different kinds of query language Db4o supports. Unfortunately, none of these methods work. &lt;/p&gt; &lt;p&gt;For Native Query, the error in Tomcat log is:&lt;br&gt;&lt;pre&gt;java.lang.IllegalArgumentException: argument type mismatch
    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:585)
    at com.db4o.query.Predicate.appliesTo(Unknown Source)
    at com.db4o.inside.query.PredicateEvaluation.evaluate(Unknown Source)
    at com.db4o.Platform4.evaluationEvaluate(Unknown Source)
    at com.db4o.QConEvaluation.visit(Unknown Source)
    at com.db4o.Tree.traverse(Unknown Source)
    at com.db4o.QCandidates.filter(Unknown Source)
    at com.db4o.QConEvaluation.evaluateEvaluationsExec(Unknown Source)
    at com.db4o.QCon.evaluateEvaluations(Unknown Source)
    at com.db4o.QCandidates.evaluate(Unknown Source)
    at com.db4o.QCandidates.execute(Unknown Source)
    at com.db4o.QQueryBase.executeLocal(Unknown Source)
    at com.db4o.QQueryBase.execute1(Unknown Source)
    at com.db4o.QQueryBase.getQueryResult(Unknown Source)
    at com.db4o.QQueryBase.execute(Unknown Source)
    at com.db4o.inside.query.NativeQueryHandler.execute(Unknown Source)
    at com.db4o.YapStreamBase.query(Unknown Source)
    at com.db4o.YapStreamBase.query(Unknown Source)
    at org.cogkit.cyberaide.axis2ws.StatusDB.getStatusByUID(StatusServiceInterfaceSkeleton.java:1204)
    at org.cogkit.cyberaide.axis2ws.StatusServiceInterfaceSkeleton.getJSONStatusByUID(StatusServiceInterfaceSkeleton.java:184)
    at org.cogkit.cyberaide.axis2ws.StatusServiceInterfaceMessageReceiverInOut.invokeBusinessLogic(StatusServiceInterfaceMessageRece
iverInOut.java:80)
    at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.invokeBusinessLogic(AbstractInOutSyncMessageReceiver.java:42)
    at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:96)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145)
    at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
    at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:595)&lt;/pre&gt;
&lt;p&gt;It seems that the error results from incompatible type conversion. I am sure I followed the instructions elaborated in the official document. &lt;/p&gt;
&lt;p&gt;Then, I tried SODA. The output was weirder. The program could not function as I expected. State information could not be retrieved successfully. However, when I investigated tomcat log, no error report existed in log!!! So, I had no way to tell what happened under the hood. This was pretty annoying. It seemed that Db4o indeed retrieved something. However, the fields of the object retrieved are invalid. &lt;/p&gt;
&lt;p&gt;I read almost all posts in Db4o forum/community. I tried all suggested solutions. But it still doesn't work. I tried different versions of Db4o, none of them solved my problem.&lt;/p&gt;
&lt;p&gt;It has taken me lots of time. Currently, I am not sure whether I can solve it finally...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1648223952867983546?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1648223952867983546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1648223952867983546' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1648223952867983546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1648223952867983546'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/03/db4o-corrupts-in-tomcat-with-axis2.html' title='DB4O corrupts in Tomcat with Axis2'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-1169200786132523396</id><published>2008-03-17T16:40:00.002-04:00</published><updated>2008-03-17T16:45:45.358-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='db4o'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><title type='text'>State Information Persistence (Status server)</title><content type='html'>Previously, state information of all workflows in status server is kept in memory. As you know, this strategy is not practical if there is too much information so that it cannot fit into memory. In other words, data persistence is necessary. Actually, after careful investigation, I found two solutions. &lt;br&gt;(1) &lt;span class="myh2"&gt;Cache&lt;/span&gt;  &lt;div class="indentparagraph"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This strategy stores some data in hard disk. And the data recently used is saved in memory to enhance performance. So it is kind of data-centric mechanism making use of locality. &lt;br&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ehcache&lt;/em&gt;&lt;/strong&gt;(&lt;a title="http://ehcache.sourceforge.net/" href="http://ehcache.sourceforge.net/"&gt;http://ehcache.sourceforge.net/&lt;/a&gt;) is a project based on this strategy. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; In order to put data into cache, you MUST construct a &lt;strong&gt;&lt;em&gt;element&lt;/em&gt;&lt;/strong&gt; object which contains key and value. From ehcache 1.2 the key and value can be serializable objects which improve the flexibility. The unique way for data query is to specify a key object. Obviously, much work must be done to compose complex query. &lt;strong&gt;&lt;em&gt;Ehcache&lt;/em&gt;&lt;/strong&gt; provides ways for users to control every aspect of cache behaviors. &lt;/div&gt;(2) &lt;span class="myh2"&gt;Database&lt;/span&gt;  &lt;div class="indentparagraph"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This strategy makes use of database to store information. There is a corresponding name : object database. The database provides interfaces by which common database operations (insert/query/update/delete) can be invoked. However, this kind of database is different from traditional relation database. The unit of manipulation in object database is an object. In other words, you can insert/query/delete objects instead of tuples. In addition to retrieval of field value in a specific object, member functions of the object can also be invoked.&lt;br&gt;&lt;strong&gt;&lt;em&gt;Db4o&lt;/em&gt;&lt;/strong&gt;(&lt;a title="http://www.db4o.com/" href="http://www.db4o.com/"&gt;http://www.db4o.com/&lt;/a&gt;) is an object database. Here is a simple introduction written by me: &lt;a title="http://zhenhua-guo.blogspot.com/2008/03/db4o-introduction.html" href="http://zhenhua-guo.blogspot.com/2008/03/db4o-introduction.html"&gt;http://zhenhua-guo.blogspot.com/2008/03/db4o-introduction.html&lt;/a&gt;. &lt;/div&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Actually, these two strategies are not competitive. Implementation of object database may make use of cache mechanism. So it is not surprising to hear that some great applications (hibernate, Spring...) use &lt;strong&gt;&lt;em&gt;Ehcache&lt;/em&gt;&lt;/strong&gt;. For upper level programmers, I think object database should be easier to work on. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; At last, I decided to apply DB4O to our project. One important reason is that this strategy lets programmers write code in high level. I don't need to care about any details of database infrastructure. As a result, modification of my original code is little so that it can be done quickly. Moreover, maintenance of code is easier. We store both data and related operations in database instead of scattered places. What's more, support of query is more powerful in DB4O than in Ehcache. It supports three kinds of query languages: Query By Example, Native Queries and SODA. And complex query can be composed easily. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;One lesson&lt;/strong&gt;: when dealing with data retrieved from object database, users MUST be careful about type conversion so that incompatible conversion won't occur. Because this kind of errors don't appear until run time, debugging becomes more difficult especially for web applications. I was aware of cause of the error by careful reading lengthy Tomcat log. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp; State information of workflows is stored in hard disk and cached in memory by using DB4O. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-1169200786132523396?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/1169200786132523396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=1169200786132523396' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1169200786132523396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/1169200786132523396'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/03/state-information-persistence-status.html' title='State Information Persistence (Status server)'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-4845595896067384734</id><published>2008-03-17T15:20:00.002-04:00</published><updated>2008-03-17T15:21:48.983-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='db4o'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>DB4O introduction</title><content type='html'>&lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;Db4o is a high-performance object database for Java and .NET. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l0 level1 lfo2; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;Ø&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Open db&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background: #e0e0e0"&gt;ObjectContainer db = Db4o.openFile(filename);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l0 level1 lfo2; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l0 level1 lfo2; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;Ø&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Insert&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 18pt"&gt;&lt;span lang="EN-US"&gt;Objects are inserted by using &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;set()&lt;/i&gt;&lt;/b&gt; method.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 18pt"&gt;&lt;span lang="EN-US"&gt;ClassName obj = new ClassName(parameters);&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 18pt"&gt;&lt;span lang="EN-US"&gt;db.set(obj);&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;Ø&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Retrieve&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 18pt; text-indent: -18pt; mso-list: l1 level2 lfo1"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(1)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Query by Example (QBE)&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Create a prototypical object for db4o to use as an example of what you wish to retrieve. Db4o will return all of the objects which match all non-default field values. The results will be returned as an &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;ObjectSet&lt;/i&gt;&lt;/b&gt; instance. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;ClassName obj = new ClassName(values…); //prototypical object&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;ObjectSet result = db.get( obj );&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;listResult( result );&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;Db4o supplies a shortcut to retrieve all instances of a class:&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US" style="background: #e0e0e0"&gt;ObjectSet result = db.get(ClassName.class);&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;Following code can be used to iterate over the results:&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;while( result.hasNext() ){&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;System.out.println( result.next() );&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 18pt; text-indent: -18pt; mso-list: l1 level2 lfo1"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(2)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;Native Query(NQ) --- main db4o querying interface.&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Native Queries provide the ability to run one or more lines of code against all instances of a class. Native query expressions return true to mark specific instances as part of the result set. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;List&amp;lt;ClassName&amp;gt; objs = db.query( new Predicate&amp;lt;ClassName&amp;gt;() {&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public Boolean &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;match&lt;/i&gt;&lt;/b&gt;(ClassName obj){&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return obj.getProperty() == value;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Users must be very careful with side effects --- especially those that might affect persistent objects. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 18pt; text-indent: -18pt; mso-list: l1 level2 lfo1"&gt;&lt;span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'"&gt;&lt;span style="mso-list: ignore"&gt;(3)&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;SODA Query API&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;Ø&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Updating objects is as easy as storing them. You use the same &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;set()&lt;/i&gt;&lt;/b&gt; method to update objects: just call &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;set()&lt;/i&gt;&lt;/b&gt; again modifying any object. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;ObjectSet result = db.get(new ClassName(parameters));&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;ClassName found = (ClassName)result.next();&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;found.methodName(parameters);&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 10.5pt; mso-para-margin-left: 1.0gd"&gt;&lt;span lang="EN-US"&gt;db.set(found);&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;Note: we query the object first. If the object is not ‘known’ (having been previously stored or retrieved during the current session), db4o will insert a new object instead of updating existing object. In this case, db4o think that you want to insert a new object which has the same field values. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt 0pt 0pt 21pt; text-indent: -21pt; mso-list: l0 level1 lfo2; tab-stops: list 21.0pt"&gt;&lt;span lang="EN-US" style="font-family: wingdings; mso-fareast-font-family: wingdings; mso-bidi-font-family: wingdings"&gt;&lt;span style="mso-list: ignore"&gt;Ø&lt;span style="font: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;strong&gt;Delete&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin: 0pt"&gt;&lt;span lang="EN-US"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Objects are removed by using &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;delete()&lt;/i&gt;&lt;/b&gt; method. &lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;ObjectSet result = db.get( new ClassName(…));&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;ClassName found = (ClassName)result.next();&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="background: #e0e0e0; margin: 0pt 0pt 0pt 21pt; mso-para-margin-left: 2.0gd"&gt;&lt;span lang="EN-US"&gt;db.delete( found );&lt;/span&gt;&lt;/p&gt; &lt;p&gt;If you want to tune DB4O to get higher performance, you need to change the default configuration. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-4845595896067384734?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/4845595896067384734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=4845595896067384734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4845595896067384734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/4845595896067384734'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/03/db4o-introduction.html' title='DB4O introduction'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-7588945428940005615</id><published>2008-03-13T17:18:00.001-04:00</published><updated>2008-03-13T17:25:48.825-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='workflow'/><title type='text'></title><content type='html'>&lt;h1 class="western" style="margin-top: 0in; margin-bottom: 0in;" align="center"&gt; &lt;font style="font-size: 15pt;" size="4"&gt;Some workflow related projects&lt;/font&gt;&lt;/h1&gt; &lt;h3 class="western" style="margin-top: 0in; margin-bottom: 0in; line-height: 172%;"&gt; &lt;font size="3"&gt;DIET&lt;/font&gt;&lt;/h3&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;font color="#0000ff"&gt;&lt;u&gt;&lt;a href="http://graal.ens-lyon.fr/DIET/"&gt;http://graal.ens-lyon.fr/DIET/&lt;/a&gt;&lt;/u&gt;&lt;/font&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;DIET (Distributed Interactive Engineering Toolbox) seems to be similar to Condor. DIET is based on &lt;b&gt;Grid-RPC&lt;/b&gt;. Clients submit computation requests to a scheduler whose goal is to find a server available on the grid. &lt;b&gt;&lt;i&gt;The aim of the DIET project is to develop a set of tools to build computational &lt;font color="#ff0000"&gt;servers&lt;/font&gt;.&lt;/i&gt;&lt;/b&gt; Scheduling is frequently applied to balance the work among the servers and a list of available servers is sent back to the client; the client is then able to send the data and the request to one of the suggested servers to solve their problem. The Distributed Interactive Engineering Toolbox (DIET) project is focused on the &lt;b&gt;&lt;i&gt;development of scalable middleware with initial efforts focused on distributing the scheduling problem across multiple agents.&lt;/i&gt;&lt;/b&gt; DIET consists of a set of elements that can be used together to build applications using the Grid-RPC paradigm.&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;So the goal of DIET project is different from that of our project.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;br&gt; &lt;/p&gt; &lt;h3 class="western" style="margin-top: 0in; margin-bottom: 0in; line-height: 172%;"&gt; &lt;font size="3"&gt;Taverna&lt;/font&gt;&lt;/h3&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Recently, I installed and tried Taverna. Then I investigated its functionality in detail.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Its manual is here: &lt;font color="#0000ff"&gt;&lt;u&gt;&lt;a href="http://www.mygrid.org.uk/usermanual1.7"&gt;http://www.mygrid.org.uk/usermanual1.7&lt;/a&gt;&lt;/u&gt;&lt;/font&gt;. &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Taverna is created by myGrid project and is a tool used for designing and executing workflows. “It provides a desktop authoring environment and enactment engine for scientific workflows expressed in SCUFL (Simple Conceptual Unified Flow Language).” SCUFL is proprietary. As a result, I can not find detailed information about SCUFL.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Services are connected with data links (providing data flow) and control links (coordination of services not connected through data flow).  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;b&gt;Several features:&lt;/b&gt;&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Fault Tolerance&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Retries for every   processor&lt;/p&gt;  &lt;/li&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; If a certain processor fails to execute, it will be retried several times. Users can specify maximum number of retries, delay of retries and backoff. Backoff is a factor determining how much the delay time increases for subsequent retries beyond the first.  &lt;/p&gt; &lt;ol&gt;  &lt;ul&gt;   &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Alternative   processor&lt;/p&gt;  &lt;/li&gt;&lt;/ul&gt; &lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Users can specify an alternative processor or list of processors which perform the same task as the primary processor. And the alternate is used in place of the main processor if the latter has failed. Note: the alternate has its own definable parameters for ‘Retries’, ‘Delay’ and ‘Backoff’.  &lt;/p&gt; &lt;ol start="2"&gt;  &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Iteration&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Taverna supports two kinds of iteration. They are dot and cross. Cross iteration is an &lt;i&gt;all-against-all&lt;/i&gt; iteration which means it iterates over all combinations of input values. For dot iteration, the first item for one input is related to the first item in the other input and the second item for one input is related to the second item in the other input…&lt;/p&gt; &lt;ol start="3"&gt;  &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Services&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Taverna provides some built-in services. Among them are XML transformation, base64 encoding/decoding, write text file… Besides, beanshell and RShell are supported as well.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; It also supports some well-known bioinformatics services including Soaplab, Biomart, Biomoby. I am not familiar with biology related tools. So I am not sure whether these services are based on web services.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Besides, Taverna supports a functionality called WSDL scavenger. Users can specify address of WSDL document and Taverna will automatically fetch the WSDL document and analyze its content to extract supported operations. Then supported operations in the WSDL document are added to list of available processors so that users can make use of them easily in course of workflow composition.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; In addition, Taverna can scavenge existing workflow and extract processors.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; Taverna is a tool designed specifically for Bioinformatics. However, some features may be also useful even if they are applied to more generic applications. These features include WSDL scavenger, dot/cross iteration, fault tolerance…&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; It is different from our project as Taverna is not based on Grid. The enactment engine is located in client-side machine. In our project, enactment engine is located at server side which makes use of Java CoG kit to manage execution of workflows.&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;b&gt;Social website myExperiment&lt;/b&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; This web site supports finding and sharing of workflows and has special support for Scufl workflows. Users can download workflows posted on the site. For every workflow written in Scufl, there is a corresponding .svg image which is easier to understand and verbose xml Scufl document.  &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt; It seems that myExperiment supports almost all functionalities most web2.0 web site supports. They include user management, group management, workflow management, blog, forum, tagging, rating, and commenting. Moreover, some statistics (number of reviews, number of comments…) is done.  &lt;/p&gt; &lt;h3 class="western" style="margin-top: 0in; margin-bottom: 0in; line-height: 172%;"&gt; &lt;font size="3"&gt;Moteur&lt;/font&gt;&lt;/h3&gt; &lt;p class="western" style="border-style: none none double; border-color: -moz-use-text-color -moz-use-text-color rgb(0, 0, 0); border-width: medium medium 1.1pt; padding: 0in 0in 0.01in; margin-bottom: 0in;"&gt;  This project is also based on SCUFL.  &lt;/p&gt; &lt;p class="western" style="border-style: none none double; border-color: -moz-use-text-color -moz-use-text-color rgb(0, 0, 0); border-width: medium medium 1.1pt; padding: 0in 0in 0.01in; margin-bottom: 0in;"&gt; &lt;br&gt; &lt;/p&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;b&gt;Karajan Workflow:&lt;/b&gt;&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;&lt;p class="western" style="margin-bottom: 0in;"&gt;Is there a way to  invoke some operations described in a WSDL document?&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0in;"&gt;&lt;br&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-7588945428940005615?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/7588945428940005615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=7588945428940005615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7588945428940005615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/7588945428940005615'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/03/some-workflow-related-projects-diet.html' title=''/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-2737953746843232251</id><published>2008-02-21T22:58:00.000-05:00</published><updated>2008-02-21T22:59:12.141-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaCOG'/><title type='text'>DAG construction</title><content type='html'>&lt;p&gt;After communication with Mike, I got the &lt;em&gt;dag.k&lt;/em&gt; file. Then I implemented the construction of DAG workflow based on all jobs and their relationship in a workflow. In other words, I put together all this information in a large Karajan workflow by using DAG. Note: this work is done at client side, not at server side. After construction of the huge workflow, it can be submitted to server just as a small job. Then id of the new submitted workflow will be returned. Based on this workflow id, a user can query state of the workflow. In addition, the user can access output files of the workflow by using common HTTP GET request. &lt;/p&gt; &lt;p&gt;More details about DAG construction:&lt;br&gt;Assume that we have four jobs in a workflow: &lt;em&gt;job1&lt;/em&gt;, &lt;em&gt;job2&lt;/em&gt;, &lt;em&gt;job3&lt;/em&gt;, &lt;em&gt;job4&lt;/em&gt;.&lt;br&gt;And their dependencies are:&lt;br&gt;&lt;em&gt;job1 -&amp;gt; job2&lt;/em&gt; ( this means &lt;em&gt;job2&lt;/em&gt; depends on &lt;em&gt;job1&lt;/em&gt; )&lt;br&gt;&lt;em&gt;job1 -&amp;gt; job3&lt;br&gt;job3 -&amp;gt; job4&lt;/em&gt;&lt;br&gt;&lt;em&gt;job3&lt;/em&gt; -&amp;gt; &lt;em&gt;job5&lt;/em&gt;&lt;br&gt;&lt;em&gt;job1&lt;/em&gt; -&amp;gt; &lt;em&gt;job5&lt;/em&gt;&lt;br&gt;These dependencies are represented in following graph:&lt;br&gt;&lt;a href="http://lh6.google.com/Jenvor/R75Ijt9JtBI/AAAAAAAAAIU/PUGFpsg39Q0/sample_workflow%5B4%5D"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 10px 0px 10px 10px; border-right-width: 0px" height="157" alt="sample_workflow" src="http://lh3.google.com/Jenvor/R75Ij99JtCI/AAAAAAAAAIc/Y40cVxgpXEY/sample_workflow_thumb%5B2%5D" width="219" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;Then constructed DAG workflow looks like this:&lt;br&gt;&lt;font color="#7d7d7d"&gt;&amp;lt;project&amp;gt;&lt;br&gt;&amp;lt;include file="cogkit.k"/&amp;gt;&lt;br&gt;&amp;lt;include file="dag.k"/&amp;gt;&lt;br&gt;&amp;lt;discard&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dag&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;&lt;font color="#0000ff"&gt;job1&lt;/font&gt;&amp;lt;/string&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Here is name of the job.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;quotedlist/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt; content of job1&lt;/font&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;edges&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;&lt;font color="#0000ff"&gt;job2&lt;/font&gt;&amp;lt;/string&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Here, it describes that job1 is prerequisite of job2, job3 and job5&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;&lt;font color="#0000ff"&gt;job3&lt;/font&gt;&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;&lt;font color="#0000ff"&gt;job5&lt;/font&gt;&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/edges&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job2&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;quotedlist/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; content of job2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job3&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;quotedlist/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; content of job3&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;edges&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job4&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job5&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/edges&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job4&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;quotedlist/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; content of job4&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;string&amp;gt;job4&amp;lt;/string&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;quotedlist/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; content of job4&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/element&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/node&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dag&amp;gt;&lt;br&gt;&amp;lt;/discard&amp;gt;&lt;br&gt;&amp;lt;/project&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-2737953746843232251?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/2737953746843232251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=2737953746843232251' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2737953746843232251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/2737953746843232251'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/02/dag-construction.html' title='DAG construction'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-6124735869482463284</id><published>2008-02-21T22:21:00.001-05:00</published><updated>2008-02-21T22:21:59.952-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaCOG'/><title type='text'>Karajan Workflow Formats: .k and .xml</title><content type='html'>&lt;p&gt;In CoGKit, there are two supported formats in Karajan workflow -- .k and .xml. &lt;br&gt;Personally, I like xml because of its prevalence and openness. There are many handy tools which can process xml documents in various ways. Unfortunately, xml support in Karajan workflow is not comprehensive. In recent programming, I need to use element &lt;em&gt;dag&lt;/em&gt; which is used to support Directed Acyclic Graph. &lt;br&gt;(1) At first, Karajan workflow supports DAG. But it does not give users a &lt;em&gt;dag.xml&lt;/em&gt; file to import. Instead, just &lt;em&gt;dag.k&lt;/em&gt; is provided. So I need to find a way to convert &lt;em&gt;dag.k&lt;/em&gt; to &lt;em&gt;dag.xml&lt;/em&gt;. Thank Mike and Gregor to help me get out of the struggle. Following method can be used to do the task:&lt;pre&gt;cog-workflow -intermediate dag.k&lt;/pre&gt;
&lt;p&gt;Although following error pops up, I still can get the file I need (&lt;em&gt;dag.xml).&lt;/p&gt;&lt;pre&gt;&lt;/em&gt;Execution failed:&lt;br&gt;Variable not found: #channel#defs&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kernel:export @ dag.k, line: 44&lt;/pre&gt;
&lt;p&gt;Note: actually, what is generated is &lt;em&gt;dag.kml&lt;/em&gt; not &lt;em&gt;dag.xml&lt;/em&gt;. Currently, I assume they are the same because I have no better choice. &lt;/p&gt;
&lt;p&gt;(2) In document I can find, sample workflows about DAG are written in .k format. &lt;br&gt;This is the unique resource I find helpful: &lt;a title="http://wiki.cogkit.org/index.php/Java_CoG_Kit_Workflow_Guide#Direct_Acyclic_Graphs" href="http://wiki.cogkit.org/index.php/Java_CoG_Kit_Workflow_Guide#Direct_Acyclic_Graphs"&gt;http://wiki.cogkit.org/index.php/Java_CoG_Kit_Workflow_Guide#Direct_Acyclic_Graphs&lt;/a&gt;.&lt;br&gt;Once again, I used command &lt;em&gt;cog-workflow&lt;/em&gt; to do this task. But the generated .&lt;em&gt;kml(xml)&lt;/em&gt; file is lengthy and not appropriate for human readers. So, I decided to convert it manually by myself. I found this useful link(&lt;a title="http://wiki.cogkit.org/index.php/Java_CoG_Kit_Karajan_Workflow_Reference_Manual_4.1.5" href="http://wiki.cogkit.org/index.php/Java_CoG_Kit_Karajan_Workflow_Reference_Manual_4.1.5"&gt;http://wiki.cogkit.org/index.php/Java_CoG_Kit_Karajan_Workflow_Reference_Manual_4.1.5&lt;/a&gt;) which describes both formats in detail.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-6124735869482463284?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/6124735869482463284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=6124735869482463284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6124735869482463284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/6124735869482463284'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/02/karajan-workflow-formats-k-and-xml.html' title='Karajan Workflow Formats: .k and .xml'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-3229157198344678614</id><published>2008-02-21T22:16:00.001-05:00</published><updated>2008-02-21T22:17:59.821-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaCOG'/><title type='text'>How to access results?</title><content type='html'>&lt;p&gt;Now, it is time to consider how to make users easily and conveniently access the results of their workflows. There are several questions here:&lt;br&gt;(1) How to track output files in Karajan workflows?  &lt;div style="margin-left: 2em"&gt;The first option is to analyze content of the Karajan workflow to figure out output files. For example, for element &lt;em&gt;execute&lt;/em&gt;, attribute &lt;em&gt;stdout&lt;/em&gt; indicates the name of output file. &lt;br&gt;&amp;lt;execute executable="/bin/date"&lt;strong&gt; &lt;font color="#070de2"&gt;stdout="thedate"&lt;/font&gt;&lt;/strong&gt; host="gf1.ucs.indiana.edu" provider="GT2" redirect="false"/&amp;gt;&lt;br&gt;However, if we use this method to track all output files, it is difficult and time-consuming because it is possible that many elements generate output files. As a result, we must capture possible output files from all these elements. &lt;br&gt;Another option I can think of is kind of tricky. The newly submitted workflow is executed in a newly created directory. After execution, the files (except workflow file) in the directory are output files. This is the method I am using in my implementation.&lt;/div&gt;(2) How to organize output files?  &lt;div style="margin-left: 2em"&gt;For the same workflow, we can categorize it based on different criteria. For example, we can categorize a workflow based on the date on which it is submitted, or the date on which it is completed... I would like to make use of workflow id and user id to categorize the workflows. All workflows submitted by a user belong to the same group which can be accessed by this user. Within these workflows, workflow id is used by the user to access a specified workflow. The id of every workflow belonging to a user is unique.&lt;br&gt;So, the directory layout may look like this:&lt;br&gt;&lt;font color="#909090"&gt;users/user1/workflow_122/output_file1&lt;/font&gt;&lt;/div&gt; &lt;div style="margin-left: 2em"&gt;&lt;font color="#909090"&gt;users/user1/workflow_122/output_file2&lt;br&gt;users/user2/workflow_1/output_file1&lt;br&gt;...&lt;/font&gt;&lt;/div&gt;(3) How can users access output files?&lt;br&gt; &lt;div style="margin-left: 2em"&gt;After talking with Marlon, I would like to provide RESTful interface by which users can retrieve output files. In my implementation, URLs to access output files look like this:&lt;br&gt;&lt;a href="http://domain:port/resources/user_name/workflow_id/"&gt;http://domain:port/resources/user_name/workflow_id/&lt;/a&gt; This retrieves list of all output files for the corresponding workflow.&lt;br&gt;&lt;a href="http://domain:port/resources/user_name/workflow_id/output_file"&gt;http://domain:port/resources/user_name/workflow_id/output_file&lt;/a&gt; This will retrieve the specified output file directly. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-3229157198344678614?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/3229157198344678614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=3229157198344678614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3229157198344678614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/3229157198344678614'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/02/how-to-access-results.html' title='How to access results?'/><author><name>Gerald Guo</name><uri>http://www.blogger.com/profile/06379139111711649958</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-36974838.post-5323263644142889051</id><published>2008-02-15T17:57:00.000-05:00</published><updated>2008-02-17T16:28:29.198-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><title type='text'>RESTful web services in Java</title><content type='html'>&lt;p&gt;Recently, I read some articles about RESTful web services and I am looking for some java libraries which have great support for REST. REST is supported by Axis2. However, the support is very limited. First, document(&lt;a title="http://ws.apache.org/axis2/1_3/rest-ws.html" href="http://ws.apache.org/axis2/1_3/rest-ws.html"&gt;http://ws.apache.org/axis2/1_3/rest-ws.html&lt;/a&gt;) of REST support in the official web site is horrible. The content is very very brief so that I have more questions and confusions than what have been addressed by that document. Support for REST in Axis2 relies on a new feature in WSDL2 which enables HTTP binding. Here is a good article about it:&lt;a title="http://www.ibm.com/developerworks/webservices/library/ws-rest1/" href="http://www.ibm.com/developerworks/webservices/library/ws-rest1/"&gt;http://www.ibm.com/developerworks/webservices/library/ws-rest1/&lt;/a&gt;. However, HTTP binding doesn't enable programmers to implement a full REST style system. I did not dig into WSDL2 to get more knowledge about its HTTP binding. Here(&lt;a title="http://wso2.org/blog/footballsoccerpainting/949" href="http://wso2.org/blog/footballsoccerpainting/949"&gt;http://wso2.org/blog/footballsoccerpainting/949&lt;/a&gt;) is an article from someone else who complains Axis2.&lt;br&gt;Then, I found that JCP published a Java API specification about RESTful web services. It is JSR-311(&lt;a title="http://jcp.org/en/jsr/detail?id=311" href="http://jcp.org/en/jsr/detail?id=311"&gt;http://jcp.org/en/jsr/detail?id=311&lt;/a&gt;). That looks pretty good because now we have a standard about how to use REST in Java. Jersey(&lt;a title="https://jersey.dev.java.net/" href="https://jersey.dev.java.net/"&gt;https://jersey.dev.java.net/&lt;/a&gt;) is reference implementation of the specification. Besides Jersey, Restlet(&lt;a title="http://www.restlet.org/" href="http://www.restlet.org/"&gt;http://www.restlet.org/&lt;/a&gt;) is another implementation which provides more features. Note that the specification itself is still in beta phase.&lt;/p&gt; &lt;p&gt;I decided to try Jersey. First download and unpack it. &lt;br&gt;Sample code:&lt;pre class="java:nocontrols" name="code"&gt;@Path("/")
public class RESTTest{
    @HttpContext UriInfo uriInfo;	
    
    @GET
    @ProduceMime("text/plain")
    public String getUserAll(){
    	return "You want to retrieve information about all users.";
    }
    
    @Path("{user}")
    public UserResource getUserInfoAsText(@UriParam("user") String userid){
    	return new UserResource(userid);
    }
}
&lt;/pre&gt;Most readers have noticed that Java annotation is used frequently. I think this method is handy and convenient.   &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/36974838-5323263644142889051?l=cglreport.zhenhua.info' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cglreport.zhenhua.info/feeds/5323263644142889051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=36974838&amp;postID=5323263644142889051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5323263644142889051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/36974838/posts/default/5323263644142889051'/><link rel='alternate' type='text/html' href='http://cglreport.zhenhua.info/2008/02/restful-web-services-in-java.html' title='RESTful web services in Java
