tag:blogger.com,1999:blog-139377342024-03-13T03:03:43.359-07:00Tips for software engineerTips that make life of a software engineer easier.
Well, not exactly. Some posts are open questions that I haven't found an answer ... yetGuogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.comBlogger181125tag:blogger.com,1999:blog-13937734.post-25953943471691013162019-10-05T23:00:00.000-07:002019-10-05T23:00:03.262-07:00Enterprise Integration Recipe: File Transfer Using Google Cloud Storage<br />
This is one of a series of recipes on how to use products offered by <a href="https://cloud.google.com/products" target="_blank">Google Cloud Platform</a> to implement enterprise integration solutions.<br />
<br />
GCP Product used in this article: <br />
<ul>
<li><a href="https://cloud.google.com/storage/" target="_blank">Google Cloud Storage</a>, </li>
<li><a href="https://cloud.google.com/pubsub/" target="_blank">Google Cloud Pub/Sub</a>, </li>
<li><a href="https://cloud.google.com/functions/" target="_blank">Google Cloud Functions</a></li>
</ul>
<h2>
Implementation</h2>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsMToAVOKDXa1Eho9h7uwRBC2zU1j0Cve3CPHehr3vrhEUV4p6pFnSeVyo-4V0jX9pIQ1tfCoJQZT_VhG9HDI27pKpkSqFXCE14W2mA8SMgYFDoj-MsXNluiomDj3Aene1jXbIrA/s1600/Screen+Shot+2019-10-05+at+7.56.29+PM.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="System Diagram" border="0" data-original-height="872" data-original-width="1600" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsMToAVOKDXa1Eho9h7uwRBC2zU1j0Cve3CPHehr3vrhEUV4p6pFnSeVyo-4V0jX9pIQ1tfCoJQZT_VhG9HDI27pKpkSqFXCE14W2mA8SMgYFDoj-MsXNluiomDj3Aene1jXbIrA/s400/Screen+Shot+2019-10-05+at+7.56.29+PM.png" title="" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">System Diagram</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaC9R9K6D_a5FUkutGYLLN9bFWJtcHemHbc7u5fWO2sQ0DDroiati6nGj1GWseWptbCFawCRNjT3dvGR2vYyRtfs1jK16nM1iYE9GiIp1Oljerizhe14ce5uzUxzsH0pqiybobMw/s1600/Screen+Shot+2019-10-05+at+7.55.52+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Flow Chart for Subscriber" border="0" data-original-height="1122" data-original-width="1284" height="347" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaC9R9K6D_a5FUkutGYLLN9bFWJtcHemHbc7u5fWO2sQ0DDroiati6nGj1GWseWptbCFawCRNjT3dvGR2vYyRtfs1jK16nM1iYE9GiIp1Oljerizhe14ce5uzUxzsH0pqiybobMw/s400/Screen+Shot+2019-10-05+at+7.55.52+PM.png" title="" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Flow Chart for Subscriber</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
Recipe:<br />
<ul>
<li><a href="https://github.com/huguogang/enterprise-integration-gcp/blob/master/terraform/gcs.tf" target="_blank">gcs.tf</a>: TerraForm code that provision and configure all GCP resource needed</li>
<li><a href="https://github.com/huguogang/enterprise-integration-gcp/blob/master/README.md">README.md</a>: up to date instruction on how to use the recipe</li>
</ul>
Noteworthy Tips:<br />
<ul>
<li><a href="https://cloud.google.com/storage/docs/managing-lifecycles">GCS Object Lifecycle</a>: make it easy to configure archive and error box. We should move old files to cold or nearline storage and eventually purge them. No more custom CRON jobs for this chore;</li>
<li><a href="https://cloud.google.com/storage/docs/pubsub-notifications">Pubsub Notification for GCS</a>: we configured notification for inbox "<span style="font-family: "Courier New", Courier, monospace;">OBJECT_FINALIZE</span>" event. Again no more CRON jobs needed to scan folders for new files. Another advantage is that the subscriber do not need to worry if we might be dealing with partially uploaded file;</li>
<li><a href="https://cloud.google.com/monitoring/api/metrics_gcp#gcp-storage">Stackdriver Monitoring or GCS</a>: not configured in the recipe. But definitely worth exploring. For example, "<span style="font-family: "Courier New", Courier, monospace;">object_count</span>" might be used to monitor error box, and send alert when we see the count increasing too fast;</li>
<li>Retry: this recipe implemented retry by simply do not "<span style="font-family: "Courier New", Courier, monospace;">ACK</span>" CPS messages. Cloud Pubsub will send notification again after <span style="font-family: "Courier New", Courier, monospace;">ACK</span> deadline expired for 7 days. So retry is implemented by CPS subscription's <a href="https://cloud.google.com/pubsub/docs/subscriber#at-least-once-delivery">At-Least-Once Delivery</a> feature. If want a shorter total retry period, you can add a line of code to check age of a message and mark it non-retriable if message age is over threshold. This approach saves the trouble of implementing reliably retry mechanism. Downside is lost control of retry intervals (for example, there is no exponential backoff retry)</li>
</ul>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-13971430800107115922016-07-18T15:51:00.003-07:002016-07-18T15:51:20.710-07:00"Permission denied to generate login hint for target domain."Google OAuth Error Message: Permission denied to generate login hint for target domain.<br />
<br />
<b>Root Cause</b>: development server, was using <a href="http://127.0.0.1:8080/">http://127.0.0.1:8080</a>, even if I added it to cloud config, does not work. But once I change to <a href="http://localhost:8080/">http://localhost:8080</a>, it starts to work.Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-24115942143304835032016-06-21T23:02:00.000-07:002016-06-23T21:45:39.056-07:00Summer Fun with Google BigQueryNothing beats a game that can keep the whole family entertained for a few hours, while teaching kids some programming sense.
<br />
<br />
Just two weeks into summer, I already ran out of ideas to keep kids entertained.<br />
<br />
Today, Google BigQuery come to the rescue. To be more precise, the <a href="https://cloud.google.com/bigquery/public-data/usa-names" target="_blank">USA Name Data</a> provided hours of entertainment.<br />
<blockquote class="tr_bq">
"This public dataset was created by the Social Security Administration
and contains all names from Social Security card applications for births
that occurred in the United States after 1879."</blockquote>
<br />
After showing my kids a few very simple queries of the <a href="https://cloud.google.com/bigquery/public-data/usa-names" target="_blank">USA Name Data</a>, we started to play "Family Feud" game:<br />
<h2>
Most Popular Names</h2>
<ul>
<li>Everyone write down 5 names in secret</li>
<li>After we are done, each need to write their own query and run it in BQ to find out total count of these five names in all years</li>
<li>Whoever gets the most counts wins</li>
<li>Cannot reuse names in the following rounds</li>
</ul>
(After three rounds, we covered almost all the top 20 names in USA.)<br />
<br />
Then we played another game with the dataset with these rules<br />
<h2>
Least Popular Names</h2>
<ul>
<li>Write down 5 names in secret</li>
<li>The names must draw at least one count</li>
<li>Whoever gets the least counts wins</li>
</ul>
(We actually got one name with only 5 in all the last 103 years!)<br />
<br />
Here is a sample query<br />
<br />
<pre class="js" name="code">SELECT SUM(number), name
FROM [bigquery-public-data:usa_names.usa_1910_2013]
WHERE name in ('John', 'Jason', 'Mary', 'David', 'William')
GROUP BY name
</pre>
<br />
Now, after we are done with the game, the following two queries will show us the top answers.
<br />
<h2>
Least Popular Names</h2>
<pre class="js" name="code">SELECT SUM(number), name
FROM [bigquery-public-data:usa_names.usa_1910_2013]
GROUP BY name
ORDER BY 1
</pre>
<h2>
Most Popular Names</h2>
<pre class="js" name="code">SELECT SUM(number), name
FROM [bigquery-public-data:usa_names.usa_1910_2013]
GROUP BY name
ORDER BY 1 DESC
</pre>
<h2>
Some Follow Up Questions</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9FJUhN_id-gJj8fEVFiVakmYr3pTfwWL3cX0q_UxJlpHZ7dCtqkJWFUAV7jHi7X90EYMBwdSm3x8hrrOEf36VmH2LJVDTQvJ-fa6w4if-CWfgLCd_pjqE69NlsEyupOYJTe8_uA/s1600/Screen+Shot+2016-06-22+at+11.31.10+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9FJUhN_id-gJj8fEVFiVakmYr3pTfwWL3cX0q_UxJlpHZ7dCtqkJWFUAV7jHi7X90EYMBwdSm3x8hrrOEf36VmH2LJVDTQvJ-fa6w4if-CWfgLCd_pjqE69NlsEyupOYJTe8_uA/s400/Screen+Shot+2016-06-22+at+11.31.10+PM.png" width="400" /></a></div>
While the kids are still keen on it, some follow up questions will keep their brains from getting rusty:<br />
<ul>
<li>How many kids were born in the same year, and with the same name as yours?</li>
<li>Which year has the most kids with the same name as yours?</li>
<li>Are there any kids with your name in the opposite gender?</li>
<li>Which years are "baby boom" years? (Hint: save to Google Sheet, and plot year vs. count(number))</li>
<li>Which years have the most "Jacqueline"s and why? (Hint: opportunity for some history lessons about first ladies)</li>
<li>Most gender neutral names (Hint: refer to <a href="https://www.reddit.com/r/bigquery/comments/2t94om/dataset_us_baby_names_1910_to_2013/" target="_blank">this page</a>) </li>
</ul>
<br />
<ul>
</ul>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-33864171670181895662016-05-17T23:18:00.000-07:002016-05-22T22:36:17.238-07:00Angular 2: Building a Google Map Component<a href="https://developertips.firebaseapp.com/google_map.html" target="_blank">Live Demo</a><br />
<a href="https://github.com/huguogang/ng2tsdemo" target="_blank">Github Repo</a><br />
<br />
In order to force myself dig deeper into Angular 2, I tried to build a component wrapper for <a href="https://developers.google.com/maps/documentation/javascript/">Google Map JavaScript API</a>. The end results is a demo component here: <a href="https://github.com/huguogang/ng2tsdemo/blob/master/app/google_map/google_map.component.ts">google_map.component.ts</a>.<br />
<h3>
</h3>
<h3>
Sample Client Code</h3>
A sample client code using the component looks like this:
<script src="https://gist.github.com/huguogang/6137003610d3ce7523acfb6c139a38ea.js"></script><br />
<h3>
Features</h3>
The features including:<br />
<ul>
<li>Drawing through Angular binding</li>
<li>Map events published as Angular events </li>
</ul>
<h3>
</h3>
<h3>
Tips</h3>
Here are some code snippets the highlights some of the lessons I have learned.<br />
<br />
First, make sure Google Maps library is loaded from here:
<br />
<pre> https://maps.googleapis.com/maps/api/js?key={YOUR_API_KEY}&libraries=visualization,place&callback=initMap
</pre>
Add this line in <a href="https://github.com/huguogang/ng2tsdemo/blob/master/typings.json">typings.ts</a>, so that we can have type definitions for Google Maps JavaScript API
<br />
<pre> "googlemaps": "github:DefinitelyTyped/DefinitelyTyped/googlemaps/google.maps.d.ts"
</pre>
Event handlers turns out to be tricky. My naive first implementation was something like this
<br />
<pre class="js" name="code">this.map.addListener('click', function(e: google.maps.MouseEvent) {
this.mapClick.emit(e.latLng));
);
</pre>
Turns out there are two big problems in this implementation:<br />
<ol>
<li><code>this</code> inside the event handler does not have member <code>mapClick</code>. Because it is no longer the component class </li>
<li>Once scope of <code>this</code> is fixed, I found data changes in the event handler does not trigger Angular change detection</li>
</ol>
Solutions for those problems? See the comments in my final implementation:<br />
<br />
<script src="https://gist.github.com/huguogang/d2805cc19f463ba8c7545cc206c18fed.js"></script>
On the CSS side, it is very important to set height of Google Map component. If not done, it is automatically collapsed to nothing, and you won't see a map.<br />
<h3>
Demo </h3>
Finally, a functional demo is here: <a href="https://github.com/huguogang/ng2tsdemo/blob/master/google_map.html">google_map.html</a>. Below is screenshot of the demo in action:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAGuPjEhz89qKqTZEaFOI86_AzsZUG1cpBu8XlVoqX7EK-qheA0ZAinAB3-lmo89G6u5xYGQALRgBRvHcxBLfb1LUFgF-p8zxbTeE-fwYJvmIOjhyT4zfypZdeA_mYNFX4Zd5xFQ/s1600/Screen+Shot+2016-05-17+at+11.40.03+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAGuPjEhz89qKqTZEaFOI86_AzsZUG1cpBu8XlVoqX7EK-qheA0ZAinAB3-lmo89G6u5xYGQALRgBRvHcxBLfb1LUFgF-p8zxbTeE-fwYJvmIOjhyT4zfypZdeA_mYNFX4Zd5xFQ/s320/Screen+Shot+2016-05-17+at+11.40.03+PM.png" width="320" /></a></div>
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-26040091899508452812016-05-02T23:25:00.002-07:002016-05-22T22:39:07.520-07:00Angular 2: Injecting Parent and Child Component<a href="https://developertips.firebaseapp.com/view_child.html" target="_blank">Live Demo</a><br />
<a href="https://github.com/huguogang/ng2tsdemo" target="_blank">Github Repo</a><br />
<br />
To inject children component into a parent component, use <code><a href="https://angular.io/docs/js/latest/api/core/index/ViewChildren-var.html">ViewChildren</a></code> (notice there is also <code><a href="https://angular.io/docs/js/latest/api/core/index/ContentChildren-var.html">ConentChildren</a></code> which will inject children from <a href="http://developertips.blogspot.com/2016/05/angular-2-content-content-projection.html">content projection</a>).
<br />
<br />
To inject a parent into child component, you simply need to inject parent in the <code>constructor</code> of child component. However, there is a bit of problem due to circular reference. The parent component has to reference child component as directive. If the child also depends on parent, we will get an error like this: <code>EXCEPTION; Cannot resolve all parameters for '[ParentComponent]'...</code>. So, the following slightly twisted injection is needed:
<br />
<pre> contructor(<b>@Inject(forwardRef(() => ParentComponent))</b> private _parent: ParentComponent)
</pre>
<br />
A small working example showing both child and parent component injection can be downloaded here: <a href="https://github.com/huguogang/ng2tsdemo/blob/master/view_child.html">https://github.com/huguogang/ng2tsdemo/blob/master/view_child.html</a>.Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-84185843282035459592016-05-02T20:51:00.002-07:002016-05-22T22:39:52.867-07:00Angular 2 Content, Content Projection, Transclusion<a href="https://developertips.firebaseapp.com/content.html" target="_blank">Live Demo</a><br />
<a href="https://github.com/huguogang/ng2tsdemo" target="_blank">Github Repo</a><br />
<br />
I guess under all these fancy words (especially <a href="https://docs.angularjs.org/api/ng/directive/ngTransclude">Transclusion</a>), there is a simple concept. And it seems to me, it is way easier to learn it by starting with looking at a working sample, make some changes and observe the changes.<br />
<br />
I have created a bare minimum working example here: <a href="https://github.com/huguogang/ng2tsdemo/blob/master/content.html">https://github.com/huguogang/ng2tsdemo/blob/master/content.html</a><br />
<br />
Here are the key code fragments. Related elements are color coded.<br />
Template for the directive:
<br />
<pre><div>
<h1><ng-content select="<span style="background-color: yellow;">my-title</span>"></ng-content></h1>
<div>
<ng-content select="<span style="background-color: cyan;">content</span>"></ng-content>
</div>
<br/>
<em style="font-size:smaller"><ng-content select="<span style="background-color: lime;">footer</span>"></ng-content></em>
</div>
</pre>
Markup in the client component:<br />
<pre><multi-slot-content>
<<span style="background-color: yellow;">my-title</span>>Angular 2 Content Demo</<span style="background-color: yellow;">my-title</span>>
<<span style="background-color: cyan;">content</span>>The selectors defined in MultiSlotContent directive will find
the content element in this template, insert it into it's own template
section.</<span style="background-color: cyan;">content</span>>
<<span style="background-color: lime;">footer</span>>Footer: this feature was called transclusion in Angular 1.</<span style="background-color: lime;">footer</span>>
</multi-slot-content>
</pre>
Resulting HTML Markup:<br />
<pre><multi-slot-content>
<div>
<h1><<span style="background-color: yellow;">my-title</span>>Angular 2 Content Demo</<span style="background-color: yellow;">my-title</span>></h1>
<div>
<<span style="background-color: cyan;">content</span>>The selectors defined in MultiSlotContent directive will find
the content element in this template, insert it into it's own template
section.</<span style="background-color: cyan;">content</span>>
</div>
<br>
<em style="font-size:smaller"><<span style="background-color: lime;">footer</span>>Footer: this feature was called transclusion in Angular 1.</<span style="background-color: lime;">footer</span>></em>
</div>
</multi-slot-content>
</pre>
Notice the key is to define proper Angular 2 selectors in the directive. Then in the client component, it just need to fill the content in the right selector target. The end result is the directive's <code>ng-content</code> elements got replaced by the fragments from client.Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-7596654447973823072016-05-01T23:26:00.001-07:002016-05-22T22:40:38.460-07:00Angular 2 HTTP JSON Service<a href="https://developertips.firebaseapp.com/json_service.html" target="_blank">Live Demo</a><br />
<a href="https://github.com/huguogang/ng2tsdemo" target="_blank">Github Repo</a><br />
<br />
Here is a bare minimum demo of how to use Angular 2 HTTP JSON Service:<a href="https://github.com/huguogang/ng2tsdemo/blob/master/json_service.html">https://github.com/huguogang/ng2tsdemo/blob/master/json_service.html</a><br />
<br />
The demo uses observable instead of promise. A few potential catches:<br />
<ul>
<li>Import Rx.js in html file: <pre><script src="node_modules/rxjs/bundles/Rx.js"></script>
</pre>
</li>
<li> Import rxjs/Rx in service: <pre>import 'rxjs/Rx'</pre>
</li>
<li> Register <code>HTTP_PROVIDERS</code>
</li>
</ul>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-51460181794703869252016-05-01T19:26:00.001-07:002016-05-22T22:42:11.427-07:00Angular 2 Renderer<a href="https://developertips.firebaseapp.com/renderer.html" target="_blank">Live Demo</a><br />
<a href="https://github.com/huguogang/ng2tsdemo" target="_blank">Github Repo</a><br />
<br />
Renderer in Angular 2 is a fascinating topic. It does not have an official documentation yet. As of this writing 5/1/2016, there is only a list of public method signatures here: <a href="https://angular.io/docs/ts/latest/api/core/Renderer-class.html">https://angular.io/docs/ts/latest/api/core/Renderer-class.html</a>.<br />
<br />
It turns out it is very easy to get a hold of the renderer in your components. All it takes is to declare a Renderer in contructor, Angular 2 will inject it for you.<br />
<br />
Code sample to inject renderer:<br />
<pre>constructor(private _renderer: <b>Renderer</b>) { }</pre>
<br />
A working demo on github:<a href="https://github.com/huguogang/ng2tsdemo/blob/master/renderer.html"> https://github.com/huguogang/ng2tsdemo/blob/master/renderer.html</a>Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-47384426800394620632016-04-01T00:16:00.000-07:002016-04-01T00:16:13.873-07:00Angular 2 Resources<h3>
Official web site</h3>
<a href="https://angular.io/">https://angular.io</a> <br />
<br />
<h3>
Official Github Repo </h3>
<a href="https://github.com/angular/angular">https://github.com/angular/angular</a><br />
A few notable sub-directories:<br />
<ul>
<li>Source Code: <a href="https://github.com/angular/angular/tree/master/modules/angular2/src">https://github.com/angular/angular/tree/master/modules/angular2/src</a></li>
<li>Release Progress: <a href="https://github.com/angular/angular/milestones">https://github.com/angular/angular/milestones</a></li>
</ul>
<h3>
Angular CLI </h3>
<a href="https://github.com/angular/angular-cli">https://github.com/angular/angular-cli</a><br />
Command line interface. It helps to build skeleton code for a new project that follows best practice. Not officially released yet. But very helpful. It generates project with proper folder structure, unit testing and end2end tests are also included.<br />
<br />
<h3>
npm packages</h3>
<ul>
<li>angular2: <a href="https://www.npmjs.com/package/angular2">https://www.npmjs.com/package/angular2</a><br />
angular-cli: <a href="https://www.npmjs.com/package/angular-cli">https://www.npmjs.com/package/angular-cli</a> </li>
</ul>
<br />
<h3>
Blog about Angular 2 (and other Software topics) by Victor Savkin</h3>
<a href="http://victorsavkin.com/">http://victorsavkin.com</a><br />
There are not many tutorials here, but those few entries will give us a deep dive into Angular 2 design philosophy.<br />
<br />
<h3>
egghead.io</h3>
<a href="https://egghead.io/technologies/angular2">https://egghead.io/technologies/angular2</a><br />
A series of short video tutorials about angular 2.<br />
<br />
<h3>
Stackoverflow tagged Angular 2</h3>
<a href="http://stackoverflow.com/questions/tagged/angular2">http://stackoverflow.com/questions/tagged/angular2</a> <br />
<br />
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-63428288223727143892015-07-31T23:56:00.000-07:002015-07-31T23:57:24.681-07:00ExtJS 6.0.0 GPL is outGo here: <a href="https://www.sencha.com/legal/gpl/">https://www.sencha.com/legal/gpl/</a>, select "<b>Sencha Ext JS</b>" and give your email address.<br />
<br />
This version has quite a few feature and performance improvements. <a href="https://docs.sencha.com/extjs/6.0/whats_new/6.0.0/whats_new.html">https://docs.sencha.com/extjs/6.0/whats_new/6.0.0/whats_new.html</a>Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-66149479553573886052015-07-06T22:45:00.002-07:002015-07-06T22:50:08.641-07:00JPA Join FetchA couple of key points to have a successful join fetch in JPA (backed by Hibernate):<br />
<ul>
<li>Why do we want join fetch? JPA default fetch strategy is "<span style="font-family: "Courier New",Courier,monospace;">Lazy</span>", which has better performance under most circumstances. But, sometimes we do want to retrieve all children (and sometimes children's children). In that case, join fetch allows us to get everything in one Database round-trip instead of N (or N*N round-tips). This change can easily speed up those queries for 100 times (in my case it went from 20 seconds to 0.2 seconds).</li>
<li>Make sure in your Entity classes, the child collections are "<span style="font-family: "Courier New",Courier,monospace;">Set<childentity></childentity></span>" not "<span style="font-family: "Courier New",Courier,monospace;">List<childentity></childentity></span>". If you get the error message: "<span style="font-family: "Courier New",Courier,monospace;">Hibernate cannot simultaneously fetch multiple bags</span>". This is the root cause.</li>
<li>How to join multiple levels: </li>
</ul>
<pre class="Java" name="code"> root
.fetch([childAttributeName], JoinType.LEFT)
.fetch([grandChildAttributeName], JoinType.LEFT);</pre>
<ul>
<li>Fetch join will return multiple duplicated rows for the parent entity. This is usually undesirable, wrap the return set in a <span style="font-family: "Courier New",Courier,monospace;">LinkedHashSet</span> will get the unique parent entities in the original select order. (See this <a href="http://stackoverflow.com/questions/18753245/one-to-many-relationship-gets-duplicate-objects-whithout-using-distinct-why">Stack Overflow post</a>)</li>
</ul>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-80413582696742104772015-03-16T11:00:00.001-07:002015-07-06T22:50:56.127-07:00Troubleshoot Networking Problems in Google Chrome Browser* Developer Tools > Network<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7a_gqMCID2QN1v-0bVX_LtodI8YUqGgK4xNhiIo_nDXxN-W5zXz-GwIh2vkztMTG04p7o6mcTWz4RO33jNjz5tOELZslR_3u5a7bmRtUmYat45UwHHUV542ujOLrbt4Dfv-6N4g/s1600/ss1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7a_gqMCID2QN1v-0bVX_LtodI8YUqGgK4xNhiIo_nDXxN-W5zXz-GwIh2vkztMTG04p7o6mcTWz4RO33jNjz5tOELZslR_3u5a7bmRtUmYat45UwHHUV542ujOLrbt4Dfv-6N4g/s1600/ss1.png" height="97" width="320" /></a></div>
<br />
* chrome://net-internals/<br />
Screenshot for the socket view: chrome://net-internals/#sockets<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkekwBntva3qq6hmt9JggJ_DKJb67uP6DENP39h5HkivF4iArErF12llBM3afNRtwAr_J8h2JU9kh-7TKxkX_9Jz8ZYS78SezMPyL-Pl7OfyVAoH8h6RQhCXgp9WK5GOr_z3KwUw/s1600/ss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkekwBntva3qq6hmt9JggJ_DKJb67uP6DENP39h5HkivF4iArErF12llBM3afNRtwAr_J8h2JU9kh-7TKxkX_9Jz8ZYS78SezMPyL-Pl7OfyVAoH8h6RQhCXgp9WK5GOr_z3KwUw/s1600/ss.png" height="230" width="320" /></a></div>
* wireshark (hopefully, do not need to go that far)<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://upload.wikimedia.org/wikipedia/commons/0/03/Wireshark_screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://upload.wikimedia.org/wikipedia/commons/0/03/Wireshark_screenshot.png" height="180" width="320" /></a></div>
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-57954492810335061502015-02-25T09:19:00.003-08:002015-02-25T10:12:12.736-08:00Coldfusion 10 Solr Indexing Zip File that Contains PDF filesSeems like I should be surprised, if I don't find some surprises in Coldfusion every week. :) Here is another one that took me a few hours to find a solution. And hopefully will save a few hours for someone else.<br />
<br />
<b>Environment</b><br />
Coldfusion 10 Update 15<br />
Windows Server 2012<br />
<b><br /></b>
<b>Symptom</b><br />
When indexing a bunch of files, Coldfusion stopped indexing without any exception or getting into any error state. It just stopped in the middle of indexing. If I was not looking at it closely, I would not have noticed that it has failed.<br />
<br />
Again, Coldfusion stopped the execution without throwing a fuss is a big surprise for me. If I run it in Brower, there is no usual 500 server error. Everything is just hunky-dory as far as Coldfusion is concerned!?<br />
<br />
<b>Cause</b><br />
After some digging, I found out the following<br />
<ul>
<li>It stopped on a zip file</li>
<li>The zip file has some PDF files in it</li>
<li><span style="font-family: Courier New, Courier, monospace;">Coldfusion-error.log</span> has the following message</li>
</ul>
<pre>Feb 25, 2015 8:30:28 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [CfmServlet] in context with path [/] threw exception [ROOT CAUSE:
<b>java.lang.NoClassDefFoundError: org/apache/pdfbox/pdmodel/PDDocument</b>
at org.apache.tika.parser.pdf.PDFParser.parse(PDFParser.java:53)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:120)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:101)
at org.apache.tika.parser.DelegatingParser.parse(DelegatingParser.java:52)
at org.apache.tika.parser.pkg.PackageParser.parseArchive(PackageParser.java:78)
at org.apache.tika.parser.pkg.ZipParser.parse(ZipParser.java:49)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:120)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:101)
at coldfusion.tagext.search.SolrUtils.getMetadata(SolrUtils.java:599)
at coldfusion.tagext.search.SolrUtils.getSolrDocument(SolrUtils.java:753)
at coldfusion.tagext.search.SolrUtils.addDocument(SolrUtils.java:1339)
at coldfusion.tagext.search.IndexTag.doUpdate(IndexTag.java:651)
at coldfusion.tagext.search.IndexTag.doStartTag(IndexTag.java:340)
</pre>
<br />
So, obviously, our Coldfusion distribution is missing some libraries.<br />
<br />
<b>Solution</b><br />
<b>Short answer</b>: find jar file for PDFBox, throw them under Coldfusion lib folder and restart Coldfusion. And I got the jar file from here: <a href="http://mirrors.ibiblio.org/maven2/org/apache/pdfbox/pdfbox/0.8.0-incubating/pdfbox-0.8.0-incubating.jar">pdfbox-0.8.0-incubating.jar</a><br />
<br />
<b>Long Answer: </b>However, as with all Open Source projects, there is not much consideration of backward compatibility or official supported bundled distribution. I tried to download latest version of PDFBox, and it just does not work. So, I will need to find the original bundled version, and here is the journey (without detours I took :( ) to the right jar file<br />
<br />
<ul>
<li>Search CF10 folder for tika jar file, found tika-parsers-0.6.jar</li>
<li>Google Tika source, found it SVN root</li>
<li>Find maven POM file under 0.6 tag: <a href="http://svn.apache.org/repos/asf/tika/tags/0.6/tika-parsers/pom.xml">http://svn.apache.org/repos/asf/tika/tags/0.6/tika-parsers/pom.xml</a></li>
<li>Located reference of PDFBox</li>
</ul>
<div>
<pre><dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version><b>0.8.0-incubating</b></version>
</dependency>
</pre>
</div>
<br />
<ul>
<li>Google "pdfbox 0.8.0 incubating"</li>
<li>voila</li>
</ul>
<br />
<br />
<b>Another Challenge (unsolved)</b><br />
There is still some unsolved challenge for Solr. For example, Verity can index our PDF files correctly, but Solr's PDF reader seem to be sub-par. It only got some fragmented text from our PDF file, and it's missing a lot of keywords in our PDF files.Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-59276007850057181362015-02-23T12:39:00.001-08:002015-07-06T22:50:33.655-07:00CFScript bug?An extra semicolon at the end of "if" block is causing a lot of head scratching for me recently. Please see the code snippet below.
<script src="https://gist.github.com/huguogang/653cd68ea489a6e515ea.js"></script>
Expected output should be:
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheb-VcqJLev3b8_nLtgrr95sxOyCO0HaGhgkpjcOOFCcSJQCjyaujhH5agBa6syWhZ_JSTCAPllb7mQQi9Zz2tu4n5UdRyassySGJIj5NoekiJ8p0gF8zQYrgZ5SIXlMwi5DA9jg/s1600/expected.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheb-VcqJLev3b8_nLtgrr95sxOyCO0HaGhgkpjcOOFCcSJQCjyaujhH5agBa6syWhZ_JSTCAPllb7mQQi9Zz2tu4n5UdRyassySGJIj5NoekiJ8p0gF8zQYrgZ5SIXlMwi5DA9jg/s320/expected.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Expected Output</td></tr>
</tbody></table>
However, below is the actual output:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB-0R8Td9UAnV82OYYa5wDuKwKzPDs4TpllWWD8lCRVDoRysb79uAzxUhXjl0kfQcdz5K_drI4MCma7kCGt6M8r765Y5rnPj0rWFRdXJIyTQTmNvydSDSzsQS4nluqK_SGisLqtw/s1600/actual.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB-0R8Td9UAnV82OYYa5wDuKwKzPDs4TpllWWD8lCRVDoRysb79uAzxUhXjl0kfQcdz5K_drI4MCma7kCGt6M8r765Y5rnPj0rWFRdXJIyTQTmNvydSDSzsQS4nluqK_SGisLqtw/s320/actual.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Actual Output</td></tr>
</tbody></table>
Now, please notice this extra ";" at the end of line 6. If I remove it, everything will just work as expected.
<br />
<pre><cfscript>
private struct function test() {
if(1 == 1) {
if(1 == 0) {
writeOutput("1==0");
}<span style="background-color: #ffffa5; font-weight: bold;">; //<- look at here</span>
writeOutput("true");
return {data = 1};
}
writeOutput("false");
return {data = 2};
}
writeDump(test());
</cfscript>
</pre>
Due to the lack of specifications for CFScript language, I cannot tell if this grammar is even allowed. But I can tell you this: the journey of discovering and finding the root cause of this problem is not fun at all!<br />
<h3>
Symptom</h3>
CFScript fall through the "if-else" statement, and did not return to caller from the expected branch.<br />
<h3>
Cause</h3>
An extra semicolon at the end of a block is the root cause.
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-88993815672421930582014-12-19T22:54:00.002-08:002014-12-20T12:19:14.077-08:00Node.JS Error "Cannot find module '...'"Setting up NodeJS is generally a smooth process. There is one thing need to be taken care of manually: set up environment variable <span style="font-family: Courier New, Courier, monospace;">NODE_PATH</span>. This variable must point to the npm global installation location, otherwise you NodeJS application may have problem starting with error message like this:<br />
<div>
<blockquote class="tr_bq">
Error: Cannot find module 'XXX'</blockquote>
</div>
<div>
<br /></div>
<div>
In Windows, the easiest way is to go Computer > Properties > Advanced System Settings > Environment Variables > User Variables > New<br />
<div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2gBxxKx2qOO2ZvS7KwO1ghVvIe_0joBH5TWOsC7o3oVNeChCUwxGI9izxHBtbcudnq8cUCZk5JooZU8AQP6vxb5BN858VqBXbIDHDFYb2QZQc_aI62Go4CIt3EIGzZ_WS_9pJWA/s1600/screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2gBxxKx2qOO2ZvS7KwO1ghVvIe_0joBH5TWOsC7o3oVNeChCUwxGI9izxHBtbcudnq8cUCZk5JooZU8AQP6vxb5BN858VqBXbIDHDFYb2QZQc_aI62Go4CIt3EIGzZ_WS_9pJWA/s1600/screenshot.png" height="144" width="320" /></a></div>
<br /></div>
</div>
</div>
</div>
<div>
After the configuration, need to exit the current command line and start a new one in order to see the environment variable in effect.</div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-42415249158209611202014-11-19T11:51:00.001-08:002014-11-19T11:51:43.974-08:00IIS Error: Cannot write configuration file<h3 style="clear: both; text-align: left;">
Symptom</h3>
<div class="separator" style="clear: both; text-align: left;">
When trying to change IIS configuration, got this error message:</div>
<blockquote class="tr_bq" style="clear: both;">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Filename:<br /> \\?\C:\Windows\System32\inetsrv\config\applicationHost.config<br /> Error: Cannot write configuration file</span></blockquote>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4bV9tlv0T9G1ZxEt6P0u0MIvUBbzjRgAlHPa6kwgikx5SIPgEPAzk2q0ZmQDU7hJqKVIh4CH6420OF2nDqhhhAuLxGYGRLxS8zY3SnSLvhlsTvH2NpqUroA5x05hOX4V6KjZ8Fg/s1600/1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4bV9tlv0T9G1ZxEt6P0u0MIvUBbzjRgAlHPa6kwgikx5SIPgEPAzk2q0ZmQDU7hJqKVIh4CH6420OF2nDqhhhAuLxGYGRLxS8zY3SnSLvhlsTvH2NpqUroA5x05hOX4V6KjZ8Fg/s1600/1.png" height="171" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Error Message</td></tr>
</tbody></table>
<h3>
Diagnosis</h3>
<div>
Turns out root cause of the problem is a full C: drive.</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1aOY5QI1uHPqepj8qpTv_35UpFWpaSxVzlDUN7oxi7vQh1iBDPO4-JhwyjwZShfiog6gZWPx3gtJzUimDXj4DyADn0mRbU2007XHe8__W87y6GnGdABGU8Xic3RzDUfEorYVUAw/s1600/2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1aOY5QI1uHPqepj8qpTv_35UpFWpaSxVzlDUN7oxi7vQh1iBDPO4-JhwyjwZShfiog6gZWPx3gtJzUimDXj4DyADn0mRbU2007XHe8__W87y6GnGdABGU8Xic3RzDUfEorYVUAw/s1600/2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Windows Explorer</td></tr>
</tbody></table>
<h3>
Solution</h3>
<div>
Luckily, this is a virtual machine with some spare disk capacity. So it's just a matter of allocating more resource, then extend C: drive.<br /><br />
<div>
<br /></div>
</div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-29237295436315017802014-11-05T15:00:00.000-08:002014-11-05T15:00:17.165-08:00Flex TextArea problem in DataGrid<h3>
Problem</h3>
Flex 4 <span style="font-family: Courier New, Courier, monospace;">TextArea </span>does not take multi-line entry when used as editor in <span style="font-family: Courier New, Courier, monospace;">DataGrid</span>.<br />
<br />
<h3>
Solution</h3>
Add <span style="font-family: Courier New, Courier, monospace;">editorUsesEnterKey="true" </span>attribute to the column with <span style="font-family: Courier New, Courier, monospace;">TextArea </span>editor.<br />
<br />
<br />
<h3>
P.S.</h3>
The solution is straightforward. But the route to finding this solution kind of proves open source or at least show your customer the source code is very important.<br />
<br />
I first suspect the <span style="font-family: Courier New, Courier, monospace;">enter </span>key is intercepted by <span style="font-family: Courier New, Courier, monospace;">DataGrid</span>, but it appears that <span style="font-family: Courier New, Courier, monospace;">keydown </span>event is intercepted by <span style="font-family: Courier New, Courier, monospace;">DataGrid </span>before the <span style="font-family: Courier New, Courier, monospace;">TextArea</span>. Some Googling with various keyword combination did not turn up anything interesting.<br />
<br />
Not sure where to start, I added a <span style="font-family: Courier New, Courier, monospace;">itemEditEnd</span> event handler to the <span style="font-family: Courier New, Courier, monospace;">DataGrid</span>, and set a breakpoint there. After walking through the stack, I saw the following code segment, and thus the solution above pops out. Now I can simply go to documentation of <span style="font-family: Courier New, Courier, monospace;">editorUsedEnterKey </span>and make sure this is what I want.<br />
<br />
(Code of interest from DataGrid.as)<br />
<span style="font-family: Courier New, Courier, monospace;"> /**</span><br />
<span style="font-family: Courier New, Courier, monospace;"> * @private</span><br />
<span style="font-family: Courier New, Courier, monospace;"> */</span><br />
<span style="font-family: Courier New, Courier, monospace;"> private function editorKeyDownHandler(event:KeyboardEvent):void</span><br />
<span style="font-family: Courier New, Courier, monospace;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // ESC just kills the editor, no new data</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (event.keyCode == Keyboard.ESCAPE)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> endEdit(DataGridEventReason.CANCELLED);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else if (event.ctrlKey && event.charCode == 46)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> { // Check for Ctrl-.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> endEdit(DataGridEventReason.CANCELLED);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else if (event.charCode == Keyboard.ENTER && event.keyCode != 229)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // multiline editors can take the enter key.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (!_editedItemPosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if (columns[_editedItemPosition.columnIndex].<span style="background-color: yellow;">editorUsesEnterKey</span>)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> // Enter edits the item, moves down a row</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // The 229 keyCode is for IME compatability. When entering an IME expression,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // the enter key is down, but the keyCode is 229 instead of the enter key code.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // Thanks to Yukari for this little trick...</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (endEdit(DataGridEventReason.NEW_ROW) && !dontEdit)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> findNextEnterItemRenderer(event);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (focusManager)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> focusManager.defaultButtonEnabled = false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span>Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-34501299728410756292014-08-21T12:59:00.000-07:002014-08-21T13:00:50.111-07:00Ubuntu LTS 12 on VMWare Player Showing Multiple Columns of Identical Screens<h3>
Symptoms</h3>
<div>
After updating to Kernel 3.2.0.67 and reboot, my screen is showing three columns of duplicated desktop. </div>
<h3>
Environment: </h3>
<ul>
<li>VMWare Player 6.0.3</li>
<li>Ubuntu: 12.04 LTS, Kernel 3.2.0.67 (post upgrade version, I'm not sure what was the version before my upgrade)</li>
<li>The VM image was created way back in a very old VMWare Player, started from Ubuntu 10. It has been kept up-to-date by applying Ubuntu patches and eventually to 12.04 LTS. Turn out this probably was the root cause of all the troubles</li>
</ul>
<h3>
Solution</h3>
<div>
After some Google search and reading up on posts, I was eventually lead to the following thread:</div>
<blockquote class="tr_bq">
<b><a href="https://communities.vmware.com/thread/481038?start=0&tstart=0" target="_blank">Guest display split into identical panes</a></b></blockquote>
Flip to page 2, on <a href="https://communities.vmware.com/thread/481038?start=17&tstart=0" target="_blank">post 17</a> from thellstrom, there is the solution that worked for me. I used solution 1b mentioned in the post, and after reboot, everything is back to normal.<br />
<h3>
Cause</h3>
<div>
So, based on the article, root cause of the problem is due to VM created on old version of player with virtualHW version 7. I updated the config file from version 7 to 9, and everything appears to be working now.</div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-17410425760004801662014-08-14T13:47:00.000-07:002014-08-14T13:47:01.128-07:00Just Because You Can Does Not Mean You Should<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdyy7DW_-kXXr_hyNNz6np4xJG6NyrOWX37jDfJPdUJJFC9UVYeNTOD7CP1jC0zLlTcOuYm-Ph9fUueQJrAAa76sKVCZr2_B4FBtfwLnXlAGONfts5Uz_mw5N1EVIYrLl3lj1qcA/s1600/UI2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdyy7DW_-kXXr_hyNNz6np4xJG6NyrOWX37jDfJPdUJJFC9UVYeNTOD7CP1jC0zLlTcOuYm-Ph9fUueQJrAAa76sKVCZr2_B4FBtfwLnXlAGONfts5Uz_mw5N1EVIYrLl3lj1qcA/s1600/UI2.png" height="199" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtvKdiaHsv3CbaZRyvNDNYwdZBKMufJwsV2_-dr9VGxKWkbnUOFzNnbszDC-qO42MRyaA5DMVo-N2FwGINu54TauyKpmPQomDBEYhyojNezYKZolXrKiJHJ481C9MYJC2Mrw5Zmw/s1600/UI1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtvKdiaHsv3CbaZRyvNDNYwdZBKMufJwsV2_-dr9VGxKWkbnUOFzNnbszDC-qO42MRyaA5DMVo-N2FwGINu54TauyKpmPQomDBEYhyojNezYKZolXrKiJHJ481C9MYJC2Mrw5Zmw/s1600/UI1.png" height="250" width="320" /></a></div>
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-77048474006444533942014-08-14T13:37:00.002-07:002014-08-14T13:37:49.953-07:00SQL Injection Attack - Law Enforcement be AwareMust see, "High Tech" attack of law enforcement IT network. It may crash license plate readers, red light cameras, ...<br />
<br />
No seriously, it might work.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigVQRa7sm1ZUfDyLZIk0xSbYfgzsFiNO5UWGBuq7UZhuES_yxnqC_HiOU3peoO4K9VWNCDq6NOKihYInnmxjxT01GTUozKWttZftGl_vm6xWjQodVo3sdehK3NwdDadrPfYg0lJQ/s1600/SQL+Injection.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigVQRa7sm1ZUfDyLZIk0xSbYfgzsFiNO5UWGBuq7UZhuES_yxnqC_HiOU3peoO4K9VWNCDq6NOKihYInnmxjxT01GTUozKWttZftGl_vm6xWjQodVo3sdehK3NwdDadrPfYg0lJQ/s1600/SQL+Injection.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">SQL Injection Attack</td></tr>
</tbody></table>
<br />
Source: <a href="http://coolshell.cn/">http://coolshell.cn/</a>Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-38736588776219325712014-08-13T18:40:00.001-07:002014-08-13T18:40:14.011-07:00Lua in Visual Studio 2013<br />
<div>
Build Lua for Windows using Visual Studio 2013 is a very straightforward task.</div>
<div>
<br /></div>
<div>
Project to build lua.exe:</div>
<ol>
<li>Create Project > Visual C++ > Empty Project</li>
<li>Add Existing Item ...</li>
<ul>
<li>Select all files under src except luac.c</li>
</ul>
<li>Project Property > All Configurations > Configuration Properties > C/C++ > Preprocessor > Preprocess Definitions, add: _CRT_SECURE_NO_WARNINGS</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX67lZIHUeDHUAryFTudmmxZhqJNJyC3cr51NPMnfGB37oOGDki7Pn1oYwQPwcuTEfbF4UcKAzxbPvxVzidOIlBD4MSNjkVh0JSzJ17z6nIUm5Pd8YfVclW1aoiv7pQCDNoyLrXQ/s1600/property.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX67lZIHUeDHUAryFTudmmxZhqJNJyC3cr51NPMnfGB37oOGDki7Pn1oYwQPwcuTEfbF4UcKAzxbPvxVzidOIlBD4MSNjkVh0JSzJ17z6nIUm5Pd8YfVclW1aoiv7pQCDNoyLrXQ/s1600/property.png" height="380" width="640" /></a></div>
<div>
<br /></div>
<div>
That is it.</div>
<div>
<br /></div>
<div>
To build luac.exe, simply repeat above steps. When selecting files, select all files, except lua.c.</div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-58701805073694826942014-08-10T23:17:00.003-07:002014-08-10T23:18:09.945-07:00Puzzles for Programmers<a href="http://fun.coolshell.cn/" target="_blank">http://fun.coolshell.cn/ </a><br />
<br />
What is the output of the code below?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrSJ_yyHlCw_jluIeqnc-aTwCTNiw_UW5q1oCguVRbc3ui9BqQcccQMTZe__lrGhgcLpo3Czb72GZ6TkAPuxNQdVrTb-Q02UjoQnWTiGvXy9Ox2gyEYFi6iXEz5cfw5ecmrxbE8A/s1600/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrSJ_yyHlCw_jluIeqnc-aTwCTNiw_UW5q1oCguVRbc3ui9BqQcccQMTZe__lrGhgcLpo3Czb72GZ6TkAPuxNQdVrTb-Q02UjoQnWTiGvXy9Ox2gyEYFi6iXEz5cfw5ecmrxbE8A/s1600/1.jpg" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRhyphenhyphen757umRonlINyQVDFQogrgBadChnlwptzkaV_e-W3M81jmQe99msmWsnSQwcYt0D7hODTQQ9VMnilDxHp7NqjrcWaQ_ZFmxjIRcY9xNQSRLoyEkj-2sdhoDBCFP8JRfTVBTsw/s1600/2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRhyphenhyphen757umRonlINyQVDFQogrgBadChnlwptzkaV_e-W3M81jmQe99msmWsnSQwcYt0D7hODTQQ9VMnilDxHp7NqjrcWaQ_ZFmxjIRcY9xNQSRLoyEkj-2sdhoDBCFP8JRfTVBTsw/s1600/2.jpg" /></a></div>
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-37892448008957835912014-08-08T21:31:00.001-07:002014-08-08T21:56:31.797-07:00JSmol Widget for ExtJS 5<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="http://huguogang.github.io/Web/JSmolExt_demo.htm" target="_blank"><img alt="Live Demo of JSmol Widget for ExtJS 5" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFL3Yn8BNFwtGxrqKjjE59tejRD6KNvxfAsY2NYy2bhCdL7NJnQmm-FRzoGIgN6FtkeCk77HAqmGgbsaRl3qrr01gaPhaDMFXWWHO-zBCzsFj1wc0GbQC7V-w_0khbqyvUTEtkVw/s1600/live+demo.jpg" height="272" title="" width="320" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="http://huguogang.github.io/Web/JSmolExt_demo.htm" target="_blank">Screenshot of the Demo Page Running in Google Chrome</a></td></tr>
</tbody></table>
<h4>
Background</h4>
<h4>
<a href="http://jmol.sourceforge.net/" target="_blank">Jmol</a></h4>
<blockquote class="tr_bq">
<b style="background-color: white; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px;">Jmol</b><span style="background-color: white; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px;"> is an open-source viewer for three-dimensional chemical structures, with features for chemicals, crystals, materials and biomolecules. Features include reading a variety of file types and output from quantum chemistry programs, and animation of multi-frame files and computed normal modes from quantum programs.</span></blockquote>
<h4>
<span style="background-color: white; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px;"><a href="http://wiki.jmol.org/index.php/JSmol" target="_blank">JSmol</a></span></h4>
<blockquote class="tr_bq">
<span style="background-color: white; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px;">JSmol is a JavaScript framework that allows web developers to create pages that utilize either Java or HTML5 (no Java), at will. This enables Jmol to display interactive 3D molecular structures on devices that do not have Java installed, or for which Java is not available (such as smart phones and some tablet computers, e.g. iPad) or has not been installed because of concerns for Java being a </span><a class="external text" href="http://proteopedia.org/w/Java#Java_is_a_security_threat" rel="nofollow" style="background: url(http://wiki.jmol.org/skins/monobook/external.png) 100% 50% no-repeat rgb(255, 255, 255); color: #3366bb; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px; padding: 0px 13px 0px 0px; text-decoration: none;" target="_blank">security threat</a><span style="background-color: white; font-family: sans-serif; font-size: 12.5px; line-height: 19.049999237060547px;">.</span></blockquote>
<br />
I have used Jmol for a few years now. But, over the past few years, due to concerns of security threat? Running Java applet in a browse is getting harder and harder. Shelling out money to buy certificate for open source software is, well, at most a hard sell.<br />
<br />
So, JSmol to the rescue, pure JavaScript HTML5 application, works on IE, Firefox, Chrome, and even iPad. What is the catch? At least it does not live well with ExtJS on the same web page. You will get weired error messages like '<span style="font-family: Courier New, Courier, monospace;">Uncaught TypeError: Cannot read property '***' of null</span>'. My guess is JSmol has changed prototype of some basic types.<br />
<h4>
Problem</h4>
<div>
<ul>
<li>Jmol: can no longer be used in any major browser without compiling with a trusted certificate</li>
<li>JSmol: not compatible with ExtJS, and I suspect may have problem with a lot of other libraries as well</li>
</ul>
</div>
<h4>
Solution</h4>
<div>
iframe! It gives the web page the needed firewall between ExtJS page and JSmol page.<br />
<br /></div>
<div>
I have implemented a basic ExtJS 5 Widget that will inject an iframe, then inject JSmol code to render molecule models.</div>
<div>
<br />
Live demo: <a href="http://huguogang.github.io/Web/JSmolExt_demo.htm" target="_blank">Example - JSmol Widget for ExtJS 5</a></div>
<div>
Demo page source code:</div>
<div>
<ul>
<li><a href="https://github.com/huguogang/Web/blob/master/JSmolExt_demo.htm" target="_blank">JSmolExt_demo.htm</a></li>
<li><a href="https://github.com/huguogang/Web/blob/master/JSmolExt_demo.js" target="_blank">JSmolExt_demo.js</a></li>
</ul>
</div>
<div>
Widget Source Code:</div>
<div>
<ul>
<li><a href="https://github.com/huguogang/Web/blob/master/JSmolExt/JSmolExt.js" target="_blank">JSmolExt.js</a></li>
</ul>
</div>
<div>
<br />
This widget takes <span style="font-family: Courier New, Courier, monospace;">JmolConfig</span> object, and will pass it along to the JSmol app in the iframe. For details of the parameters, please refer to: <a href="http://wiki.jmol.org/index.php/Jmol_JavaScript_Object/Info" target="_blank">Jmol JavaScript Object/Info</a>.<br />
<br /></div>
<div>
One more thing, the component has a "safe" option. Because the code to inject JSmol to iframe does not work in Firefox and IE 9. If "safe" is true, it will simply set iframe src to a pre-existing page that host JSmol library. I used this page: <a href="http://huguogang.github.io/Web/JSmolDemo.htm" target="_blank">A bare bone JSmol Demo Page</a>. Problem with my page is that it is static and does not honor the JSmolConfig passed to the widget. Now it is up to you to pass along the JSmolConfig to a dynamic page.<br />
<br />
Just for fun, below is a screenshot of <a href="http://jmol.sourceforge.net/demo/animation/" target="_blank">Jmol's official demo</a> from one of my computers.</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzs3UZQOcI58-5eXVIDlejGLa3IUMswblBB1o46uF4BOzPhCW8M5pS90RQdBNcvWSsTgolAGeREztZk-ay0oxWpuWmqsYq88iQGchCxJ7lmrE0X-GbSx9ltp_2_f6obtbHyQsUiA/s1600/update+java.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzs3UZQOcI58-5eXVIDlejGLa3IUMswblBB1o46uF4BOzPhCW8M5pS90RQdBNcvWSsTgolAGeREztZk-ay0oxWpuWmqsYq88iQGchCxJ7lmrE0X-GbSx9ltp_2_f6obtbHyQsUiA/s1600/update+java.jpg" height="161" width="320" /></a></div>
<br /></div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-74413293835007015312014-08-08T01:34:00.003-07:002014-08-08T01:34:36.138-07:00Github: mirror master -> gh-pages<br />
<ol>
<li>Navigate to the project page</li>
<li>To the left of branch dropdown, click "Compare, review, create a pull request";</li>
<li>Select: Base: gh-pages, Compare: master</li>
<li>Create pull request</li>
<li>Merge pull request</li>
<li>Confirm merge</li>
</ol>
<div>
Done!</div>
Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0tag:blogger.com,1999:blog-13937734.post-16082052917228150702014-08-05T10:43:00.001-07:002014-08-05T10:43:20.493-07:00Windows 3 NostalgiaMust see for Windows 3 nostalgia. :) <a href="http://www.michaelv.org/">http://www.michaelv.org/</a>, everything done using HTML, and actually works.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihAlApZjy0eIhxc51sOVdQijgxzuDOSoQX0qgT7SFwFB9Q1SpyKH8a-ENDKcs9KkaJrgyXR5K61OVsUnf4fJsrCbvSDszn7wFbkrUMbN1JB8WUm5OIbNYutyCU0Akbl66n35fuvA/s1600/Calculator.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihAlApZjy0eIhxc51sOVdQijgxzuDOSoQX0qgT7SFwFB9Q1SpyKH8a-ENDKcs9KkaJrgyXR5K61OVsUnf4fJsrCbvSDszn7wFbkrUMbN1JB8WUm5OIbNYutyCU0Akbl66n35fuvA/s1600/Calculator.PNG" height="316" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Calculator</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho86imhvYb_mSrtGjGyxz98eN1fSLbPlqkCSpm0emvikphbH7pfN9Xfn_d0rgliUROoCz29I71yDlDGOfNOizNnw1ISZvOO49Q8c8nAqaxGFuvBqM9l-Jq4_Z97VMMOxJoDPeA8Q/s1600/DosCommand.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho86imhvYb_mSrtGjGyxz98eN1fSLbPlqkCSpm0emvikphbH7pfN9Xfn_d0rgliUROoCz29I71yDlDGOfNOizNnw1ISZvOO49Q8c8nAqaxGFuvBqM9l-Jq4_Z97VMMOxJoDPeA8Q/s1600/DosCommand.PNG" height="181" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Dos Prompt, try DIR</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDnebXsOBRd1ixiXjM8nBz4mh2GcfVeefPubcWzirGoMj8sSNCrkrBTBLj8wvscwxRC1_IMn63k7Bm_6hA2i1YohnLlfBAHvMNWxvnuft4v1ON2fiSUTxx4lT8LgxNGStWrJq2jw/s1600/MediaPlayer.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDnebXsOBRd1ixiXjM8nBz4mh2GcfVeefPubcWzirGoMj8sSNCrkrBTBLj8wvscwxRC1_IMn63k7Bm_6hA2i1YohnLlfBAHvMNWxvnuft4v1ON2fiSUTxx4lT8LgxNGStWrJq2jw/s1600/MediaPlayer.PNG" height="218" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Media Player</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIASnnLGal0f0gQoAGROBBhPRA6LMOc7ACBjg6Qs8Ivu7ADjcsocsYAFgmDSlYLvnEVLDTKx3PedxTXOw3Lhz5GHPKGfXwc97DRzfuTfYy6PAT5ya6_qpDr9dQQl_vkuiD4uRccg/s1600/MinSweeper.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIASnnLGal0f0gQoAGROBBhPRA6LMOc7ACBjg6Qs8Ivu7ADjcsocsYAFgmDSlYLvnEVLDTKx3PedxTXOw3Lhz5GHPKGfXwc97DRzfuTfYy6PAT5ya6_qpDr9dQQl_vkuiD4uRccg/s1600/MinSweeper.PNG" height="242" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Minesweeper, it works too!!</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhel-uO1R3wTPPBN8mtbAT0GB8SzABlL27UcLllC0yOieE9TvOp0Fa4Cccdi7F8oaXFYy2wqNNFH_PIdeTsR8Uo9nS7vHmcMs_N5Y3fVstSzsUy45onRgu5u9jTgxUrLfaJJrmIrg/s1600/Notepad.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhel-uO1R3wTPPBN8mtbAT0GB8SzABlL27UcLllC0yOieE9TvOp0Fa4Cccdi7F8oaXFYy2wqNNFH_PIdeTsR8Uo9nS7vHmcMs_N5Y3fVstSzsUy45onRgu5u9jTgxUrLfaJJrmIrg/s1600/Notepad.PNG" height="238" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Notepad, you can even save the text file</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4nHqhwzrnUUv_OJ03iTzjJlDCXPAgV1JHknDA0OJ3movz1Rly4TIcwoGogH9BzvPaQ4izAiWwZaxZBjzXZUgk_o2e5tA5ppFuSupx_xLVuQ2myAUmaDjkUv4sulNl2AOw3cTl0Q/s1600/ProgramManager.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4nHqhwzrnUUv_OJ03iTzjJlDCXPAgV1JHknDA0OJ3movz1Rly4TIcwoGogH9BzvPaQ4izAiWwZaxZBjzXZUgk_o2e5tA5ppFuSupx_xLVuQ2myAUmaDjkUv4sulNl2AOw3cTl0Q/s1600/ProgramManager.PNG" height="212" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
Finally, where it all begins, Program Manager</div>
<br />Guogang Huhttp://www.blogger.com/profile/00815620106700755743noreply@blogger.com0