tag:blogger.com,1999:blog-250405342023-07-04T13:19:10.625+03:00dmitrygusev onlineJust a blog for my researchesAnonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.comBlogger74125tag:blogger.com,1999:blog-25040534.post-47009718486670658372013-06-04T18:35:00.002+04:002013-06-04T18:35:57.981+04:00Deploy Application Binaries (*.war) to OpenShift<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://openshift.redhat.com/">RedHat OpenShift</a> is a PaaS that provides a cloud hosting for your applications.<br />
<br />
I'd like to share a practice that I use to deploy my Java application to OpenShift.<br />
<br />
I only have experience with Tomcat 7 (JBoss EWS 2.0) cartridge and non-scalable applications, so I will talk about them. However this may be applied to other environments.<br />
<br />
I use GitHub to store my application codebase, and I also use Gradle as a build tool.<br />
<br />
If you use Maven for your builds and you have all your dependencies in public Maven repositories or these repositories that are accessible from OpenShift, then this blog post is likely not for you.<br />
<br />
As of today OpenShift does not support Gradle as a build tool, and I have some of my dependencies in my private/local repositories that are not available from OpenShift, this is why I build my application locally and only deploy binaries to OpenShift.<br />
<br />
When you create OpenShift application there is a Git repository that you may use to deploy your code. You can also use this Git as your primary source storage (or you can synchronize with your GitHub repo), but I don't do this.<br />
<br />
This Git repo has specific directory structure and OpenShift auto-deployment rely on this structure, this is one of the reasons I don't use this Git repo as my primary code base -- I use multiple deployment targets for my project and OpenShift is only one of them.<br />
<br />
The directory structure contains <span style="font-family: Courier New, Courier, monospace;">/webapps</span> folder where you can put your <span style="font-family: Courier New, Courier, monospace;">*.war</span> file and OpenShift will deploy it when you Git push.<br />
<br />
If you do this, however, you will find soon that your Git repository will eat all your server-side disk quota (which is only 1GB for free). This is because remote Git repository will hold all revisions of your binaries. My <span style="font-family: Courier New, Courier, monospace;">*.war</span> file size is near 50MB -- this is typical for most small-to-medium Java applications. So after you do 20 deployments -- you will be out of free space.<br />
<br />
Usually you don't need all these revisions of your binaries, so to fix this situation you first should delete your remote Git history and adopt some other practice for deployments.<br />
<br />
Here is how I do this.<br />
<br />
<h3 style="text-align: left;">
Delete old revisions of your binaries from your remote OpenShift Git repo</h3>
<div>
<ol style="text-align: left;">
<li>First you need to do a <span style="font-family: Courier New, Courier, monospace;">git clone</span> or a <span style="font-family: Courier New, Courier, monospace;">git pull</span> to fetch recent version of your remote repo. Lets name the folder you've cloned to as OLD_REPO. You will need this to restore your git hooks that are in the <span style="font-family: Courier New, Courier, monospace;">.openshift</span> subfolder, and maybe some other configs except your binaries (see step 8 below). </li>
<li>SSH connect to your OpenShift instance.</li>
<li>cd ~/git/<app-name>.git/objects</app-name></li>
<li>rm -rf *</li>
<li>cd ..</li>
<li>rm refs/heads/master</li>
<li>Do a fresh <span style="font-family: Courier New, Courier, monospace;">git clone</span> from remote OpenShift Git. It will tell you that you've cloned empty repository -- this is correct, your remote repository now clean. Lets name your new clone folder as NEW_REPO.</li>
<li>Copy contents of OLD_REPO to the NEW_REPO. You should copy all except <span style="font-family: Courier New, Courier, monospace;">.git</span> folder, because NEW_REPO will already contain itself <span style="font-family: Courier New, Courier, monospace;">.git</span> folder.</li>
<li>Delete NEW_REPO/webapps/*.war -- these are your previous binaries:<br /><span style="font-family: 'Courier New', Courier, monospace;">git rm webapps/*.war</span></li>
</ol>
<div>
At this stage you will have empty remote Git repository and local clone with latest revision of what you've had in remote before deleting it except your binaries.</div>
</div>
<div>
<br /></div>
<h3 style="text-align: left;">
Way to deploy new binaries</h3>
<div>
To deploy new binaries you have to copy them manually to OpenShift. I do this using SCP command.</div>
<div>
<br /></div>
<div>
I created a shell-script <span style="font-family: Courier New, Courier, monospace;">upload-war.sh</span> with the following content:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">scp $PROJECT_X_WORKSPACE_DIR/project-x/project-x-web/build/libs/*.war $PROJECT_X_OPENSHIFT_ADDRESS:~/app-root/data/webapps/ROOT.war</span></div>
<div>
<br /></div>
<div>
As you see I use environment variables to tell the script where my local binary is located and where should I place them in remote OpenShift. <span style="font-family: 'Courier New', Courier, monospace;">PROJECT_X_OPENSHIFT_ADDRESS</span> is the <span style="font-family: Courier New, Courier, monospace;">username@address</span> you use when connect to OpenShift by SSH.</div>
<div>
<br /></div>
<div>
My project has only one target <span style="font-family: Courier New, Courier, monospace;">*.war</span> artifact and I copy it to remote <span style="font-family: Courier New, Courier, monospace;">data</span> folder under the <span style="font-family: Courier New, Courier, monospace;">ROOT.war</span> name. In OpenShift the <span style="font-family: Courier New, Courier, monospace;">data</span> folder is the place where you store your custom files.</div>
<div>
<br /></div>
<div>
After I copied the file I have to tell OpenShift to deploy it.</div>
<div>
To do this I modify build action hook which is located here: <span style="font-family: Courier New, Courier, monospace;">NEW_REPO/.openshift/action_hooks/build</span> to make it look like this:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">#!/bin/bash</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"># This is a simple build script and will be executed on your CI system if</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"># available. Otherwise it will execute while your application is stopped</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"># before the deploy step. This script gets executed directly, so it</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"># could be python, php, ruby, etc.</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">cp $OPENSHIFT_DATA_DIR/webapps/* $OPENSHIFT_REPO_DIR/webapps/</span></div>
<div>
<br /></div>
<div>
Here <span style="font-family: 'Courier New', Courier, monospace;">$OPENSHIFT_DATA_DIR</span> and <span style="font-family: 'Courier New', Courier, monospace;">$OPENSHIFT_REPO_DIR</span> are OpenShift built-in environment variables.</div>
<div>
<br /></div>
<div>
Add this script to version control, commit and push to OpenShift remote.</div>
<div>
<br /></div>
<div>
When you commit this hook will copy the binary you copied earlier and deploy it. So next time when you will release new version, just run <span style="font-family: Courier New, Courier, monospace;">upload-war.sh</span> and do some dummy commit/push to the OpenShift remote and thats it.</div>
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-82103248825626764502013-04-07T22:29:00.002+04:002013-04-07T22:56:55.847+04:00Render Tapestry5 Block to a string from code<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
Recently I integrated Select2 component to my tapestry5 application.</div>
<div>
<br /></div>
<div>
Select2 can load data from server using ajax when user scrolls through drop down.</div>
<div>
<br /></div>
<div>
There could be any data formats in ajax response provided that developer implements javascript <code>results()</code> function that parses the response into the format expected by select2.</div>
<div>
<br /></div>
<div>
Select2 provides two more callback functions that developers usually implement to post-process returned data:</div>
<div>
<ul style="text-align: left;">
<li><code>id()</code> function that retrieves id from the choice object;</li>
<li><code>formatResult()</code> function that builds HTML markup which is used to display choice object in drop down.</li>
</ul>
<div>
<div>
I used Tynamo's tapestry-resteasy to build REST service that returns data to select2, and my REST service returned everything needed to implement <code>id()</code> and <code>formatResult()</code> functions.</div>
</div>
</div>
<div>
<br /></div>
<div>
I could just implement <code>formatResult()</code> to build HTML markup for select2, but I already had similar tapestry5 component that builds the same markup and I wanted to increase code reuse.<br />
<br />
To do that I built tapestry5 service that does just this – <code>EventResponseRenderer</code> (see code below).</div>
<div>
<br />
To use it:<br />
<ol style="text-align: left;">
<li>Declare a block you want to render, as you usually do. In my example I created separate page –<code>internal/CompanyBlocks.tml</code> – and there is my <code>addressBlock</code>;</li>
<li>Declare <a href="http://tapestry.apache.org/component-events.html#ComponentEvents-EventHandlerMethods">event handler method</a> that handles "Render" event and returns the block you want to render (note that you may also use tapestry5 <code>AjaxResponseRenderer.addRender()</code>);</li>
<ol>
<li>In my example this is:</li>
<ul>
<li><code>public Block onRenderFromCompanyAddress(Company company)</code></li>
</ul>
<li>Note that you must specify id of tapestry5 component in event handler method name. <i>This is the limitation of my EventResponseRenderer implementation and only required to conform tapestry5 API. This could be id of any component from the page;</i></li>
<li>You will probably want to declare some parameters that you will use to initialize page properties required for block renderer. You don't have to implement type coercers for them, because you will pass values for these parameters from code;</li>
</ol>
<li><code>@Inject</code> instance of <code>EventResponseRenderer</code> and call its <code>render()</code> method passing instance of <code>RenderEvent</code> to it. <code>RenderEvent</code> constructor accepts <code>pageName</code> where event handler method declared, <code>componentId</code> that was used in event handler method name (see previous step), and <code>eventArgs</code> – list of objects that will be passed as parameters to the event handler method. See method <code>CompanyResourceImpl.createMatch()</code></li>
<li>Thats it.</li>
</ol>
</div>
<h3>
Usage Example</h3>
<br />
<script src="https://gist.github.com/dmitrygusev/5331606.js"></script>
<br />
<h3>
EventResponseRenderer Implementation</h3>
<br />
<script src="https://gist.github.com/dmitrygusev/5331488.js"></script>
</div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-33540776378104279752012-03-11T16:55:00.004+04:002012-03-11T16:55:47.662+04:00Serving Tapestry5 Assets As Static Resources<div dir="ltr" style="text-align: left;" trbidi="on">
In Tapestry5 you use <a href="http://tapestry.apache.org/assets.html">assets</a> to reference <span style="font-family: 'Courier New', Courier, monospace;">*.js</span>, <span style="font-family: 'Courier New', Courier, monospace;">*.css</span> or image files from your templates/code. The reference may look like:<br />
<br />
<div style="color: #413af6; font-family: Monaco; font-size: 11px;">
<span style="color: black;"> </span><span style="color: #009192;"><</span><span style="color: #489191;">link</span><span style="color: black;"> </span><span style="color: #98228d;">rel</span><span style="color: black;">=</span>"stylesheet"<span style="color: black;"> </span><span style="color: #98228d;">type</span><span style="color: black;">=</span>"text/css"<span style="color: black;"> </span><span style="color: #98228d;">href</span><span style="color: black;">=</span>"${context:/css/all.css}"<span style="color: black;"> </span><span style="color: #009192;">/></span></div>
<div>
<br />
During the render phase Tapestry5 converts the <span style="font-family: 'Courier New', Courier, monospace;">${context:/css/all.css}</span> part to asset URL, which may look like the following (see Asset URLs section <a href="http://tapestry.apache.org/assets.html#FootnoteMarker2">here</a>):<br />
<br />
<div style="color: #413af6; font-family: Monaco; font-size: 11px;">
<span style="color: black;"> </span><span style="color: #009192;"><</span><span style="color: #489191;">link</span><span style="color: black;"> </span><span style="color: #98228d;">rel</span><span style="color: black;">=</span>"stylesheet"<span style="color: black;"> </span><span style="color: #98228d;">type</span><span style="color: black;">=</span>"text/css"<span style="color: black;"> </span><span style="color: #98228d;">href</span><span style="color: black;">=</span>"/assets/stage-20120310/ctx/css/all.css"<span style="color: black;"> </span><span style="color: #009192;">/></span></div>
<br />
Here "<span style="font-family: 'Courier New', Courier, monospace;">stage-20120310</span>" -- is an application version string, which Tapestry5 adds to asset URLs to manage assets versioning. When running in production Tapestry5 adds a far future expires header for the asset, which will encourage the client browser to cache it.<br />
<br />
When you change one of your assets you have to change application version number in your <span style="font-family: 'Courier New', Courier, monospace;">AppModule.java</span>, so that Tapestry5 generate new asset URLs and browser fetched new assets instead of using the ones from cache.<br />
<br />
One disadvantage of such approach is that client browser will have to get <i>all</i> the assets once again, not just the one that was changed.<br />
<br />
For the majority of assets the asset URL is generated by Tapestry5. Exceptions are assets, that are referenced from <span style="font-family: 'Courier New', Courier, monospace;">*.css</span> files by the relative URL, like this (file <span style="font-family: 'Courier New', Courier, monospace;">all.css</span>):<br />
<br />
<div style="color: #489191; font-family: Monaco; font-size: 11px;">
a.external<span style="color: black;"> {</span></div>
<div style="color: #4033de; font-family: Monaco; font-size: 11px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #98228d;">background</span><span style="color: black;">: </span>transparent<span style="color: black;"> </span>url(../images/external.png)<span style="color: black;"> </span>no-repeat<span style="color: black;"> </span>scroll<span style="color: black;"> </span>right<span style="color: black;"> </span>center<span style="color: black;">;</span></div>
<div style="color: #4033de; font-family: Monaco; font-size: 11px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #98228d;">display</span><span style="color: black;">: </span>inline-block<span style="color: black;">;</span></div>
<div style="color: #98228d; font-family: Monaco; font-size: 11px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span>margin-left<span style="color: black;">: </span><span style="color: #4033de;">2px</span><span style="color: black;">;</span></div>
<div style="color: #98228d; font-family: Monaco; font-size: 11px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span>height<span style="color: black;">: </span><span style="color: #4033de;">11px</span><span style="color: black;">;</span></div>
<div style="color: #98228d; font-family: Monaco; font-size: 11px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span>width<span style="color: black;">: </span><span style="color: #4033de;">11px</span><span style="color: black;">;</span></div>
<div style="font-family: Monaco; font-size: 11px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #98228d;">zoom</span>: <span style="color: #4033de;">1</span>;</div>
<div style="font-family: Monaco; font-size: 11px;">
}</div>
<br />
In this case browser will form the URL itself relatively to <span style="color: #413af6; font-family: Monaco; font-size: 11px;">"/assets/stage-20120310/ctx/css/all.css"</span>, and the resulting URL will be <span style="color: #413af6; font-family: Monaco; font-size: 11px;">"/assets/stage-20120310/ctx/images/external.png"</span>.<br />
<br />
So you <i>have to</i> change application version in <span style="font-family: 'Courier New', Courier, monospace;">AppModule.java</span> if you provide new version of "<span style="font-family: 'Courier New', Courier, monospace;">external.png</span>".<br />
<br />
But, for the majority of assets it would be enough to append MD5/SHA1/... checksum as a GET-parameter to asset URL and make them look like:<br />
<br />
<div style="font-family: Monaco; font-size: 11px;">
<div style="color: #413af6;">
<span style="color: black;"> </span><span style="color: #009192;"><</span><span style="color: #489191;">link</span><span style="color: black;"> </span><span style="color: #98228d;">rel</span><span style="color: black;">=</span>"stylesheet"<span style="color: black;"> </span><span style="color: #98228d;">type</span><span style="color: black;">=</span>"text/css"<span style="color: black;"> </span><span style="color: #98228d;">href</span><span style="color: black;">=</span>"/assets/stage-20120310/ctx/css/all.css?5ef25ac1ec38f119e283f338e6c120a4e53127b1"<span style="color: black;"> </span><span style="color: #009192;">/></span></div>
<div>
<span style="color: #009192;"><br /></span></div>
</div>
In Tapestry5 you have the ability to provide your own implementation of <span style="font-family: 'Courier New', Courier, monospace;"><a href="http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/services/AssetPathConverter.html">AssetPathConverter</a></span> service and append this checksum manually. But, in this interface you only have original asset URL, and don't have the resource itself to calculate the checksum.<br />
<br />
There are several ways this may be implemented. Ideally, I'd like this to be implemented in Tapestry5 core.<br />
<br />
There's one thing I don't like about Tapestry5 assets handling, though, even if the above solution will be implemented -- is that assets are not static.<br />
<br />
This means every asset URL is handled by the Java code, and in most cases assets handling is just streaming of existing files from filesystem to browser (with optional <a href="http://tapestry.apache.org/assets.html#Assets-HowcanweminimizeanAsset%3F">minimization</a> and gzip-compression).<br />
<br />
Once the asset was handled, Tapestry5 caches the response and uses it in further responses, but still this is all done in Java.<br />
<br />
In Ping Service we've implemented "assets precompilation", and placed all the rendered assets as static files in the web app root folder.<br />
<br />
This is done using <a href="https://github.com/anjlab/ping-service/blob/3bf35d4e8b925009f1432e2148d67c588e2ce802/src/com/anjlab/tapestry5/StaticAssetResourceStreamer.java">custom implementation</a> of <span style="font-family: 'Courier New', Courier, monospace;">org.apache.tapestry5.internal.services.ResourceStreamer</span>, which is responsible for streaming every asset to client. During resource streaming we calculate asset checksum and store in a <span style="font-family: 'Courier New', Courier, monospace;">static.properties</span> file, where we put asset URL as a key, and checksum as a value:<br />
<br />
<div style="color: #479075; font-family: Monaco; font-size: 11px;">
#Static Assets For Tapestry5 Application</div>
<div style="color: #479075; font-family: Monaco; font-size: 11px;">
#Sat Mar 10 19:42:38 UTC 2012</div>
<div style="color: #413af6; font-family: Monaco; font-size: 11px;">
<span style="color: black;">/assets/stage-20120310/ctx/css/all.css=</span>5ef25ac1ec38f119e283f338e6c120a4e53127b1</div>
<div style="font-family: Monaco; font-size: 11px;">
/assets/stage-20120310/ctx/css/analytics.css=<span style="color: #413af6;">ee470432c344820e43995fb4632ab4bee3b92e38</span></div>
<div style="font-family: Monaco; font-size: 11px;">
/assets/stage-20120310/tapestry/t5-prototype.js=<span style="color: #413af6;">95e30b840a5654b82e6a0334a14a2766c57c4d99</span></div>
<div>
<span style="color: #413af6;">...</span></div>
<br />
<a href="https://github.com/anjlab/ping-service/blob/3bf35d4e8b925009f1432e2148d67c588e2ce802/src/com/anjlab/tapestry5/StaticAssetPathConverter.java">Our implementation</a> of <span style="font-family: 'Courier New', Courier, monospace;">AssetPathConverter</span> uses this property file to modify asset URLs.<br />
<div>
<br /></div>
We run our implementation of <span style="font-family: 'Courier New', Courier, monospace;">ResourceStreamer</span> only in production mode, since Google App Engine doesn't allow writing to the filesystem.<br />
<br />
Also we've implemented it to work only if special HTTP-header passed with the request. To pass this header and to trigger every asset we have in our application, we use <a href="https://github.com/anjlab/ping-service/blob/3bf35d4e8b925009f1432e2148d67c588e2ce802/test/com/anjlab/ping/integration/CreateStaticAssets.java">Selenium-powered integration test</a> that queries every single page. We run this test before deploying new version to production.<br />
<br />
Now Tapestry5 asset URLs and URLs of static files are the same in our application. So Google App Engine runtime won't even pass the request to Java. Also it uses <a href="http://code.google.com/intl/en/appengine/docs/java/runtime.html#Responses">its own facilities</a> to serve <a href="http://code.google.com/intl/en/appengine/docs/java/gettingstarted/staticfiles.html">static files</a>, i.e. gzip-compression, etc.</div>
</div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-31254469092282141262012-01-14T14:16:00.000+04:002012-01-14T14:16:54.930+04:00Simple Sorting Facade for Java (SSF4J)<div dir="ltr" style="text-align: left;" trbidi="on">
In Java to sort two or more lists together you have to write a custom solution.<br />
<br />
Say, you have list of names and corresponding list of weights. There is no API that allows you to sort names by weights (at least not that I know). However this is very common use case, especially when you analyzing data in your programs.<br />
<br />
To achieve this, you, most likely, implement one of the sorting algorithms with a custom swap-logic.<br />
<br />
Simple sorting facade is a pattern that already contains implementation of sorting algorithm(s) and only requires developers to specify source list, its bounds, and compare- and the swap-logic.<br />
<br />
You can explore <a href="https://github.com/anjlab/ssf4j">SSF4J on GitHub</a> and contribute your implementations of sorting algorithms.<br />
<br />
Here's an example of using SSF4J:<br />
<br />
<br />
<script src="https://gist.github.com/1610889.js?file=gistfile1.java">
</script>
</div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com3tag:blogger.com,1999:blog-25040534.post-19442077234910458262011-09-19T20:41:00.001+04:002011-09-19T20:41:57.166+04:00Mac OS X Lion HTTP Sniffer<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Simple command-line sniffer:</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo tcpdump -s 0 -A -i en1 port 80</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Use <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ifconfig</span> to lookup interface name (i.e. <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">en1</span>).</div>
</div>
Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-64187561558521627382011-09-05T05:08:00.000+04:002011-09-07T12:49:14.914+04:00Running BIRT Reports in Tomcat<div dir="ltr" style="text-align: left;" trbidi="on">
Context: You have database and you need to do data analysis: draw charts, build some tables, calculate totals, etc. You want it all to be available over the web and secured with a password.<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Your database is any JDBC-supported database (I use MySQL 5.1.49).</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Your server is running any OS where Java can run (I use Ubuntu Linux 10.10 available through SSH).</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
I will show how to implement this using Eclipse BIRT 3.7.</div>
<br />
<span class="Apple-style-span" style="font-size: 19px; font-weight: bold;">Developer Environment</span><br />
<ol style="text-align: left;">
<li>Download "Eclipse IDE for Java and Report Developers" package <a href="http://www.eclipse.org/downloads/">here</a>.<br />Unzip to install.</li>
<li>Design new report (I created <tt>sales.rptdesign</tt>). This is really straightforward.</li>
</ol>
<div>
<b>JDBC Driver.</b> You will need MySQL JDBC driver to create Data Source for report. I got <tt>mysql-connector-java-5.1.17-bin.jar</tt> <a href="http://www.mysql.com/downloads/connector/j/">here</a>.</div>
<div>
Installing the driver in BIRT designer is easy using "Manage drivers..." dialog. But you will probably have problems deploying it to the runtime.</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span"><b>Fonts.</b> You probably won't have any problems with fonts in BIRT designer. And again you will likely have problems with fonts in runtime</span><span class="Apple-style-span">.</span><br />
<br />
<b>Connection Profile Store.</b> With BIRT 3.7 you can use Connection Profiles to hold database connections. After you've finished designing and testing your report, double click report Data Source to bring properties dialog and create new connection profile store in there. Save it to some file (I saved to <tt>planet33_v2.xml</tt>).<br />
Here's what I have in there:<br />
<pre style="background: #ffffff; color: black;"><span style="color: #7f0055;"><?</span><span style="color: #7f0055;">xml</span> <span style="color: #7f0055;">version</span>="1.0" <span style="color: #7f0055;">encoding</span>=<span style="color: #2a00ff;">"UTF-8"</span> <span style="color: #7f0055;">standalone</span>=<span style="color: #2a00ff;">"no"</span><span style="color: #7f0055;">?></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">DataTools.ServerProfiles</span> version=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">1.0</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">profile</span> autoconnect=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">No</span><span style="color: #2a00ff;">"</span> desc=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">"</span>
id=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">ecc3bc60-d4fd-11e0-957a-e0e31b9a34ee</span><span style="color: #2a00ff;">"</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">planet33_v2</span><span style="color: #2a00ff;">"</span>
providerID=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.enablement.mysql.connectionProfile</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">baseproperties</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span>
name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.connectionProperties</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.savePWD</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">true</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.drivers.defnType</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.enablement.mysql.5_1.driverTemplate</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">jarList</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">/usr/local/share/mysql-connector-java-5.1.17-bin.jar</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.username</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">your_username</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.driverClass</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">com.mysql.jdbc.Driver</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.databaseName</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">planet33_v2</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.password</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">your_password</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.version</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">5.1</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.URL</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">jdbc:mysql://127.0.0.1:3306/planet33_v2</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.connectivity.db.vendor</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">MySql</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">baseproperties</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">org.eclipse.datatools.connectivity.versionInfo</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">server.version</span><span style="color: #2a00ff;">"</span> value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">5.1.49</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">technology.name.jdbc</span><span style="color: #2a00ff;">"</span> value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">JDBC</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">server.name</span><span style="color: #2a00ff;">"</span> value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">MySQL</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">technology.version.jdbc</span><span style="color: #2a00ff;">"</span> value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">4.0.0</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">org.eclipse.datatools.connectivity.versionInfo</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">driverreference</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">driverName</span><span style="color: #2a00ff;">"</span> value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">MySQL JDBC Driver</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">driverTypeID</span><span style="color: #2a00ff;">"</span>
value=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.datatools.enablement.mysql.5_1.driverTemplate</span><span style="color: #2a00ff;">"</span> <span style="color: #7f0055;">/></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">driverreference</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">profile</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">DataTools.ServerProfiles</span><span style="color: #7f0055;">></span>
</pre>
<br />
Note: I bet you can use JDNI data sources here (and I suppose this is even preferable because of connection pooling, etc.). Please, drop a few lines in comments below with instructions how you do this.<br />
<br />
You can now edit XML source of you report and replace <tt>/report/data-sources</tt> with something like this:<br />
<br />
<pre style="background: #ffffff; color: black;"><span style="color: #7f0055;"><</span><span style="color: #7f0055;">data-sources</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">oda-data-source</span> extensionID=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">org.eclipse.birt.report.data.oda.jdbc.dbprofile</span><span style="color: #2a00ff;">"</span>
name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">Planet33 V2 Data Source</span><span style="color: #2a00ff;">"</span> id=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">359</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">OdaConnProfileName</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>planet33_v2<span style="color: #7f0055;"></</span><span style="color: #7f0055;">property</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">OdaConnProfileStorePath</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>../conf/planet33_v2.xml<span style="color: #7f0055;"></</span><span style="color: #7f0055;">property</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">oda-data-source</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">data-sources</span><span style="color: #7f0055;">></span>
</pre>
<br />
Several things to mention here:<br />
<ul style="text-align: left;">
<li><tt>planet33_v2.xml</tt> (Connection Profile Store)</li>
<ul>
<li>Check all properties and change them according to your connection.</li>
<li>Note the <tt>jarList</tt> property, there you should specify path(s) to where your JDBC drivers located (I copied driver that I've downloaded to <tt>/usr/local/share/mysql-connector-java-5.1.17-bin.jar</tt>).</li>
<li>When you create connection profile store file from designer it places property with <tt>name="org.eclipse.datatools.connectivity.driverDefinitionID"</tt>. You should remove this property because of <a href="http://www.eclipse.org/forums/index.php/mv/msg/170815/547384/#msg_547384">this issue</a>.</li>
</ul>
<li><tt>sales.rptdesign</tt> (The Report)</li>
<ul>
<li>You should keep value of <tt>ida-data-source@id</tt> attribute the same that was in your design.</li>
<li>Value of <tt>OdaConnProfileName</tt> should match value of <tt>DataTools.ServerProfiles/profile@name</tt> attribute from <tt>planet33_v2.xml</tt>.</li>
<li>Note that <tt>OdaConnProfileStorePath</tt> is relative path (see below). But you can keep it absolute if you want. </li>
</ul>
</ul>
</div>
<h3>
Server Environment</h3>
<div>
(Note: I recommend to configure Tomcat instance on your developer machine first to make it easier to verify report settings, and then transfer the entire <tt>$CATALINA_HOME</tt> to production server. Of course, you can do all these steps on production server directly.)</div>
<ol style="text-align: left;">
<li>Download Apache Tomcat (any Java application server should be fine).<br />Unzip to some folder (I used <tt>/usr/local/share/apache-tomcat-5.5.33/</tt>) -- this will be <tt>$CATALINA_HOME</tt>.</li>
<li>Download BIRT "Runtime" package <a href="http://download.eclipse.org/birt/downloads/">here</a>.<br />Copy <tt>birt.war</tt> (BIRT Web Viewer application) to <tt>$CATALINA_HOME/webapps</tt>.</li>
<li>Edit <tt>$CATALINA_HOME/catalina.sh</tt> and paste these lines somewhere after <tt>JAVA_OPTS</tt> variable initialized (this prepares <a href="http://wiki.eclipse.org/DTP_1.9_M7_New_and_Noteworthy">workspace for DTP plugin</a>):<br />
<pre style="background: #ffffff; color: black;"></pre>
<pre style="background: #ffffff; color: black;">java_io_tmpdir=$CATALINA_HOME<span style="color: #3f3fbf;">/temp</span>
org_eclipse_datatools_workspacepath=$java_io_tmpdir<span style="color: #3f3fbf;">/workspace_dtp</span>
mkdir -p $org_eclipse_datatools_workspacepath
JAVA_OPTS=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">$JAVA_OPTS</span><span style="color: #2a00ff;"> -Dorg.eclipse.</span><span style="color: #2a00ff;">datatools_workspacepath</span><span style="color: #2a00ff;">=</span><span style="color: #2a00ff;">$org_eclipse_datatools_workspacepath</span><span style="color: #2a00ff;">"</span>
</pre>
</li>
<li>Start Tomcat by running <tt>$CATALINA_HOME/startup.sh</tt>. After this BIRT Report Viewer application should be available by <tt>http://localhost:8080/birt</tt>. Also <tt>birt.war</tt> should be now extracted to <tt>$CATALINA_HOME/webapps/birt</tt> -- this will be <tt>$BIRT_HOME</tt>. You can now delete <tt>$CATALINA_HOME/webapps/birt.war</tt>.</li>
<li>Copy <tt>planet33_v2.xml</tt> to <tt>$CATALINA_HOME/conf</tt> as (remember <tt>OdaConnProfileStorePath</tt> property in <tt>sales.rptdesign</tt> file?).</li>
<li>Copy your <tt>sales.rtpdesign</tt> file to <tt>$BIRT_HOME</tt>.</li>
</ol>
<div>
At this point you should be able to execute the report by simply following the address <tt>http://localhost:8080/birt/frameset?__report=sales.rptdesign&__dpi=600</tt>.</div>
<div>
<br /></div>
<div>
Note the <a href="http://www.eclipse.org/forums/index.php/mv/msg/118630/360957/#msg_360957"><tt>__dpi</tt> URL parameter</a> -- it controls DPI of chart images rendered in HTML/PDF. You will probably want to modify like this it to increase image quality. Also note that if you set chart output format to SVG you will get vector graphics quality in PDF output.</div>
<h4>
Security</h4>
<div>
There are obvious reasons why you may want to keep your reports secure.</div>
<div>
<br /></div>
<div>
Besides that keep in mind that in BIRT Web Viewer application all reports sources (*.rptdesign files) available to user by request. Try navigating to <span class="Apple-style-span" style="font-family: monospace;">http://localhost:8080/birt/sales.rptdesign</span> and you'll see what I mean. I think this is a good reason, why you should use connection profile store (or at least JNDI data sources), because that files not available through HTTP.</div>
<div>
<br /></div>
<div>
Implementing simple (<a href="http://www.cafesoft.com/products/cams/tomcat-security.html">HTTP BASIC AUTH</a>) security with Tomcat is pretty simple.</div>
<div>
<br /></div>
<div>
First, modify <tt>$BIRT_HOME/WEB-INF/web.xml</tt>, by adding this (you can change role names as you want):<br />
<pre style="background: #ffffff; color: black;"><span style="color: #3f7f59;"><!--</span><span style="color: #3f7f59;"> Define a security constraint on this application </span><span style="color: #3f7f59;">--></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">security-constraint</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">web-resource-collection</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">web-resource-name</span><span style="color: #7f0055;">></span>Entire Application<span style="color: #7f0055;"></</span><span style="color: #7f0055;">web-resource-name</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">url-pattern</span><span style="color: #7f0055;">></span>/*<span style="color: #7f0055;"></</span><span style="color: #7f0055;">url-pattern</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">web-resource-collection</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">auth-constraint</span><span style="color: #7f0055;">></span>
<span style="color: #3f7f59;"><!--</span><span style="color: #3f7f59;"> This role is not in the default user directory </span><span style="color: #3f7f59;">--></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">role-name</span><span style="color: #7f0055;">></span>manager<span style="color: #7f0055;"></</span><span style="color: #7f0055;">role-name</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">auth-constraint</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">security-constraint</span><span style="color: #7f0055;">></span>
<span style="color: #3f7f59;"><!--</span><span style="color: #3f7f59;"> Define the login configuration for this application </span><span style="color: #3f7f59;">--></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">login-config</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">auth-method</span><span style="color: #7f0055;">></span>BASIC<span style="color: #7f0055;"></</span><span style="color: #7f0055;">auth-method</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">realm-name</span><span style="color: #7f0055;">></span>BIRT Report Viewer<span style="color: #7f0055;"></</span><span style="color: #7f0055;">realm-name</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">login-config</span><span style="color: #7f0055;">></span>
<span style="color: #3f7f59;"><!--</span><span style="color: #3f7f59;"> Security roles referenced by this web application </span><span style="color: #3f7f59;">--></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">security-role</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">description</span><span style="color: #7f0055;">></span>
The role that is required to log in to the BIRT Report Viewer
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">description</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">role-name</span><span style="color: #7f0055;">></span>manager<span style="color: #7f0055;"></</span><span style="color: #7f0055;">role-name</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">security-role</span><span style="color: #7f0055;">></span>
</pre>
<br />
You may also do the same for <tt>$CATALINA_HOME/conf/web.xml</tt> to secure all applications in this Tomcat instance.<br />
Second, you should edit <tt>$CATALINA_HOME/conf/tomcat-users.xml</tt> to define user login and password.</div>
<div>
<br />
Thats all, you're secured :) This is should be fine for most cases, but I would recommend you to read about <a href="http://tomcat.apache.org/tomcat-5.5-doc/ssl-howto.html">HTTPS</a> if your data is extremely secure.</div>
<h4>
Deploy to server</h4>
<div>
<ol style="text-align: left;">
<li>Copy Tomcat to the server:<br />Tip: Use <tt>scp</tt> command in terminal to transfer files from your machine to the server over SSH:<br /><tt>scp /usr/local/share/apache-tomcat-5.5.33 dmitrygusev@planet33.ru:/usr/local/share/</tt></li>
<li>Copy JDBC Driver to the server:</li>
<ul>
<li>Copy this driver to the same path as specified in the <tt>jarList</tt> property from <tt>planet33_v2.xml</tt> file.</li>
<li>DO NOT COPY this driver to <tt>$BIRT_HOME/WEB-INF/lib</tt>, because it may lead to <tt>ClassNotFoundException</tt>.</li>
</ul>
<ol>
</ol>
</ol>
<div>
<b>Fix file permissions.</b> When you copy files over scp you may need to chmod them to grant read/execute access. This should fix it:<br />
<br /></div>
<pre>chmod a+r /usr/local/share/mysql-connector-java-5.1.17-bin.jar
chmod -R a+r /usr/local/share/apache-tomcat-5.5.33/
chmod a+x /usr/local/share/apache-tomcat-5.5.33/bin/*.sh
</pre>
<div>
<br />
Now you should be able to start tomcat and run reports on the server.<br />
<br /></div>
<div>
</div>
<div>
<b>Fonts.</b> BIRT PDF output doesn't work good for Russian fonts out-of-the-box, because of licensing issues with fonts. One simple solution to fix this is:</div>
<div>
<ol style="text-align: left;">
<li>Get the <tt>*.ttf</tt> font files you need (you can copy them from any Windows installation, look in <tt>c:\Windows\Fonts</tt>). These 8 files should be enough in most cases (these are "Arial" and "Times New Roman" fonts):<br /><br /><tt>arialbd.ttf arialbi.ttf ariali.ttf arial.ttf<br />timesbd.ttf timesbi.ttf timesi.ttf times.ttf</tt></li>
<li>Copy these files to <tt>/usr/share/fonts/truetype</tt> (or any other place that is referenced from <a href="http://dev.eclipse.org/viewcvs/viewvc.cgi/source/org.eclipse.birt.report.engine.fonts/fontsConfig.xml?view=markup&root=BIRT_Project"><tt>fontsConfig.xml</tt></a>).</li>
<li>Don't forget to fix file permissions:<br /><span class="Apple-style-span" style="font-family: monospace;">chmod a+r /usr/share/fonts/truetype/*.ttf</span></li>
<li>Reference the fonts from <tt>*.rptdesign</tt> (or configure <a href="http://dev.eclipse.org/viewcvs/viewvc.cgi/source/org.eclipse.birt.report.engine.fonts/fontsConfig.xml?view=markup&root=BIRT_Project"><tt>font-aliases</tt></a>):
<br /><tt>/report/styles</tt>
<pre style="background: #ffffff; color: black;"><span style="color: #7f0055;"><</span><span style="color: #7f0055;">style</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">report</span><span style="color: #2a00ff;">"</span> id=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">4</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">fontFamily</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>"Arial"<span style="color: #7f0055;"></</span><span style="color: #7f0055;">property</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"><</span><span style="color: #7f0055;">property</span> name=<span style="color: #2a00ff;">"</span><span style="color: #2a00ff;">fontSize</span><span style="color: #2a00ff;">"</span><span style="color: #7f0055;">></span>9pt<span style="color: #7f0055;"></</span><span style="color: #7f0055;">property</span><span style="color: #7f0055;">></span>
<span style="color: #7f0055;"></</span><span style="color: #7f0055;">style</span><span style="color: #7f0055;">></span>
</pre>
</li>
<li>Restart Tomcat:</li>
<ul>
<li><tt>$CATALINA_HOME/bin/shutdown.sh</tt></li>
<li><tt>$CATALINA_HOME/bin/startup.sh</tt></li>
</ul>
</ol>
</div>
<div>
</div>
<div>
<b>Russian Localization.</b> I used <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=255633#c0">this method</a> to do it. Although you may want to try <a href="http://download.eclipse.org/birt/downloads/lang.php">BIRT Language Packs</a>.</div>
<div>
</div>
<div>
<b><br /></b><br />
<b>Troubleshooting.</b><br />
<br />
<ul style="text-align: left;">
<li>Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
<br />At least one of these environment variable is needed to run this program<br /><br />You should define <tt>JAVA_HOME</tt> variable. Execute this command before running Tomcat's <tt>*.sh</tt> files in terminal:<br /><br /><span class="Apple-style-span" style="font-family: monospace;">export JAVA_HOME=/usr/bin/java</span></li>
</ul>
<ul style="text-align: left;">
<li>If you get OutOfMemoryError you may want to give JVM more memory. Edit <tt>$CATALINA_HOME/bin/catalina.sh</tt> to include this (see <a href="http://stackoverflow.com/questions/6843893/birt-outofmemoryerror-permgen-space">this thread on stackoverflow</a>, and read more about <a href="http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp">JVM memory settings</a>):<br /><br /><span class="Apple-style-span" style="font-family: monospace;">JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx512m -XX:MaxPermSize=256m"</span></li>
</ul>
</div>
<div>
<ul style="text-align: left;">
<li>If you got OutOfMemoryError you most likely couldn't restart Tomcat using <tt>$CATALINA_HOME/bin/shutdown.sh</tt> script.<br /><br />To kill Tomcat instance use <tt>htop</tt> command in terminal. In htop interface select Tomcat process (this is <tt>/usr/lib/java</tt>), press 'k', select <tt>9 SIGKILL</tt> in "Send signal" area, and press Enter. To exit htop press 'q'.</li>
<li>Executing report never stops. Tomcat process consumes all CPU resources.<br /><br />I've seen this situation when used charts in report and they were on page break. I fixed this by moving charts to other place (far from page break). Changing page size to avoid page breaks also fixes this issue.</li>
</ul>
<br /></div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-69427070220021418632010-12-01T01:42:00.001+03:002010-12-01T04:47:17.521+03:00Deploy SharePoint Designer 2010 Reusable Workflow As *.WSP FileSharePoint Designer 2010 makes workflow development really fast and simple. Much simpler than using Visual Studio. But unlike Visual Studio this tool has some limitations from developer's point of view.<br /><br />This is due to SPD was created as a tool for end (SharePoint) users, but not for solution developers. As a result we have one serious limitation that prevents developers to use this tool: it doesn't allow deploy created workflows to another SharePoint servers. Which means you cannot develop and test workflows on a development SharePoint server and then move it to production. You forced to develop in production, which is not right.<br /><br />In particular what I said is true for reusable workflows that work with custom list instances. The problem is once you reference some list in workflow, SPD will link workflow template (<tt>*.xoml</tt>) to this list using its <code>ListId</code> attribute which is unique identifier that is valid for that particular site. This <code>ListId</code> is a random value that SharePoint generates when the list deployed. Note that you deploy list instances not only when staging ready solution from development to production, but also repeatedly during development cycle.<br /><br />There are two ways you can notice your workflow corrupted. The first is in SPD you will see GUIDs instead of list names, and if you click these GUIDs you'll see unbinded dialogs:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__b4fPTzdGYs/TPWN-NwIGQI/AAAAAAAAAmc/WaqDydUU3JY/s1600/valid-spd-workflow.PNG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 211px;" src="http://4.bp.blogspot.com/__b4fPTzdGYs/TPWN-NwIGQI/AAAAAAAAAmc/WaqDydUU3JY/s400/valid-spd-workflow.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5545494616159557890" /></a><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/TPWN-R_GWKI/AAAAAAAAAmk/0jjx5cJR-0M/s1600/broken-spd-workflow.PNG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/TPWN-R_GWKI/AAAAAAAAAmk/0jjx5cJR-0M/s400/broken-spd-workflow.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5545494617296099490" /></a><br /><br />And if you deploy such workflow to another SharePoint site (with prior export to *.WSP) you will get the error like this (in SharePoint logs) when try to run it:<br /><code><br />SOAP exception: System.Runtime.InteropServices.COMException (0x82000006): <span style="color: red;">List does not exist. The page you selected contains a list that does not exist. It may have been deleted by another user.</span><br />at Microsoft.SharePoint.SoapServer.SPBaseImpl.GetSPListByTitle(SPWeb spWeb, String strListName)<br />at Microsoft.SharePoint.SoapServer.SPBaseImpl.GetSPList(SPWeb spWeb, String strListName, Boolean bGetMetaData, Boolean bGetSecurityData)<br />at Microsoft.SharePoint.SoapServer.SPBaseImpl.GetSPList(String strListName, Boolean bGetMetaData, Boolean bGetSecurityData)<br />at Microsoft.SharePoint.SoapServer.ListSchemaImpl.GetList(String strListName)<br />at Microsoft.SharePoint.SoapServer.ListSchemaValidatorImpl.GetList(String strListName)<br />at Microsoft.SharePoint.SoapServer.Lists.GetList(String listName)<br /></code><br /><br />The most common approach you may find on the Internet is to export SPD reusable workflow to <tt>*.WSP</tt> solution package, import that <tt>*.WSP</tt> to Visual Studio and continue development there. I don't like this approach for two reasons: first is once you do this you can't open that workflow in SharePoint designer again to made any changes (and you don't want to change it in Visual Studio because, like every auto-generated code, SPD generated <tt>*.xoml</tt> is not very human-friendly):<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__b4fPTzdGYs/TPWV_2pxPCI/AAAAAAAAAms/pU9o7_lPW74/s1600/xoml-preview.PNG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 117px; height: 320px;" src="http://4.bp.blogspot.com/__b4fPTzdGYs/TPWV_2pxPCI/AAAAAAAAAms/pU9o7_lPW74/s320/xoml-preview.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5545503440411638818" /></a><br /><br />And the second (which I'm not sure, though)---you can't deploy such workflow as a sandboxed solution (correct me if I wrong).<br /><br />Fortunately, there is nothing that prevents us from deploying SPD reusable workflows except <code>ListId</code>s. All we need to do is replace broken Ids with the new ones. Here's how you may do this:<br /><br /><ol><li><a href="http://www.google.ru/search?hl=ru&q=SharePoint+Designer+2010+Save+Reusable+Workflow+As+Template">Export reusable workflows to <tt>*.WSP</tt> files</a> using SPD 2010</li><li>To fix <code>ListIds</code> change contents of the process<tt>*.xoml</tt> file contained in <tt>*.WSP</tt> file (which is <tt>*.CAB</tt> file that contain (inter alia) <tt>Feature.xml</tt>)<br />To extract and package contents of <tt>*.WSP</tt> I recommend to use PowerShell + built-in <tt>expand</tt> command and <a href="http://wspbuilder.codeplex.com/releases/view/30858">WSPBuilder's <tt>CabLib.dll</tt></a> accordingly</li><li><tt>*.xoml</tt> is an regular text/xml file so we can simply find and replace GUID strings</li><li>We know what GUIDs to be replaced by examining contents of the <tt>*.xoml</tt> file.<br />Look for entries like this:<br /><pre><span style=' color: Blue;'><</span><span style=' color: Maroon;'>ns1:LookupActivity</span> <span style=' color: Red;'>ListId</span>="<span style=' color: Blue;'>{}{<span style="font-weight:bold;">909E9DFD-A30B-4E28-BF2E-5BA47095967D</span>}</span>" <br /> <span style=' color: Red;'>x:Name</span>="<span style=' color: Blue;'>ID10</span>" <span style=' color: Red;'>FieldName</span>="<span style=' color: Blue;'>ID</span>" <span style=' color: Red;'>LookupFunction</span>="<span style=' color: Blue;'>LookupInt</span>" <br /> <span style=' color: Red;'>__Context</span>="<span style=' color: Blue;'>{ActivityBind ROOT,Path=__context}</span>" <br /> <span style=' color: Red;'>ListItem</span>="<span style=' color: Blue;'>{ActivityBind ID11,Path=ReturnValue}</span>" /<span style=' color: Blue;'>></span> <br /></pre><br /></li><li>We know the replacement for old GUIDs by using PowerShell automation: get SPWeb object of site where we want to deploy the workflow, get list in that web by list title, get ID of that list and convert that ID to string. Note that GUID string should be in upper case, otherwize you won't be able to edit workflow in SPD, though it will run okay on site (thats probably SPD bug)</li><li>After replacing GUIDs we create new <tt>*.WSP</tt> with relevant <code>ListId</code>s which may be deployed to SharePoint</li></ol><br /><br />Below is sample PowerShell script that you can use as a reference to implement steps described above. To run it save contents to file, say <tt>Deploy-Workflows.ps1</tt>, change values of <code>$siteUrl</code>, <code>$wspDir</code> and <code>$listIds</code> to match your environment. You will also have to place <a href="http://wspbuilder.codeplex.com/releases/view/30858"><tt>CabLib.dll</tt></a> and <a href="https://sites.google.com/site/dmitrygusev/AnjLab-SharePoint.ps1?attredirects=0&d=1"><tt>AnjLab-SharePoint.ps1</tt></a> files to the same folder as <tt>Deploy-Workflows.ps1</tt>. After that open SharePoint 2010 Management Shell, <tt>CD</tt> to directory with <tt>Deploy-Workflows.ps1</tt> and run the script with command <tt>.\Deploy-Workflows.ps1</tt>.<br /><br /><pre><span style=' color: Green;'># Allow running *.ps1 scripts from network shares</span> <br /><span style=' color: Green;'># Set-ExecutionPolicy Unrestricted</span> <br /><br /><span style=' color: Green;'># Copy CabLib.dll to user's temp (to prevent security exceptions if your project files are on network share)</span> <br /><span style=' color: Green;'># Note: $cablibFullName is a global variable used in AnjLab-SharePoint.ps1</span> <br /><span style=' color: #35687D;'>$cablibFullName</span> = <span style=' color: Maroon;'>"$env:TEMP\CabLib.dll"</span> <br /><span style=' color: Blue;'>if</span> ((<span style=' color: #2B91AF;'>test-path</span> <span style=' color: #35687D;'>$cablibFullName</span>) -eq <span style=' color: #35687D;'>$false</span>) <br />{ <br /> <span style=' color: #2B91AF;'>cp</span> <span style=' color: Maroon;'>"CabLib.dll"</span> <span style=' color: #35687D;'>$env</span>:TEMP <br />} <br /><br /><span style=' color: Green;'># Import AnjLab-SharePoint functions</span> <br />. .\AnjLab-SharePoint.ps1 <br /><br /><span style=' color: Green;'># Replace with yours</span> <br /><br /><span style=' color: #35687D;'>$siteUrl</span> = <span style=' color: Maroon;'>"http://dev-en/gls/"</span> <span style=' color: Green;'># SharePoint site to deploy *.WSP workflows to</span> <br /><span style=' color: #35687D;'>$wspDir</span> = <span style=' color: Maroon;'>"bin\Debug\Workflows"</span> <span style=' color: Green;'># Directory with *.WSP files </span> <br /> <span style=' color: Green;'># (all files from this folder will be updated and deployed)</span> <br /><span style=' color: #35687D;'>$wspTempDir</span> = <span style=' color: Maroon;'>"$wspDir\temp"</span> <span style=' color: Green;'># Temp directory</span> <br /><span style=' color: #35687D;'>$wspFinalDir</span> = <span style=' color: Maroon;'>"$wspDir\final"</span> <span style=' color: Green;'># Directory where final *.WSP files will be placed</span><br /><br /><span style=' color: Green;'>###################################################################################################</span> <br /><span style=' color: Green;'># Define mapping for GUID replacement in the hashtable below. </span><br /><span style=' color: Green;'># All GUIDs that match keys from this hashtable will be replaced with corresponding GUIDs of lists</span><br /><span style=' color: Green;'># taken from $siteUrl by specified list titles.</span> <br /><span style=' color: Green;'>###################################################################################################</span> <br /><br /><span style=' color: #35687D;'>$listIds</span> = @{ <span style=' color: Green;'># ListId in workflow's *.WSP List Title on SharePoint Site</span><br /> <span style=' color: Green;'># ------------------------------------- -----------------------------</span> <br /> <span style=' color: Maroon;'>"909E9DFD-A30B-4E28-BF2E-5BA47095967D"</span> = <span style=' color: Maroon;'>"Consumers"</span>; <br /> <span style=' color: Maroon;'>"2F311150-7360-45DA-A4B1-C64339F3B931"</span> = <span style=' color: Maroon;'>"Warehouses"</span>; <br /> <span style=' color: Maroon;'>"435E8D1B-FC3F-42A9-B761-1958A31D9BDE"</span> = <span style=' color: Maroon;'>"Leads"</span>; <br /> } <br /><br /><span style=' color: Green;'># Replace List Ids</span> <br /><br /><span style=' color: #35687D;'>$wspFiles</span> = (<span style=' color: #2B91AF;'>Get-ChildItem</span> <span style=' color: Maroon;'>"$wspDir\*.wsp"</span>) <br />Update-WspListIds <span style=' color: #35687D;'>$siteUrl</span> <span style=' color: #35687D;'>$wspFiles</span> <span style=' color: #35687D;'>$wspTempDir</span> <span style=' color: #35687D;'>$wspFinalDir</span> <span style=' color: #35687D;'>$listIds</span><br /><br /><span style=' color: Green;'># Deploy Packages</span> <br /><br /><span style=' color: #35687D;'>$wspFiles</span> = (<span style=' color: #2B91AF;'>Get-ChildItem</span> <span style=' color: Maroon;'>"$wspFinalDir\*.wsp"</span>) <br />Deploy-Wsp <span style=' color: #35687D;'>$siteUrl</span> <span style=' color: #35687D;'>$wspFiles</span> <span style=' color: #35687D;'>$wspTempDir</span><br /><br /><span style=' color: #2B91AF;'>Write-Host</span> <span style=' color: Maroon;'>"Done"</span> <br /></pre>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com3tag:blogger.com,1999:blog-25040534.post-11942835204710653622010-09-14T23:52:00.000+04:002010-09-15T01:31:44.882+04:00Add Interactivity to ASP.NET ReportViewerIn one of our projects I had a task to add interactivity to charts located on (MS Report Server) reports that were viewed in ASP.NET web application using <code>ReportViewer</code> control.<br /><br />Charts I worked with contained date series and user should had have the ability to add notes to data in series by clicking on that data on chart.<br /><br />In the final solution I used jQuery to find images (charts) in rendered report HTML that had special value encoded in image's <code>alt</code> tag. Client javascript (which was on the same page as <code>ReportViewer</code> control) made AJAX requests to server to calibrate chart axes. Then calibration result was used on client side to build HTML <code>MAP</code> with <code>AREA</code>s to which jQuery <code>onclick</code> handlers were attached.<br /><br />Here's how working example looked in browser:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/TI_c80H641I/AAAAAAAAAlg/_7WPP5rkmyQ/s1600/report-notes.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 222px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/TI_c80H641I/AAAAAAAAAlg/_7WPP5rkmyQ/s400/report-notes.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5516871005894271826" /></a><br /><br />Client side implementation was written in pure jQuery with help of <a href="http://craigsworks.com/projects/qtip/">jQuery qTip plugin</a> and takes around 450 lines of code. Nothing interesting.<br /><br />The most interesting part in this approach was getting chart image from generated report on server side.<br /><br />To get image on server side I used the same mechanism that <code>ReportViewer</code> web control uses. I must to say that I couldn't do this without <a href="http://www.red-gate.com/products/reflector/">Red Gate's .Net Reflector</a> (I used free version, it was enough here). This is really helpful tool that makes (nearly all) .Net libraries open sourced. I highly recommend it.<br /><br />Browser obtains chart image by URL, so I had to pass that URL to server side to grab that image from there.<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <b><font color="#0000FF">function</font></b> <b><font color="#000000">calibrate</font></b><font color="#990000">(</font>$image<font color="#990000">)</font> <font color="#FF0000">{</font><br /> $<font color="#990000">.</font><b><font color="#000000">ajax</font></b><font color="#990000">(</font><font color="#FF0000">{</font><br /> type<font color="#990000">:</font> <font color="#FF0000">"POST"</font><font color="#990000">,</font><br /> contentType<font color="#990000">:</font> <font color="#FF0000">"application/json; charset=utf-8"</font><font color="#990000">,</font><br /> url<font color="#990000">:</font> options<font color="#990000">.</font>calibrateAxesUrl<font color="#990000">,</font><br /> data<font color="#990000">:</font> <font color="#FF0000">"{imageUrl: '"</font> <font color="#990000">+</font> $image<font color="#990000">.</font><b><font color="#000000">attr</font></b><font color="#990000">(</font><font color="#FF0000">"src"</font><font color="#990000">)</font> <font color="#990000">+</font> <font color="#FF0000">"'}"</font><font color="#990000">,</font><br /> dataType<font color="#990000">:</font> <font color="#FF0000">"json"</font><font color="#990000">,</font><br /> success<font color="#990000">:</font> <b><font color="#0000FF">function</font></b><font color="#990000">(</font>msg<font color="#990000">)</font> <font color="#FF0000">{</font><br /> calibrationResult <font color="#990000">=</font> msg<font color="#990000">.</font>d<font color="#990000">;</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> process calibration result...</font></i><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><br />As you see I used image's src tag to get image URL and invoked web method <code>CalibrateAxes</code> (which is a <code>public static</code> method with <code>[WebMethod]</code> annotation) of my ASP.NET page (the full URL looks like <tt><font color="#FF0000">'</font><font color="#FF0000"><%= ResolveClientUrl("~/Reporting/ReportViewer.aspx") + "/CalibrateAxes" %></font><font color="#FF0000">'</font></tt>).<br /><br /><code>CalibrateAxes</code> method gets chart image as bitmap and does some bitmap analysis to form the result:<br /><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <font color="#990000">[</font>WebMethod<font color="#990000">]</font><br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> CalibrationResult <b><font color="#000000">CalibrateAxes</font></b><font color="#990000">(</font>string imageUrl<font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> byte<font color="#990000">[</font><font color="#990000">]</font> image <font color="#990000">=</font> <b><font color="#000000">RenderImage</font></b><font color="#990000">(</font>imageUrl<font color="#990000">)</font><font color="#990000">;</font><br /><br /> <b><font color="#0000FF">using</font></b> <font color="#990000">(</font>var stream <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">MemoryStream</font></b><font color="#990000">(</font>image<font color="#990000">)</font><font color="#990000">)</font><br /> <b><font color="#0000FF">using</font></b> <font color="#990000">(</font>var bmp <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">Bitmap</font></b><font color="#990000">(</font>stream<font color="#990000">)</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> var result <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">CalibrationResult</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> analyze bitmap...</font></i><br /><br /> <b><font color="#0000FF">return</font></b> result<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> byte<font color="#990000">[</font><font color="#990000">]</font> <b><font color="#000000">RenderImage</font></b><font color="#990000">(</font>string imageUrl<font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> var imageUri <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">Uri</font></b><font color="#990000">(</font>HttpContext<font color="#990000">.</font>Current<font color="#990000">.</font>Request<font color="#990000">.</font>Url<font color="#990000">.</font><b><font color="#000000">GetLeftPart</font></b><font color="#990000">(</font>UriPartial<font color="#990000">.</font>Authority<font color="#990000">)</font> <font color="#990000">+</font> imageUrl<font color="#990000">)</font><font color="#990000">;</font><br /><br /> var parameters <font color="#990000">=</font> HttpUtility<font color="#990000">.</font><b><font color="#000000">ParseQueryString</font></b><font color="#990000">(</font>imageUri<font color="#990000">.</font>Query<font color="#990000">)</font><font color="#990000">;</font><br /><br /> var reportSession <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"ReportSession"</font><font color="#990000">]</font><font color="#990000">;</font><br /> var controlID <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"ControlID"</font><font color="#990000">]</font><font color="#990000">;</font><br /> var culture <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"Culture"</font><font color="#990000">]</font><font color="#990000">;</font><br /> var uiCulture <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"UICulture"</font><font color="#990000">]</font><font color="#990000">;</font><br /> var reportStack <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"ReportStack"</font><font color="#990000">]</font><font color="#990000">;</font><br /> var streamID <font color="#990000">=</font> parameters<font color="#990000">[</font><font color="#FF0000">"StreamID"</font><font color="#990000">]</font><font color="#990000">;</font><br /><br /> var rs <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> ReportExecutionService<br /> <font color="#FF0000">{</font><br /> Url <font color="#990000">=</font> ConfigurationManager<font color="#990000">.</font>AppSettings<font color="#990000">[</font><font color="#FF0000">"ReportExecutionServiceUrl"</font><font color="#990000">]</font><font color="#990000">,</font><br /> Credentials <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">NetworkCredential</font></b><font color="#990000">(</font><br /> ConfigurationManager<font color="#990000">.</font>AppSettings<font color="#990000">[</font><font color="#FF0000">"ReportServerUserName"</font><font color="#990000">]</font><font color="#990000">,</font><br /> ConfigurationManager<font color="#990000">.</font>AppSettings<font color="#990000">[</font><font color="#FF0000">"ReportServerUserPassword"</font><font color="#990000">]</font><font color="#990000">,</font><br /> ConfigurationManager<font color="#990000">.</font>AppSettings<font color="#990000">[</font><font color="#FF0000">"ReportServerUserDomain"</font><font color="#990000">]</font><font color="#990000">)</font><font color="#990000">,</font><br /> ExecutionHeaderValue <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> ExecutionHeader <font color="#FF0000">{</font>ExecutionID <font color="#990000">=</font> reportSession<font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><font color="#990000">;</font><br /><br /> string deviceInfo <font color="#990000">=</font> <b><font color="#000000">GetDeviceInfo</font></b><font color="#990000">(</font>reportSession<font color="#990000">,</font> controlID<font color="#990000">,</font> culture<font color="#990000">,</font> uiCulture<font color="#990000">,</font> reportStack<font color="#990000">)</font><font color="#990000">;</font><br /><br /> string encoding<font color="#990000">;</font><br /> string mimetype<font color="#990000">;</font><br /><br /> <b><font color="#0000FF">return</font></b> rs<font color="#990000">.</font><b><font color="#000000">RenderStream</font></b><font color="#990000">(</font><font color="#FF0000">"HTML4.0"</font><font color="#990000">,</font> streamID<font color="#990000">,</font> deviceInfo<font color="#990000">,</font> out encoding<font color="#990000">,</font> out mimetype<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> string <b><font color="#000000">GetDeviceInfo</font></b><font color="#990000">(</font>string reportSession<font color="#990000">,</font> string controlID<font color="#990000">,</font> string culture<font color="#990000">,</font> string uiCulture<font color="#990000">,</font> string reportStack<font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> var writer <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">StringWriter</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> var xmlWriter <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">XmlTextWriter</font></b><font color="#990000">(</font>writer<font color="#990000">)</font><font color="#990000">;</font><br /> xmlWriter<font color="#990000">.</font><b><font color="#000000">WriteStartElement</font></b><font color="#990000">(</font><font color="#FF0000">"DeviceInfo"</font><font color="#990000">)</font><font color="#990000">;</font><br /> var url <font color="#990000">=</font> <b><font color="#000000">CreateUrl</font></b><font color="#990000">(</font>reportSession<font color="#990000">,</font> controlID<font color="#990000">,</font> culture<font color="#990000">,</font> uiCulture<font color="#990000">,</font> reportStack<font color="#990000">)</font><font color="#990000">;</font><br /> xmlWriter<font color="#990000">.</font><b><font color="#000000">WriteElementString</font></b><font color="#990000">(</font><font color="#FF0000">"StreamRoot"</font><font color="#990000">,</font> url<font color="#990000">)</font><font color="#990000">;</font><br /> xmlWriter<font color="#990000">.</font><b><font color="#000000">WriteEndElement</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> writer<font color="#990000">.</font><b><font color="#000000">ToString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> string <b><font color="#000000">CreateUrl</font></b><font color="#990000">(</font>string reportSession<font color="#990000">,</font><br /> string controlID<font color="#990000">,</font><br /> string culture<font color="#990000">,</font><br /> string uiCulture<font color="#990000">,</font><br /> string reportStack<font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> var uriBuilder <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">UriBuilder</font></b><font color="#990000">(</font>HttpContext<font color="#990000">.</font>Current<font color="#990000">.</font>Request<font color="#990000">.</font>Url<font color="#990000">.</font><b><font color="#000000">GetLeftPart</font></b><font color="#990000">(</font>UriPartial<font color="#990000">.</font>Authority<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> var applicationPath <font color="#990000">=</font> HttpContext<font color="#990000">.</font>Current<font color="#990000">.</font>Request<font color="#990000">.</font>ApplicationPath<font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font><font color="#990000">!</font>applicationPath<font color="#990000">.</font><b><font color="#000000">EndsWith</font></b><font color="#990000">(</font><font color="#FF0000">"/"</font><font color="#990000">,</font> <b><font color="#0000FF">true</font></b><font color="#990000">,</font> CultureInfo<font color="#990000">.</font>InvariantCulture<font color="#990000">)</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> applicationPath <font color="#990000">=</font> applicationPath <font color="#990000">+</font> <font color="#FF0000">"/"</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> applicationPath <font color="#990000">=</font> applicationPath <font color="#990000">+</font> <font color="#FF0000">"Reserved.ReportViewerWebControl.axd"</font><font color="#990000">;</font><br /> applicationPath <font color="#990000">=</font> HttpContext<font color="#990000">.</font>Current<font color="#990000">.</font>Response<font color="#990000">.</font><b><font color="#000000">ApplyAppPathModifier</font></b><font color="#990000">(</font>applicationPath<font color="#990000">)</font><font color="#990000">;</font><br /> uriBuilder<font color="#990000">.</font>Path <font color="#990000">=</font> applicationPath<font color="#990000">;</font><br /><br /> var builder <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">StringBuilder</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">AppendFormat</font></b><font color="#990000">(</font><font color="#FF0000">"{0}={1}"</font><font color="#990000">,</font> <font color="#FF0000">"ReportSession"</font><font color="#990000">,</font> reportSession<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">AppendFormat</font></b><font color="#990000">(</font><font color="#FF0000">"&{0}={1}"</font><font color="#990000">,</font> <font color="#FF0000">"ControlID"</font><font color="#990000">,</font> HttpUtility<font color="#990000">.</font><b><font color="#000000">UrlEncode</font></b><font color="#990000">(</font>controlID<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">AppendFormat</font></b><font color="#990000">(</font><font color="#FF0000">"&{0}={1}"</font><font color="#990000">,</font> <font color="#FF0000">"Culture"</font><font color="#990000">,</font> culture<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">AppendFormat</font></b><font color="#990000">(</font><font color="#FF0000">"&{0}={1}"</font><font color="#990000">,</font> <font color="#FF0000">"UICulture"</font><font color="#990000">,</font> uiCulture<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">AppendFormat</font></b><font color="#990000">(</font><font color="#FF0000">"&{0}={1}"</font><font color="#990000">,</font> <font color="#FF0000">"ReportStack"</font><font color="#990000">,</font> reportStack<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">Append</font></b><font color="#990000">(</font><font color="#FF0000">"&OpType=ReportImage&StreamID="</font><font color="#990000">)</font><font color="#990000">;</font><br /> uriBuilder<font color="#990000">.</font>Query <font color="#990000">=</font> builder<font color="#990000">.</font><b><font color="#000000">ToString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> <b><font color="#0000FF">return</font></b> uriBuilder<font color="#990000">.</font>Uri<font color="#990000">.</font>PathAndQuery<font color="#990000">;</font><br /> <font color="#FF0000">}</font></tt></pre><br /><br />This code of getting rendered image from report turned to be very generic, so you may also use it in your web applications.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-87524866351034872022010-09-14T10:16:00.001+04:002010-09-14T11:36:33.631+04:00Tapestry5: Caching Method ResultsAssume you have methods that (almost) always return the same result for the same input arguments. If preparing method result is a heavy operation and/or it consumes time, it is reasonable to cache these results.<br /><br />One way of building method cache in Tapestry5 is by implementing <a href="http://tapestry.apache.org/tapestry5.2-dev/apidocs/org/apache/tapestry5/ioc/MethodAdvice.html">MethodAdvice</a> interface like this:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> CacheMethodResultAdvice <b><font color="#0000FF">implements</font></b> MethodAdvice <font color="#FF0000">{</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> <b><font color="#0000FF">final</font></b> Logger logger <font color="#990000">=</font> LoggerFactory<font color="#990000">.</font><b><font color="#000000">getLogger</font></b><font color="#990000">(</font>CacheMethodResultAdvice<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Cache cache<font color="#990000">;</font><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Class<font color="#990000"><</font><font color="#990000">?</font><font color="#990000">></font> advisedClass<font color="#990000">;</font><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Object nullObject <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">Object</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">public</font></b> <b><font color="#000000">CacheMethodResultAdvice</font></b><font color="#990000">(</font>Class<font color="#990000"><</font><font color="#990000">?</font><font color="#990000">></font> advisedClass<font color="#990000">,</font> Cache cache<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>advisedClass <font color="#990000">=</font> advisedClass<font color="#990000">;</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>cache <font color="#990000">=</font> cache<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">advise</font></b><font color="#990000">(</font>Invocation invocation<font color="#990000">)</font> <font color="#FF0000">{</font><br /> String invocationSignature <font color="#990000">=</font> <b><font color="#000000">getInvocationSignature</font></b><font color="#990000">(</font>invocation<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> String entityCacheKey <font color="#990000">=</font> String<font color="#990000">.</font><b><font color="#000000">valueOf</font></b><font color="#990000">(</font>invocationSignature<font color="#990000">.</font><b><font color="#000000">hashCode</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> Object result<font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>cache<font color="#990000">.</font><b><font color="#000000">containsKey</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">)</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> result <font color="#990000">=</font> cache<font color="#990000">.</font><b><font color="#000000">get</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">)</font><font color="#990000">;</font><br /><br /> logger<font color="#990000">.</font><b><font color="#000000">debug</font></b><font color="#990000">(</font><font color="#FF0000">"Using invocation result ({}) from cache '{}'"</font><font color="#990000">,</font> invocationSignature<font color="#990000">,</font> result<font color="#990000">)</font><font color="#990000">;</font><br /><br /> invocation<font color="#990000">.</font><b><font color="#000000">overrideResult</font></b><font color="#990000">(</font>result<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <b><font color="#0000FF">else</font></b> <br /> <font color="#FF0000">{</font><br /> invocation<font color="#990000">.</font><b><font color="#000000">proceed</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font><font color="#990000">!</font>invocation<font color="#990000">.</font><b><font color="#000000">isFail</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> result <font color="#990000">=</font> invocation<font color="#990000">.</font><b><font color="#000000">getResult</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> cache<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">,</font> result<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /><br /> <b><font color="#0000FF">private</font></b> String <b><font color="#000000">getInvocationSignature</font></b><font color="#990000">(</font>Invocation invocation<font color="#990000">)</font> <font color="#FF0000">{</font><br /> StringBuilder builder <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">StringBuilder</font></b><font color="#990000">(</font><font color="#993399">150</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>advisedClass<font color="#990000">.</font><b><font color="#000000">getName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'.'</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>invocation<font color="#990000">.</font><b><font color="#000000">getMethodName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'('</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">for</font></b> <font color="#990000">(</font><font color="#009900">int</font> i <font color="#990000">=</font> <font color="#993399">0</font><font color="#990000">;</font> i <font color="#990000"><</font> invocation<font color="#990000">.</font><b><font color="#000000">getParameterCount</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font> i<font color="#990000">+</font><font color="#990000">+</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>i <font color="#990000">></font> <font color="#993399">0</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">','</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> Class<font color="#990000"><</font><font color="#990000">?</font><font color="#990000">></font> type <font color="#990000">=</font> invocation<font color="#990000">.</font><b><font color="#000000">getParameterType</font></b><font color="#990000">(</font>i<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>type<font color="#990000">.</font><b><font color="#000000">getName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">' '</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> Object param <font color="#990000">=</font> invocation<font color="#990000">.</font><b><font color="#000000">getParameter</font></b><font color="#990000">(</font>i<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>param <font color="#990000">!</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b> <font color="#990000">?</font> param <font color="#990000">:</font> nullObject<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">')'</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">return</font></b> builder<font color="#990000">.</font><b><font color="#000000">toString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /><font color="#FF0000">}</font></tt></pre><br /><br />Implementation of <code>getInvocationSignature(...)</code> is not ideal, but you may improve it to match your requirements. One issue I see here is building invocation signature for <code>null</code>-value parameters in a clustered environment (which is GAE). In this implementation method <code>nullObject.toString()</code> will return something like <code>java.lang.Object@33aa9b</code>. And this value will vary in different instances of your application. You may replace <code>nullObject</code> with just <code>"null"</code> string. Just keep in mind that <code>"null" != null</code>.<br /><br />To make this advice working you should declare it in your AppModule.java:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> @<b><font color="#000000">SuppressWarnings</font></b><font color="#990000">(</font><font color="#FF0000">"unchecked"</font><font color="#990000">)</font><br /> @<b><font color="#000000">Match</font></b><font color="#990000">(</font><font color="#FF0000">"IPResolver"</font><font color="#990000">)</font><br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> <font color="#009900">void</font> <b><font color="#000000">adviseCacheIPResolverMethods</font></b><font color="#990000">(</font><b><font color="#0000FF">final</font></b> MethodAdviceReceiver receiver<font color="#990000">,</font> Logger logger<font color="#990000">,</font> PerthreadManager perthreadManager<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">try</font></b> <font color="#FF0000">{</font><br /> Map props <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">HashMap</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> IP address of URL may change, keep it in cache for one day</font></i><br /> props<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>GCacheFactory<font color="#990000">.</font>EXPIRATION_DELTA<font color="#990000">,</font> <font color="#993399">60</font> <font color="#990000">*</font> <font color="#993399">60</font> <font color="#990000">*</font> <font color="#993399">24</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> CacheFactory cacheFactory <font color="#990000">=</font> CacheManager<font color="#990000">.</font><b><font color="#000000">getInstance</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">getCacheFactory</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> Cache cache <font color="#990000">=</font> cacheFactory<font color="#990000">.</font><b><font color="#000000">createCache</font></b><font color="#990000">(</font>props<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> LocalMemorySoftCache cache2 <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">LocalMemorySoftCache</font></b><font color="#990000">(</font>cache<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> We don't want local memory cache live longer than memcache</font></i><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Since we don't have any mechanism to set local cache expiration</font></i><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> we will just reset this cache after each request</font></i><br /> perthreadManager<font color="#990000">.</font><b><font color="#000000">addThreadCleanupListener</font></b><font color="#990000">(</font>cache2<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> receiver<font color="#990000">.</font><b><font color="#000000">adviseAllMethods</font></b><font color="#990000">(</font><b><font color="#0000FF">new</font></b> <b><font color="#000000">CacheMethodResultAdvice</font></b><font color="#990000">(</font>IPResolver<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">,</font> cache2<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font> <b><font color="#0000FF">catch</font></b> <font color="#990000">(</font>CacheException e<font color="#990000">)</font> <font color="#FF0000">{</font><br /> logger<font color="#990000">.</font><b><font color="#000000">error</font></b><font color="#990000">(</font><font color="#FF0000">"Error instantiating cache"</font><font color="#990000">,</font> e<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /><br /> @<b><font color="#000000">Match</font></b><font color="#990000">(</font><font color="#FF0000">"LocationResolver"</font><font color="#990000">)</font><br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> <font color="#009900">void</font> <b><font color="#000000">adviseCacheLocationResolverMethods</font></b><font color="#990000">(</font><b><font color="#0000FF">final</font></b> MethodAdviceReceiver receiver<font color="#990000">,</font> Cache cache<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Assume that location of IP address will never change, </font></i><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> so we don't have to set any custom cache expiration parameters</font></i><br /> receiver<font color="#990000">.</font><b><font color="#000000">adviseAllMethods</font></b><font color="#990000">(</font><b><font color="#0000FF">new</font></b> <b><font color="#000000">CacheMethodResultAdvice</font></b><font color="#990000">(</font>LocationResolver<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">,</font> cache<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font> </tt></pre><br /><br />These declarations tell Tapestry5 to add our advice to all methods of services that implement <code>IPResolver</code> and <code>LocationResolver</code> interfaces. <br /><br />Note that we able to use caches with different settings for different methods/services like in example above (see comments in code).<br /><br />See also:<br /><ul><br /><li><a href="http://tapestry.apache.org/tapestry5/tapestry-ioc/advice.html">Tapestry5 Service Advisors</a></li><br /><li><a href="http://dmitrygusev.blogspot.com/2010/09/gae-and-tapestry5-data-access-layer.html">Caching in Tapestry5 Data Access Layer</a></li><br /><li><a href="http://dmitrygusev.blogspot.com/2010/09/how-to-determine-client-timezone-in-web.html">How To Determine Client TimeZone In A Web Application</a></li><br /></ul>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com1tag:blogger.com,1999:blog-25040534.post-52636169313693501592010-09-13T16:08:00.000+04:002012-04-25T10:43:45.463+04:00How To Determine Client TimeZone In A Web Application<div dir="ltr" style="text-align: left;" trbidi="on">
In web applications when client and server located in different timezones we need a way to determine client timezone to display date/time sensitive information. This is almost always true for Google Appengine, where default server time zone is UTC.<br />
<br />
There are several ways to determine client timezone.<br />
<br />
One of them is resolving client IP address to location:<br />
<ol><br />
<li>Get client IP</li>
<br />
<li>Get client location (latitude, longitude) by the IP-address</li>
<br />
<li>Get information about timezone by the location coordinates</li>
</ol>
<br />
<br />
Every web framework provides API to get client IP. For instance, in java there is a method <code><a href="http://download-llnw.oracle.com/javaee/1.2.1/api/javax/servlet/ServletRequest.html#getRemoteAddr()">ServletRequest.getRemoteAddr()</a></code> for this purpose.<br />
<br />
To resolve IP and location information you can use one of the numerous web services available online. <br />
<br />
For instance, to resolve IP to location Ping Service uses <a href="http://ip-whois.net/ip_geo.php">IP-whois.net</a> service.<br />
<br />
Another service, <a href="http://www.geonames.org/export/web-services.html#timezone">Geonames.org</a> provides web service API to get timezone information by latitude/longitude pair.<br />
<br />
Here's an implementation of described approach in java:<br />
<br />
<br />
<pre><tt> <b><span style="color: blue;">private</span></b> TimeZone <b><span style="color: black;">getTimeZoneByClientIP</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span> <span style="color: red;">{</span>
TimeZone timeZone <span style="color: #990000;">=</span> UTC_TIME_ZONE<span style="color: #990000;">;</span>
<b><span style="color: blue;">try</span></b> <span style="color: red;">{</span>
String clientIP <span style="color: #990000;">=</span> globals<span style="color: #990000;">.</span><b><span style="color: black;">getHTTPServletRequest</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">.</span><b><span style="color: black;">getRemoteAddr</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">;</span>
<b><span style="color: blue;">if</span></b> <span style="color: #990000;">(</span><span style="color: #990000;">!</span>Utils<span style="color: #990000;">.</span><b><span style="color: black;">isNullOrEmpty</span></b><span style="color: #990000;">(</span>clientIP<span style="color: #990000;">)</span><span style="color: #990000;">)</span> <span style="color: red;">{</span>
Location location <span style="color: #990000;">=</span> locationResolver<span style="color: #990000;">.</span><b><span style="color: black;">resolveLocation</span></b><span style="color: #990000;">(</span>clientIP<span style="color: #990000;">)</span><span style="color: #990000;">;</span>
<b><span style="color: blue;">if</span></b> <span style="color: #990000;">(</span><span style="color: #990000;">!</span>location<span style="color: #990000;">.</span><b><span style="color: black;">isEmpty</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">)</span> <span style="color: red;">{</span>
timeZone <span style="color: #990000;">=</span> timeZoneResolver<span style="color: #990000;">.</span><b><span style="color: black;">resolveTimeZone</span></b><span style="color: #990000;">(</span>location<span style="color: #990000;">.</span><b><span style="color: black;">getLatitude</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">,</span> location<span style="color: #990000;">.</span><b><span style="color: black;">getLongitude</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">)</span><span style="color: #990000;">;</span>
<span style="color: red;">}</span>
<b><span style="color: blue;">if</span></b> <span style="color: #990000;">(</span>timeZone <span style="color: #990000;">=</span><span style="color: #990000;">=</span> <b><span style="color: blue;">null</span></b><span style="color: #990000;">)</span> <span style="color: red;">{</span>
timeZone <span style="color: #990000;">=</span> UTC_TIME_ZONE<span style="color: #990000;">;</span>
<span style="color: red;">}</span>
<span style="color: red;">}</span>
logger<span style="color: #990000;">.</span><b><span style="color: black;">debug</span></b><span style="color: #990000;">(</span><span style="color: red;">"Resolved timeZoneId is {}"</span><span style="color: #990000;">,</span> timeZone<span style="color: #990000;">.</span><b><span style="color: black;">getID</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">)</span><span style="color: #990000;">;</span>
<span style="color: red;">}</span> <b><span style="color: blue;">catch</span></b> <span style="color: #990000;">(</span>Exception e<span style="color: #990000;">)</span> <span style="color: red;">{</span>
logger<span style="color: #990000;">.</span><b><span style="color: black;">error</span></b><span style="color: #990000;">(</span><span style="color: red;">"Error resolving client timezone by ip "</span>
<span style="color: #990000;">+</span> globals<span style="color: #990000;">.</span><b><span style="color: black;">getHTTPServletRequest</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">.</span><b><span style="color: black;">getRemoteAddr</span></b><span style="color: #990000;">(</span><span style="color: #990000;">)</span><span style="color: #990000;">,</span> e<span style="color: #990000;">)</span><span style="color: #990000;">;</span>
<span style="color: red;">}</span>
<b><span style="color: blue;">return</span></b> timeZone<span style="color: #990000;">;</span>
<span style="color: red;">}</span></tt></pre>
<br />
<br />
The disadvantages using this approach are:<br />
<ul><br />
<li>Your code becomes dependent on third party online services that are not 100% reliable</li>
<br />
<li>Requesting third party services online will take time (up to several seconds) which may result in long response time</li>
</ul>
<br />
<cite>Note: according to Ping Service statistics IP-Whois.net availability is close to 100% with average response time ~270 ms, while Geonames.org availability is only around 80% with average response time ~1100 ms. Geonames.org low level availability is due to GAE hosting: Geonames.org restricts free access to its API to 3000 requests per IP per hour.</cite><br />
<br />
On the other hand you have <em>really simple</em> solution to implement that allows to determine client timezone at the very first client request so you can display all date/time sensitive data using client local time.<br />
<br />
See also:<br />
<ul><br />
<li><a href="http://tapestry.1045711.n5.nabble.com/DISCUSSION-Time-zones-and-date-selection-td2432626.html">DISCUSSION: Time zones and date selection</a></li>
<br />
<li><a href="http://github.com/dmitrygusev/ping-service/tree/master/ping-service/src/dmitrygusev/ping/services/location">Ping Service implementation of described approach</a></li>
<br /><ul><br />
<li><a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/ping/services/location/gae/IPWhoisNetLocationResolver.java">IPWhoisNetLocationResolver.java</a></li>
<br />
<li><a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/ping/services/location/gae/GeonamesTimeZoneResolver.java">GeonamesTimeZoneResolver.java</a></li>
</ul>
</ul>
<b>Update:</b>
GAE 1.6.5 introduces some request headers which already contains Lat/Lng pair for incoming request: <a href="https://developers.google.com/appengine/docs/java/runtime#Request_Headers">https://developers.google.com/appengine/docs/java/runtime#Request_Headers</a>
</div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com3tag:blogger.com,1999:blog-25040534.post-63298664126412631802010-09-02T00:02:00.000+04:002010-09-02T00:27:17.704+04:00Profiling GAE API callsWhile optimizing performance of GAE application its convenient to measure GAE API calls.<br /><br />I'm using the following implementation of <code>com.google.apphosting.api.ApiProxy.Delegate</code> to do this:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> ProfilingDelegate <b><font color="#0000FF">implements</font></b> Delegate<font color="#990000"><</font>Environment<font color="#990000">></font> <font color="#FF0000">{</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> <b><font color="#0000FF">final</font></b> Logger logger <font color="#990000">=</font> LoggerFactory<font color="#990000">.</font><b><font color="#000000">getLogger</font></b><font color="#990000">(</font>ProfilingDelegate<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Delegate<font color="#990000"><</font>Environment<font color="#990000">></font> parent<font color="#990000">;</font><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> String appPackage<font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">public</font></b> <b><font color="#000000">ProfilingDelegate</font></b><font color="#990000">(</font>Delegate<font color="#990000"><</font>Environment<font color="#990000">></font> parent<font color="#990000">,</font> String appPackage<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>parent <font color="#990000">=</font> parent<font color="#990000">;</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>appPackage <font color="#990000">=</font> appPackage<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">log</font></b><font color="#990000">(</font>Environment env<font color="#990000">,</font> LogRecord logRec<font color="#990000">)</font> <font color="#FF0000">{</font><br /> parent<font color="#990000">.</font><b><font color="#000000">log</font></b><font color="#990000">(</font>env<font color="#990000">,</font> logRec<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font> <b><font color="#000000">makeSyncCall</font></b><font color="#990000">(</font>Environment env<font color="#990000">,</font> String pkg<font color="#990000">,</font> String method<font color="#990000">,</font> <font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font> request<font color="#990000">)</font> <b><font color="#0000FF">throws</font></b> ApiProxyException <font color="#FF0000">{</font><br /> <font color="#009900">long</font> start <font color="#990000">=</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font> result <font color="#990000">=</font> parent<font color="#990000">.</font><b><font color="#000000">makeSyncCall</font></b><font color="#990000">(</font>env<font color="#990000">,</font> pkg<font color="#990000">,</font> method<font color="#990000">,</font> request<font color="#990000">)</font><font color="#990000">;</font><br /> StringBuilder builder <font color="#990000">=</font> <b><font color="#000000">buildStackTrace</font></b><font color="#990000">(</font>appPackage<font color="#990000">)</font><font color="#990000">;</font><br /> logger<font color="#990000">.</font><b><font color="#000000">info</font></b><font color="#990000">(</font><font color="#FF0000">"GAE/S {}.{}: ->{} ms<-\n{}"</font><font color="#990000">,</font> <b><font color="#0000FF">new</font></b> Object<font color="#990000">[</font><font color="#990000">]</font> <font color="#FF0000">{</font> pkg<font color="#990000">,</font> method<font color="#990000">,</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">-</font> start<font color="#990000">,</font> builder <font color="#FF0000">}</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> result<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <i><font color="#9A1900">/**</font></i><br /><i><font color="#9A1900"> * </font></i><br /><i><font color="#9A1900"> * </font></i><font color="#009900">@param</font><i><font color="#9A1900"> appPackage</font></i><br /><i><font color="#9A1900"> * Only classes from this package would be included in trace.</font></i><br /><i><font color="#9A1900"> * </font></i><font color="#009900">@return</font><br /><i><font color="#9A1900"> </font></i><i><font color="#9A1900">*/</font></i><br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> StringBuilder <b><font color="#000000">buildStackTrace</font></b><font color="#990000">(</font>String appPackage<font color="#990000">)</font> <font color="#FF0000">{</font><br /> StackTraceElement<font color="#990000">[</font><font color="#990000">]</font> traces <font color="#990000">=</font> Thread<font color="#990000">.</font><b><font color="#000000">currentThread</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">getStackTrace</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> StringBuilder builder <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">StringBuilder</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#009900">int</font> length <font color="#990000">=</font> traces<font color="#990000">.</font>length<font color="#990000">;</font><br /> StackTraceElement traceElement<font color="#990000">;</font><br /> String className<font color="#990000">;</font><br /> <b><font color="#0000FF">for</font></b> <font color="#990000">(</font><font color="#009900">int</font> i <font color="#990000">=</font> <font color="#993399">3</font><font color="#990000">;</font> i <font color="#990000"><</font> length<font color="#990000">;</font> i<font color="#990000">+</font><font color="#990000">+</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> traceElement <font color="#990000">=</font> traces<font color="#990000">[</font>i<font color="#990000">]</font><font color="#990000">;</font><br /> className <font color="#990000">=</font> traceElement<font color="#990000">.</font><b><font color="#000000">getClassName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>className<font color="#990000">.</font><b><font color="#000000">startsWith</font></b><font color="#990000">(</font>appPackage<font color="#990000">)</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>builder<font color="#990000">.</font><b><font color="#000000">length</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">></font> <font color="#993399">0</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'\n'</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">".."</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>className<font color="#990000">.</font><b><font color="#000000">substring</font></b><font color="#990000">(</font>className<font color="#990000">.</font><b><font color="#000000">lastIndexOf</font></b><font color="#990000">(</font><font color="#FF0000">'.'</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'.'</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>traceElement<font color="#990000">.</font><b><font color="#000000">getMethodName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">':'</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>traceElement<font color="#990000">.</font><b><font color="#000000">getLineNumber</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>builder<font color="#990000">.</font><b><font color="#000000">length</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">=</font><font color="#990000">=</font> <font color="#993399">0</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">for</font></b> <font color="#990000">(</font><font color="#009900">int</font> i <font color="#990000">=</font> <font color="#993399">1</font><font color="#990000">;</font> i <font color="#990000"><</font> length<font color="#990000">;</font> i<font color="#990000">+</font><font color="#990000">+</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> traceElement <font color="#990000">=</font> traces<font color="#990000">[</font>i<font color="#990000">]</font><font color="#990000">;</font><br /> className <font color="#990000">=</font> traceElement<font color="#990000">.</font><b><font color="#000000">getClassName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>builder<font color="#990000">.</font><b><font color="#000000">length</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">></font> <font color="#993399">0</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'\n'</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>className<font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">'.'</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>traceElement<font color="#990000">.</font><b><font color="#000000">getMethodName</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font><font color="#FF0000">':'</font><font color="#990000">)</font><font color="#990000">;</font><br /> builder<font color="#990000">.</font><b><font color="#000000">append</font></b><font color="#990000">(</font>traceElement<font color="#990000">.</font><b><font color="#000000">getLineNumber</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /> <b><font color="#0000FF">return</font></b> builder<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> Future<font color="#990000"><</font><font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font><font color="#990000">></font> <b><font color="#000000">makeAsyncCall</font></b><font color="#990000">(</font>Environment env<font color="#990000">,</font> String pkg<font color="#990000">,</font> String method<font color="#990000">,</font> <font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font> request<font color="#990000">,</font> ApiConfig config<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <font color="#009900">long</font> start <font color="#990000">=</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> Future<font color="#990000"><</font><font color="#009900">byte</font><font color="#990000">[</font><font color="#990000">]</font><font color="#990000">></font> result <font color="#990000">=</font> parent<font color="#990000">.</font><b><font color="#000000">makeAsyncCall</font></b><font color="#990000">(</font>env<font color="#990000">,</font> pkg<font color="#990000">,</font> method<font color="#990000">,</font> request<font color="#990000">,</font> config<font color="#990000">)</font><font color="#990000">;</font><br /> StringBuilder builder <font color="#990000">=</font> <b><font color="#000000">buildStackTrace</font></b><font color="#990000">(</font>appPackage<font color="#990000">)</font><font color="#990000">;</font><br /> logger<font color="#990000">.</font><b><font color="#000000">info</font></b><font color="#990000">(</font><font color="#FF0000">"GAE/A {}.{}: ->{} ms<-\n{}"</font><font color="#990000">,</font> <b><font color="#0000FF">new</font></b> Object<font color="#990000">[</font><font color="#990000">]</font> <font color="#FF0000">{</font> pkg<font color="#990000">,</font> method<font color="#990000">,</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">-</font> start<font color="#990000">,</font> builder <font color="#FF0000">}</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> result<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><font color="#FF0000">}</font></tt></pre><br /><br />To register this delegate add the following code to prior to any API calls, i.e. to filter <code>init()</code> method:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">init</font></b><font color="#990000">(</font>FilterConfig config<font color="#990000">)</font> <b><font color="#0000FF">throws</font></b> ServletException<br /> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>config <font color="#990000">=</font> config<font color="#990000">;</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Note: Comment this off to profile Google API requests</font></i><br /> ApiProxy<font color="#990000">.</font><b><font color="#000000">setDelegate</font></b><font color="#990000">(</font><b><font color="#0000FF">new</font></b> <b><font color="#000000">ProfilingDelegate</font></b><font color="#990000">(</font>ApiProxy<font color="#990000">.</font><b><font color="#000000">getDelegate</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">,</font> <font color="#FF0000">"dmitrygusev"</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><br />Here's an example of log output:<br /><pre><br />02.09.2010 0:22:19 dmitrygusev.tapestry5.gae.ProfilingDelegate makeSyncCall<br />INFO: GAE/S datastore_v3.BeginTransaction: ->1076 ms<-<br />...LazyJPATransactionManager$1.assureTxBegin:48<br />...LazyJPATransactionManager$1.createQuery:137<br />...AccountDAOImpl.findByEmail:36<br />...AccountDAOImpl.getAccount:26<br />...AccountDAOImplCache.getAccount:36<br />...Application.getUserAccount:395<br />...Application.trackUserActivity:400<br />...AppModule$1.service:229<br />...AppModule$2.service:291<br />...LazyTapestryFilter.doFilter:62<br />02.09.2010 0:22:19 dmitrygusev.tapestry5.gae.LazyJPATransactionManager$1 assureTxBegin<br />INFO: Transaction created (1200 ms) for context ...AccountDAOImpl.findByEmail:36<br />...AccountDAOImpl.getAccount:26<br />...AccountDAOImplCache.getAccount:36<br />...Application.getUserAccount:395<br />...Application.trackUserActivity:400<br />...AppModule$1.service:229<br />...AppModule$2.service:291<br /></pre><br /><br />See also <a href="http://dmitrygusev.blogspot.com/2010/09/gae-and-tapestry5-data-access-layer.html">GAE and Tapestry5 Data Access Layer</a>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-58164792556535941792010-09-01T17:32:00.000+04:002010-09-17T20:33:28.827+04:00GAE and Tapestry5 Data Access LayerGAE provides two ways communicating with its <a href="http://code.google.com/appengine/docs/java/datastore/">datastore</a> from Java:<br /><ol><br /><li>Using low-level API</li><br /><li>Using JDO/JPA (with DataNucleus appengine edition)</li></ol><br />In this post I will try to explain some performance improvements of JPA usage. Of course, there's always some overhead using high-level API. But I use JPA in <a href="http://github.com/dmitrygusev/ping-service">Ping Service</a> and think it worth it.<br /><br /><b>Update (17.09.2010):</b> <i>There is another way to communicate with GAE datastore from Java: <a href="http://code.google.com/p/objectify-appengine/">Objectify</a></i><br /><br /><h3>Spring vs. Tapestry-JPA</h3><br /><br />Its a good practice using JPA in conjunction with IoC-container to inject <code>EntityManager</code> into your services. At the very beginning of development I used Spring 3.0 as IoC and for transaction management. It worked, but it takes too much time to initialize during load requests, and every time user opens its first web page, he ended with <code>DeadlineExceededException</code>.<br /><br />Then I tried <a href="http://tynamo.org/tapestry-jpa+guide">tapestry-jpa</a> from Tynamo and it fits perfectly. It runs pretty fast and allows to:<br /><ul><br /><li>inject <code>EntityManager</code> to DAO classes (as regular T5 services)</li><br /><li>manage transactions using <code>@CommitAfter</code> annotation</li><br /></ul><br /><h3>DAO and Caching</h3><br /><br />Since GAE datastore can't operate with multiple entities in a single transaction I've added <code>@CommitAfter</code> annotation to every method of each DAO class.<br /><br />Datastore access is a an expensive operation in GAE, so I've implemented DAO-level caching:<br /><br /><b>DAO interface</b><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">interface</font></b> JobDAO <font color="#FF0000">{</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /><br /> @CommitAfter<br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">abstract</font></b> Job <b><font color="#000000">find</font></b><font color="#990000">(</font>Key jobKey<font color="#990000">)</font><font color="#990000">;</font><br /> @CommitAfter<br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">abstract</font></b> <font color="#009900">void</font> <b><font color="#000000">update</font></b><font color="#990000">(</font>Job job<font color="#990000">,</font> <font color="#009900">boolean</font> commitAfter<font color="#990000">)</font><font color="#990000">;</font><br /></tt></pre><br /><b>DAO implementation</b><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> JobDAOImpl <b><font color="#0000FF">implements</font></b> JobDAO <font color="#FF0000">{</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> Job <b><font color="#000000">find</font></b><font color="#990000">(</font>Key jobKey<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">return</font></b> em<font color="#990000">.</font><b><font color="#000000">find</font></b><font color="#990000">(</font>Job<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">,</font> jobKey<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">update</font></b><font color="#990000">(</font>Job job<font color="#990000">,</font> <font color="#009900">boolean</font> commitAfter<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font><font color="#990000">!</font>em<font color="#990000">.</font><b><font color="#000000">getTransaction</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">isActive</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> see Application#internalUpdateJob(Job)</font></i><br /> logger<font color="#990000">.</font><b><font color="#000000">debug</font></b><font color="#990000">(</font><font color="#FF0000">"Transaction is not active. Begin new one..."</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> XXX Rewrite this to handle transactions more gracefully</font></i><br /> em<font color="#990000">.</font><b><font color="#000000">getTransaction</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">begin</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> em<font color="#990000">.</font><b><font color="#000000">merge</font></b><font color="#990000">(</font>job<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>commitAfter<font color="#990000">)</font> <font color="#FF0000">{</font><br /> em<font color="#990000">.</font><b><font color="#000000">getTransaction</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">commit</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><b>DAO cache</b><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> JobDAOImplCache <b><font color="#0000FF">extends</font></b> JobDAOImpl <font color="#FF0000">{</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> Job <b><font color="#000000">find</font></b><font color="#990000">(</font>Key jobKey<font color="#990000">)</font> <font color="#FF0000">{</font><br /> Object entityCacheKey <font color="#990000">=</font> <b><font color="#000000">getEntityCacheKey</font></b><font color="#990000">(</font>Job<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">,</font> <b><font color="#000000">getJobWideUniqueData</font></b><font color="#990000">(</font>jobKey<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> Job result <font color="#990000">=</font> <font color="#990000">(</font>Job<font color="#990000">)</font> cache<font color="#990000">.</font><b><font color="#000000">get</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>result <font color="#990000">!</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">return</font></b> result<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> result <font color="#990000">=</font> <b><font color="#0000FF">super</font></b><font color="#990000">.</font><b><font color="#000000">find</font></b><font color="#990000">(</font>jobKey<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>result <font color="#990000">!</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> cache<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">,</font> result<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <b><font color="#0000FF">return</font></b> result<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">update</font></b><font color="#990000">(</font>Job job<font color="#990000">,</font> <font color="#009900">boolean</font> commitAfter<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">super</font></b><font color="#990000">.</font><b><font color="#000000">update</font></b><font color="#990000">(</font>job<font color="#990000">,</font> commitAfter<font color="#990000">)</font><font color="#990000">;</font><br /> Object entityCacheKey <font color="#990000">=</font> <b><font color="#000000">getEntityCacheKey</font></b><font color="#990000">(</font>Job<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">,</font> <b><font color="#000000">getJobWideUniqueData</font></b><font color="#990000">(</font>job<font color="#990000">.</font><b><font color="#000000">getKey</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> Job cachedJob <font color="#990000">=</font> <font color="#990000">(</font>Job<font color="#990000">)</font>cache<font color="#990000">.</font><b><font color="#000000">get</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">)</font><font color="#990000">;</font><br /><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>cachedJob <font color="#990000">!</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font><font color="#990000">!</font>cachedJob<font color="#990000">.</font><b><font color="#000000">getCronString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">equals</font></b><font color="#990000">(</font>job<font color="#990000">.</font><b><font color="#000000">getCronString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#000000">abandonJobsByCronStringCache</font></b><font color="#990000">(</font>cachedJob<font color="#990000">.</font><b><font color="#000000">getCronString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#000000">abandonJobsByCronStringCache</font></b><font color="#990000">(</font>job<font color="#990000">.</font><b><font color="#000000">getCronString</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> cache<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>entityCacheKey<font color="#990000">,</font> job<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font> <b><font color="#0000FF">else</font></b> <font color="#FF0000">{</font><br /> <b><font color="#000000">abandonJobsByCronStringCache</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> <b><font color="#000000">updateJobInScheduleCache</font></b><font color="#990000">(</font>job<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><br />Notice how update method implemented in <code>JobDAOImplCache</code>. If DAO method changes object in database it is responsible for updating all cached object instances in the entire cache. It may be difficult to support such implementation, on the other hand it may be very effective because you have full control over cache.<br /><br />Each <code>*DAOImplCache</code> class uses two-level <a href="http://jcp.org/en/jsr/detail?id=107">JSR-107</a> based cache:<br /><ul><br /><li>Level-1: Local memory (appserver instance, request scoped)<br /><p>provides quick access to objects that were "touched" during current request</p></li><br /><li>Level-2: Memcache (cluster wide)<br /><p>allows application instances to share cached objects across entire appengine cluster</p></li><br /></ul><br />Note that local memory cache should be request scoped, or it may lead to stale data across appserver instances. To reset local cache after each request it should be registered as <code>ThreadCleanupListener</code>:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> Cache <b><font color="#000000">buildCache</font></b><font color="#990000">(</font>Logger logger<font color="#990000">,</font> PerthreadManager perthreadManager<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">try</font></b> <font color="#FF0000">{</font><br /> CacheFactory cacheFactory <font color="#990000">=</font> CacheManager<font color="#990000">.</font><b><font color="#000000">getInstance</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">getCacheFactory</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> Cache cache <font color="#990000">=</font> cacheFactory<font color="#990000">.</font><b><font color="#000000">createCache</font></b><font color="#990000">(</font>Collections<font color="#990000">.</font><b><font color="#000000">emptyMap</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> LocalMemorySoftCache cache2 <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">LocalMemorySoftCache</font></b><font color="#990000">(</font>cache<font color="#990000">)</font><font color="#990000">;</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> perthreadManager may be null if we creating cache from AbstractFilter</font></i><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>perthreadManager <font color="#990000">!</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> perthreadManager<font color="#990000">.</font><b><font color="#000000">addThreadCleanupListener</font></b><font color="#990000">(</font>cache2<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> <b><font color="#0000FF">return</font></b> cache2<font color="#990000">;</font><br /> <font color="#FF0000">}</font> <b><font color="#0000FF">catch</font></b> <font color="#990000">(</font>CacheException e<font color="#990000">)</font> <font color="#FF0000">{</font><br /> logger<font color="#990000">.</font><b><font color="#000000">error</font></b><font color="#990000">(</font><font color="#FF0000">"Error instantiating cache"</font><font color="#990000">,</font> e<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> <b><font color="#0000FF">null</font></b><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><br />Here's how <code><a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/ping/services/LocalMemorySoftCache.java">LocalMemorySoftCache</a></code> implementation looks like:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> LocalMemorySoftCache <b><font color="#0000FF">implements</font></b> Cache<font color="#990000">,</font> ThreadCleanupListener <font color="#FF0000">{</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Cache cache<font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">final</font></b> Map<font color="#990000"><</font>Object<font color="#990000">,</font> Object<font color="#990000">></font> map<font color="#990000">;</font><br /> <br /> @<b><font color="#000000">SuppressWarnings</font></b><font color="#990000">(</font><font color="#FF0000">"unchecked"</font><font color="#990000">)</font><br /> <b><font color="#0000FF">public</font></b> <b><font color="#000000">LocalMemorySoftCache</font></b><font color="#990000">(</font>Cache cache<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>map <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">SoftValueMap</font></b><font color="#990000">(</font><font color="#993399">100</font><font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>cache <font color="#990000">=</font> cache<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">clear</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> map<font color="#990000">.</font><b><font color="#000000">clear</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> cache<font color="#990000">.</font><b><font color="#000000">clear</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">boolean</font> <b><font color="#000000">containsKey</font></b><font color="#990000">(</font>Object key<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">return</font></b> map<font color="#990000">.</font><b><font color="#000000">containsKey</font></b><font color="#990000">(</font>key<font color="#990000">)</font><br /> <font color="#990000">|</font><font color="#990000">|</font> cache<font color="#990000">.</font><b><font color="#000000">containsKey</font></b><font color="#990000">(</font>key<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> Object <b><font color="#000000">get</font></b><font color="#990000">(</font>Object key<font color="#990000">)</font> <font color="#FF0000">{</font><br /> Object value <font color="#990000">=</font> map<font color="#990000">.</font><b><font color="#000000">get</font></b><font color="#990000">(</font>key<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>value <font color="#990000">=</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> value <font color="#990000">=</font> cache<font color="#990000">.</font><b><font color="#000000">get</font></b><font color="#990000">(</font>key<font color="#990000">)</font><font color="#990000">;</font><br /> map<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>key<font color="#990000">,</font> value<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <b><font color="#0000FF">return</font></b> value<font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> Object <b><font color="#000000">put</font></b><font color="#990000">(</font>Object key<font color="#990000">,</font> Object value<font color="#990000">)</font> <font color="#FF0000">{</font><br /> map<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>key<font color="#990000">,</font> value<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> cache<font color="#990000">.</font><b><font color="#000000">put</font></b><font color="#990000">(</font>key<font color="#990000">,</font> value<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> Object <b><font color="#000000">remove</font></b><font color="#990000">(</font>Object key<font color="#990000">)</font> <font color="#FF0000">{</font><br /> map<font color="#990000">.</font><b><font color="#000000">remove</font></b><font color="#990000">(</font>key<font color="#990000">)</font><font color="#990000">;</font><br /> <b><font color="#0000FF">return</font></b> cache<font color="#990000">.</font><b><font color="#000000">remove</font></b><font color="#990000">(</font>key<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /><br /> <i><font color="#9A1900">/**</font></i><br /><i><font color="#9A1900"> * Reset in-memory cache but leave original cache untouched.</font></i><br /><i><font color="#9A1900"> </font></i><i><font color="#9A1900">*/</font></i><br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">reset</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> map<font color="#990000">.</font><b><font color="#000000">clear</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">threadDidCleanup</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#000000">reset</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><font color="#FF0000">}</font><br /></tt></pre><br /><br /><h3>Make Tapestry-JPA Lazy</h3><br /><br />On every request Tapestry-JPA creates new EntityManager and starts new transaction on it. And at the end of request if current transaction is still active it gets rolled back.<br /><br />But if all data were taken from cache, there won't be any interaction to database. In this case <code>EntityManager</code> creation and transaction begin/rollback were not required. But they consumed time and another resources. <br /><br />Moreover Tapestry-JPA creates <code>EntityManagerFactory</code> instance on application load which is very expensive, though you might not need it (because of DAO cache or simply because request isn't using datastore at all).<br /><br />To avoid this I created lazy implementations of <code><a href="http://tynamo.org/constant/tapestry-jpa/apidocs/org/tynamo/jpa/JPAEntityManagerSource.html">JPAEntityManagerSource</a></code>, <code><a href="http://tynamo.org/constant/tapestry-jpa/apidocs/org/tynamo/jpa/JPATransactionManager.html">JPATransactionManager</a></code> and <code>EntityManager</code>, you can find them here: <code><a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/tapestry5/gae/LazyJPAEntityManagerSource.java">LazyJPAEntityManagerSource</a></code> and <code><a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/tapestry5/gae/LazyJPATransactionManager.java">LazyJPATransactionManager</a></code>.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com2tag:blogger.com,1999:blog-25040534.post-52442649498567166452010-08-27T13:28:00.000+04:002010-08-27T15:43:52.793+04:00GAE and background workers in Tapestry5 appIn GAE you use task queues API to implement background workers.<br /><br />For instance Ping Service uses task queues to batch ping web pages according to cron schedule.<br /><br />In task queue API every task considered as an HTTP request to your application.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/THeNo8Ei-BI/AAAAAAAAAlQ/6QYq5GWGLGo/s1600/task-queue.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 213px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/THeNo8Ei-BI/AAAAAAAAAlQ/6QYq5GWGLGo/s400/task-queue.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5510028403570571282" /></a><br /><br />If you have just several requests per your billing period (say ~100 per day) then using Tapestry5 to handle tasks requests is not a bad idea since this doesn't hurt billing too much. <br /><br />But if you have thousands of requests (for instance Ping Service currently servers ~13K background jobs per day) using Tapestry5 for this purposes will be a problem. Why? Because of GAE load balancing policy. The thing is GAE may (and do) shut down/start up instances of your application sporadically for better utilization of its internal resources. And every time load request happens your T5 application will have to load and initialize entire app configuration again and again.<br /><br /><h3>Tapestry5 page as background worker</h3><br />To implement this approach you may just create new T5 page and implement worker logic in <code>onActivate()</code> method. In this case you have all the power of Tapestry5 (IoC, built-in services, activation context, etc.).<br /><br />In Tapestry5 every page should have a template file with markup. But for background workers this would typically be files with empty/dummy markup since nobody will access these pages from browser. When I used this approach I used <code>@Meta(Application.NO_MARKUP)</code> annotation and override MarkupRender service that prevents normal rendering queue for pages having this annotation and returns empty content (<code><html></html></code>) to client. <a href="http://tapestry-users.832.n2.nabble.com/Page-without-markup-tp4825548p4837185.html">Here's the discussion</a> of implementation details.<br /><br /><h3>Custom filter as background worker</h3><br /><br />Using Filter API you can declare custom filter that handle task requests. In this way Tapestry5 shouldn't be involved to processing at all and there won't be any additional overhead during load requests.<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <b><font color="#0000FF"><filter></font></b><br /> <b><font color="#0000FF"><filter-name></font></b>runJob<b><font color="#0000FF"></filter-name></font></b><br /> <b><font color="#0000FF"><filter-class></font></b>dmitrygusev.ping.filters.RunJobFilter<b><font color="#0000FF"></filter-class></font></b><br /> <b><font color="#0000FF"></filter></font></b><br /> <b><font color="#0000FF"><filter-mapping></font></b><br /> <b><font color="#0000FF"><filter-name></font></b>runJob<b><font color="#0000FF"></filter-name></font></b><br /> <b><font color="#0000FF"><url-pattern></font></b>/filters/runJob/*<b><font color="#0000FF"></url-pattern></font></b><br /> <b><font color="#0000FF"></filter-mapping></font></b><br /></tt></pre><br /><br />The problem here is that Tapestry5 also uses Filter API to handle requests and usually declared to serve all incoming requests:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> <b><font color="#0000FF"><filter-mapping></font></b><br /> <b><font color="#0000FF"><filter-name></font></b>app<b><font color="#0000FF"></filter-name></font></b><br /> <b><font color="#0000FF"><url-pattern></font></b>/*<b><font color="#0000FF"></url-pattern></font></b><br /> <b><font color="#0000FF"></filter-mapping></font></b><br /></tt></pre><br /><br />To avoid loading Tapestry5 on such request I implemented <code>LazyTapestryFilter</code> class that checks if request is a background worker URL and ignores it.<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> LazyTapestryFilter <b><font color="#0000FF">implements</font></b> Filter <font color="#FF0000">{</font><br /><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> <b><font color="#0000FF">final</font></b> Logger logger <font color="#990000">=</font> LoggerFactory<font color="#990000">.</font><b><font color="#000000">getLogger</font></b><font color="#990000">(</font>LazyTapestryFilter<font color="#990000">.</font><b><font color="#0000FF">class</font></b><font color="#990000">)</font><font color="#990000">;</font> <br /> <br /> <b><font color="#0000FF">private</font></b> Filter tapestryFilter<font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">private</font></b> FilterConfig config<font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> FilterConfig FILTER_CONFIG<font color="#990000">;</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">init</font></b><font color="#990000">(</font>FilterConfig config<font color="#990000">)</font> <b><font color="#0000FF">throws</font></b> ServletException<br /> <font color="#FF0000">{</font><br /> FILTER_CONFIG <font color="#990000">=</font> config<font color="#990000">;</font><br /> <b><font color="#0000FF">this</font></b><font color="#990000">.</font>config <font color="#990000">=</font> config<font color="#990000">;</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Note: Comment this off to profile Google API requests</font></i><br /><i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ApiProxy.setDelegate(new ProfilingDelegate(ApiProxy.getDelegate()));</font></i><br /> <font color="#FF0000">}</font><br /> <br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">doFilter</font></b><font color="#990000">(</font>ServletRequest request<font color="#990000">,</font> ServletResponse response<font color="#990000">,</font> FilterChain chain<font color="#990000">)</font> <br /> <b><font color="#0000FF">throws</font></b> IOException<font color="#990000">,</font> ServletException<br /> <font color="#FF0000">{</font><br /> String requestURI <font color="#990000">=</font> <font color="#990000">(</font><font color="#990000">(</font>HttpServletRequest<font color="#990000">)</font> request<font color="#990000">)</font><font color="#990000">.</font><b><font color="#000000">getRequestURI</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>requestURI<font color="#990000">.</font><b><font color="#000000">startsWith</font></b><font color="#990000">(</font><font color="#FF0000">"/filters/"</font><font color="#990000">)</font> <font color="#990000">|</font><font color="#990000">|</font> requestURI<font color="#990000">.</font><b><font color="#000000">equalsIgnoreCase</font></b><font color="#990000">(</font><font color="#FF0000">"/favicon.ico"</font><font color="#990000">)</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">return</font></b><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>tapestryFilter <font color="#990000">=</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> <font color="#009900">long</font> startTime <font color="#990000">=</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> logger<font color="#990000">.</font><b><font color="#000000">info</font></b><font color="#990000">(</font><font color="#FF0000">"Creating Tapestry Filter..."</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> tapestryFilter <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000000">TapestryFilter</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> tapestryFilter<font color="#990000">.</font><b><font color="#000000">init</font></b><font color="#990000">(</font>config<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> logger<font color="#990000">.</font><b><font color="#000000">info</font></b><font color="#990000">(</font><font color="#FF0000">"Tapestry Filter created and initialized ({} ms)"</font><font color="#990000">,</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font> <font color="#990000">-</font> startTime<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <br /> tapestryFilter<font color="#990000">.</font><b><font color="#000000">doFilter</font></b><font color="#990000">(</font>request<font color="#990000">,</font> response<font color="#990000">,</font> chain<font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">destroy</font></b><font color="#990000">(</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> tapestryFilter<font color="#990000">.</font><b><font color="#000000">destroy</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /><font color="#FF0000">}</font><br /></tt></pre><br /><br />Its also a good idea to skip all non-tapestry requests that you usually declare in <code>AppModule.java</code> like this:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> <font color="#009900">void</font> <b><font color="#000000">contributeIgnoredPathsFilter</font></b><font color="#990000">(</font>Configuration<font color="#990000"><</font>String<font color="#990000">></font> configuration<font color="#990000">)</font> <font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> GAE filters (Admin Console)</font></i><br /> configuration<font color="#990000">.</font><b><font color="#000000">add</font></b><font color="#990000">(</font><font color="#FF0000">"/_ah/.*"</font><font color="#990000">)</font><font color="#990000">;</font><br /><font color="#FF0000">}</font><br /></tt></pre><br /><br />Note its required for Tapestry5 to ignore these paths to enable Admin Console in development server.<br /><br />Worker filter implementation should initialize as late as possible, i.e. not in <code>init()</code> method, but in <code>doFilter()</code> because <code>init()</code> may be invoked during app server startup even if incoming request will not match that filter:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt> @Override<br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">doFilter</font></b><font color="#990000">(</font>ServletRequest request<font color="#990000">,</font> ServletResponse response<font color="#990000">,</font> FilterChain chain<font color="#990000">)</font><br /> <b><font color="#0000FF">throws</font></b> IOException<font color="#990000">,</font> ServletException<br /> <font color="#FF0000">{</font><br /> <font color="#009900">long</font> startTime <font color="#990000">=</font> System<font color="#990000">.</font><b><font color="#000000">currentTimeMillis</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font>emf <font color="#990000">=</font><font color="#990000">=</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font> <font color="#FF0000">{</font><br /> <b><font color="#000000">lazyInit</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /> <font color="#FF0000">}</font><br /></tt></pre><br /><br />Also note that using this approach you will have to manage transactions manually. You may consider Ping Service <a href="http://github.com/dmitrygusev/ping-service/blob/master/ping-service/src/dmitrygusev/ping/filters/AbstractFilter.java">AbstractFilter</a> as a reference.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-16259855184360053332010-08-26T15:53:00.000+04:002010-08-27T00:45:10.397+04:00GAE and Tapestry5 Exception HandlingTapestry5 uses its own technique to process unhandled exceptions. <br />When unhandled exception occurs Tapestry5 redirects response to special error page which is responsible to display exception detail.<br /><br />There is a standard error page in Tapestry5 that can be very helpful for developer if you configure your application to run in development mode. To do this you contribute <code>SymbolConstants.PRODUCTION_MODE</code> symbol with value <code>"false"</code> in your <code>AppModule.java</code> like this:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> <font color="#009900">void</font> <b><font color="#000000">contributeApplicationDefaults</font></b><font color="#990000">(</font><br /> MappedConfiguration<font color="#990000"><</font>String<font color="#990000">,</font> String<font color="#990000">></font> configuration<font color="#990000">)</font><br /><font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /> configuration<font color="#990000">.</font><b><font color="#000000">add</font></b><font color="#990000">(</font>SymbolConstants<font color="#990000">.</font>PRODUCTION_MODE<font color="#990000">,</font> <font color="#FF0000">"false"</font><font color="#990000">)</font><font color="#990000">;</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> ...</font></i><br /><font color="#FF0000">}</font><br /></tt></pre><br />Standard error page provides you all necessary information to understand the cause of exception:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__b4fPTzdGYs/THbQaaIAJkI/AAAAAAAAAkw/ykyoxwhYZGc/s1600/detailed-error-report.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 253px;" src="http://2.bp.blogspot.com/__b4fPTzdGYs/THbQaaIAJkI/AAAAAAAAAkw/ykyoxwhYZGc/s400/detailed-error-report.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5509820346242442818" /></a><br />And here is how exception report looks like in production:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__b4fPTzdGYs/THbQa7Ecn9I/AAAAAAAAAk4/grHDbLWNNRI/s1600/production-error-report.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 48px;" src="http://4.bp.blogspot.com/__b4fPTzdGYs/THbQa7Ecn9I/AAAAAAAAAk4/grHDbLWNNRI/s400/production-error-report.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5509820355085901778" /></a><br /><br />This is reasonable, because in production you usually don't want to display all this information to clients. But this is also not so user friendly, because it displays value of <code>Throwable.getMessage()</code>.<br /><br />Tapestry5 allows <a href="http://wiki.apache.org/tapestry/Tapestry5ExceptionPage">overriding standard error page</a> with your own exception page so you can display more user friendly messages.<br /><br />There's also another scenario when you don't want Tapestry5 to generate exception report, and let application server provide static HTML page with apologizes to client. This approach better suits for production, but in development mode its better to leave detailed error report as is.<br /><br />To change the way Tapestry5 handles exceptions you should provide another implementation of <code>RequestExceptionHandler</code>. One way doing this is to decorate <code>RequestExceptionHandler</code>:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> RequestExceptionHandler <b><font color="#000000">decorateRequestExceptionHandler</font></b><font color="#990000">(</font><br /> <b><font color="#0000FF">final</font></b> Logger logger<font color="#990000">,</font><br /> <b><font color="#0000FF">final</font></b> Response response<font color="#990000">,</font><br /> @<b><font color="#000000">Symbol</font></b><font color="#990000">(</font>SymbolConstants<font color="#990000">.</font>PRODUCTION_MODE<font color="#990000">)</font><br /> <font color="#009900">boolean</font> productionMode<font color="#990000">)</font><br /><font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Leave default implementation of RequestExceptionHandler in development mode</font></i><br /> <b><font color="#0000FF">if</font></b> <font color="#990000">(</font><font color="#990000">!</font>productionMode<font color="#990000">)</font> <b><font color="#0000FF">return</font></b> <b><font color="#0000FF">null</font></b><font color="#990000">;</font><br /><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Provide simple implementation that logs exception and returns</font></i><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> HTTP error code which will be handled by application server</font></i><br /> <b><font color="#0000FF">return</font></b> <b><font color="#0000FF">new</font></b> <b><font color="#000000">RequestExceptionHandler</font></b><font color="#990000">(</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">handleRequestException</font></b><font color="#990000">(</font>Throwable exception<font color="#990000">)</font> <b><font color="#0000FF">throws</font></b> IOException<br /> <font color="#FF0000">{</font><br /> logger<font color="#990000">.</font><b><font color="#000000">error</font></b><font color="#990000">(</font><font color="#FF0000">"Unexpected runtime exception"</font><font color="#990000">,</font> exception<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Return HTTP error code 500</font></i><br /> response<font color="#990000">.</font><b><font color="#000000">sendError</font></b><font color="#990000">(</font>HttpServletResponse<font color="#990000">.</font>SC_INTERNAL_SERVER_ERROR<font color="#990000">,</font> <b><font color="#0000FF">null</font></b><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /> <font color="#FF0000">}</font><font color="#990000">;</font><br /><font color="#FF0000">}</font><br /></tt></pre><br /><br />Next, add this markup to <code>web.xml</code>:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF"><error-page></font></b><br /> <b><font color="#0000FF"><error-code></font></b>500<b><font color="#0000FF"></error-code></font></b><br /> <b><font color="#0000FF"><location></font></b>/500.html<b><font color="#0000FF"></location></font></b><br /><b><font color="#0000FF"></error-page></font></b><br /></tt></pre><br /><br />Now in case of any exceptions client will see contents of <code>500.html</code>.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/THbSDKwKM1I/AAAAAAAAAlI/rx9inNVGkWc/s1600/error-500.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 122px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/THbSDKwKM1I/AAAAAAAAAlI/rx9inNVGkWc/s400/error-500.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5509822146002170706" /></a><br /><br />This approach have one more advantage for GAE. Generating exception reports consumes billable CPU cycles and takes request processing time. <br /><br />Saving CPU cycles is good. And there is one note about request processing time. As you may know <a href="http://code.google.com/appengine/docs/java/runtime.html#The%5FRequest%5FTimer">on GAE each request have to be processed in 30 seconds</a>. If it doesn't, then runtime raises <code>DeadlineExceededException</code> and gives application few hundreds of milliseconds to fail gracefully. As practice shows, default T5 <code>RequestExceptionHandler</code> + error report generation usually takes longer.<br /><br />One more note about GAE exception handling. Since version 1.3.6 GAE allows developers declare <a href="http://code.google.com/appengine/docs/java/config/appconfig.html#Custom_Error_Responses">custom static error handlers</a> for GAE specific errors: <code>over_quota</code>, <code>dos_api_denial</code> and <code>timeout</code>. <br />In case of first two errors GAE doesn't even pass requests to application code. Timeout errors appear as a result of application code execution and (I suppose) this static error handler may conflict with <code>RequestExceptionHandler</code> that overrides <code>DeadlineExceededException</code> with HTTP error code 500.<br /><br />I also want to share my implementation of <code>over_quota.html</code> page. I noticed free quotas got reset every day near 11am-12am Moscow Summer Time (its around 7am-8am UTC time, not sure if it the same for another applications). I thought it would be good if I include how many time is it left for GAE enabled free quotas next time. And though <code>over_quota.html</code> is a static page it is possible to include a peace of javascript that calculates this time in client timezone. Here is it:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF"><html></font></b><br /><b><font color="#0000FF"><head></font></b><br /> <b><font color="#0000FF"><title></font></b>Ping Service - Over Capacity<b><font color="#0000FF"></title></font></b><br /><b><font color="#0000FF"></head></font></b><br /><b><font color="#0000FF"><body></font></b><br /> <b><font color="#0000FF"><h1></font></b><br /> Over Capacity<br /> <b><font color="#0000FF"></h1></font></b><br /> <br /> <b><font color="#0000FF"><p></font></b><br /> We apologize for the inconvenience.<br /> <b><font color="#0000FF"></p></font></b><br /> <br /> <b><font color="#0000FF"><p></font></b><br /> Service is temporary unavailable until <b><font color="#0000FF"><span</font></b> id=<font color="#FF0000">"</font><font color="#FF0000">deadline</font><font color="#FF0000">"</font><b><font color="#0000FF">></font></b>8:00 am UTC time.<b><font color="#0000FF"></span></font></b><br /> <br /> <b><font color="#0000FF"><script</font></b> type=<font color="#FF0000">"</font><font color="#FF0000">text/javascript</font><font color="#FF0000">"</font><b><font color="#0000FF">></font></b><br /> var element = document.getElementById("deadline");<br /> var now = new Date();<br /> var deadline = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 8);<br /> var timezoneOffset = now.getTimezoneOffset() / 60;<br /> deadline.setHours(deadline.getHours() - timezoneOffset);<br /> if (deadline <= now) {<br /> deadline.setDate(deadline.getDate() + 1);<br /> }<br /> element.innerHTML = deadline.toLocaleTimeString().replace(/:00$/, "") <br /> + " your time (" <br /> + Math.round((deadline - now) / 60 / 60 / 1000) <br /> + " hours left).";<br /> <b><font color="#0000FF"></script></font></b><br /> <b><font color="#0000FF"></p></font></b><br /><b><font color="#0000FF"></body></font></b><br /><b><font color="#0000FF"></html></font></b><br /></tt></pre><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/THbQbHriQAI/AAAAAAAAAlA/iVxTnpKBVUg/s1600/over-capacity.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 108px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/THbQbHriQAI/AAAAAAAAAlA/iVxTnpKBVUg/s400/over-capacity.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5509820358471073794" /></a><br /><br />See also<br /><ul><br /><li><a href="http://wiki.apache.org/tapestry/Tapestry5HowToUseTapestryForCustomErrorPages">Serving custom HTTP error codes with T5 pages</a></li><br /><li>Sources of <a href="http://ping-service.appspot.com/">one live T5 GAE application</a>: <a href="http://github.com/dmitrygusev/ping-service">http://github.com/dmitrygusev/ping-service</a></li><br /></ul>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com4tag:blogger.com,1999:blog-25040534.post-15362180831412625182010-04-28T15:37:00.000+04:002010-05-14T17:02:01.276+04:00AnjLab.FX Scheduler for ASP.NETIf you need simple yet easy configurable scheduler in your ASP.NET application, AnjLab.FX Scheduler might be your choise.<br /><br />To use AnjLab.FX Scheduler you need to do 3 simple steps:<br /><br /><ol start="0"><br /><li>Get the latest version of AnjLab.FX from <a href="http://github.com/anjlab/fx">github</a>, make a build and add AnjLab.FX.dll as a reference to your project;</li><br /><li><span style="font-weight:bold;">Implement <code>AnjLab.FX.Sys.ICommand</code> interface on your task workers</span>, like this:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> HelloWorldTask <font color="#990000">:</font> ICommand<br /><font color="#FF0000">{</font><br /> <b><font color="#0000FF">private</font></b> <b><font color="#0000FF">static</font></b> readonly log4net<font color="#990000">.</font>ILog Log <font color="#990000">=</font> log4net<font color="#990000">.</font>LogManager<font color="#990000">.</font><b><font color="#000000">GetLogger</font></b><font color="#990000">(</font><b><font color="#000000">typeof</font></b><font color="#990000">(</font>HelloWorldTask<font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> <b><font color="#0000FF">public</font></b> <font color="#009900">void</font> <b><font color="#000000">Execute</font></b><font color="#990000">(</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> Log<font color="#990000">.</font><b><font color="#000000">Info</font></b><font color="#990000">(</font><font color="#FF0000">"Hello World!"</font><font color="#990000">)</font><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><font color="#FF0000">}</font><br /></tt></pre></li><br /><li><span style="font-weight:bold;">Configure tasks schedule in <code>web.config</code>.</span> To do this you need to:<br /><ol start="a"><br /><li>add the following line to <code>web.config/configuration/configSections</code>:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#000080"><?xml</font></b> version=<font color="#FF0000">"</font><font color="#FF0000">1.0</font><font color="#FF0000">"</font> encoding=<font color="#FF0000">"</font><font color="#FF0000">UTF-8</font><font color="#FF0000">"</font><b><font color="#000080">?></font></b><br /><b><font color="#0000FF"><configuration></font></b><br /> <b><font color="#0000FF"><configSections></font></b><br /> ...<br /> <b><font color="#0000FF"><section</font></b> name=<font color="#FF0000">"</font><font color="#FF0000">triggers</font><font color="#FF0000">"</font> type=<font color="#FF0000">"</font><font color="#FF0000">AnjLab.FX.Tasks.Scheduling.SchedulerConfigSection, AnjLab.FX</font><font color="#FF0000">"</font><b><font color="#0000FF">/></font></b><br /> ...</tt></pre></li><br /><li>define <code>triggers</code> section:<br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF"><configuration></font></b><br /> ...<br /> <b><font color="#0000FF"><triggers></font></b><br /> <i><font color="#9A1900"><!--</font></i><br /><i><font color="#9A1900"> <daily tag='restoreDB' timeOfDay='23:00'/></font></i><br /><i><font color="#9A1900"> <weekly tag='backupDB' timeOfDay='01:30' weekDays='monday,friday'/></font></i><br /><i><font color="#9A1900"> <hourly tag='delTempFiles' minutes='30'/></font></i><br /><i><font color="#9A1900"> <interval tag='dumpLog' interval='00:05:00'/></font></i><br /><i><font color="#9A1900"> <once tag='upgradeDB' dateTime='01/15/2007 23:00'/></font></i><br /><i><font color="#9A1900"> <monthly tag='archiveDB' monthDay='29' timeOfDay='23:00'/></font></i><br /><i><font color="#9A1900"> </font></i><i><font color="#9A1900">--></font></i><br /> <b><font color="#0000FF"><interval</font></b> tag='helloworld-task' interval='00:00:10'<b><font color="#0000FF">/></font></b><br /> <b><font color="#0000FF"></triggers></font></b><br /> ...<br /><b><font color="#0000FF"></configuration></font></b><br /></tt></pre><br />Here we defined named trigger "helloworld-task" to be triggered every 10 seconds.<br /></li><br /></ol><br /><li><span style="font-weight:bold;">Map trigger names to your task workers and start up the scheduler.</span><br /><br />To map your task workers you create instance of KeyedFactory and register your tasks. We propose you do this in <code>Global.asax</code> <code>Application_Start</code> method:<br /><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#0000FF">protected</font></b> <font color="#009900">void</font> <b><font color="#000000">Application_Start</font></b><font color="#990000">(</font>object sender<font color="#990000">,</font> EventArgs e<font color="#990000">)</font><br /><font color="#FF0000">{</font><br /> <i><font color="#9A1900">//</font></i><i><font color="#9A1900"> Map trigger names to task workers</font></i><br /><br /> var factory <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> KeyedFactory<font color="#990000"><</font>string<font color="#990000">,</font> ICommand<font color="#990000">></font><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /> factory<font color="#990000">.</font>RegisterType<font color="#990000"><</font>HelloWorldTask<font color="#990000">></font><font color="#990000">(</font><font color="#FF0000">"helloworld-task"</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> <i><font color="#9A1900">// Start up scheduler</font></i><br /><br /> var scheduler <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> Scheduler<font color="#990000"><</font>ICommand<font color="#990000">></font><font color="#990000">(</font>factory<font color="#990000">)</font><font color="#990000">;</font><br /> <br /> var triggers <font color="#990000">=</font> <font color="#990000">(</font>List<font color="#990000"><</font>ITrigger<font color="#990000">></font><font color="#990000">)</font>ConfigurationManager<font color="#990000">.</font><b><font color="#000000">GetSection</font></b><font color="#990000">(</font><font color="#FF0000">"triggers"</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> scheduler<font color="#990000">.</font><b><font color="#000000">RegisterTriggers</font></b><font color="#990000">(</font>triggers<font color="#990000">.</font><b><font color="#000000">ToArray</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">)</font><font color="#990000">;</font><br /><br /> scheduler<font color="#990000">.</font><b><font color="#000000">Start</font></b><font color="#990000">(</font><font color="#990000">)</font><font color="#990000">;</font><br /><font color="#FF0000">}</font><br /></tt></pre></li><br /></ol><br />Thats it!<br /><br />Resources:<br /><ul><li>AnjLab.FX on github: <a href="http://github.com/anjlab/fx">http://github.com/anjlab/fx</a></li><br /><li><a href="http://www.rsdn.ru/article/patterns/KeyedFactory.xml">Here</a> is an article about KeyedFactory pattern in Russian</li></ul><br /><br />P.S.<br />By the way, you can also use this API to schedule your tasks in Windows.Forms applications as well.<br /><br />P.P.S.<br />AnjLab.FX is a framework we built during development of our projects. Its continue evolving and you can use it in your applications without any restrictions.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com3tag:blogger.com,1999:blog-25040534.post-41709380668756325182010-04-28T15:14:00.000+04:002010-04-28T15:36:00.805+04:00МОДИФИКАЦИЯ АЛГОРИТМА ТОРБЕНА ДЛЯ ПОИСКА МЕДИАНЫ В БОЛЬШОМ ОДНОМЕРНОМ МАССИВЕВыкладываю статью, как и обещал в <a href="http://dmitrygusev.blogspot.com/2010/01/histogram-based-median-search.html">предыдущем посте</a>.<br /><br />МОДИФИКАЦИЯ АЛГОРИТМА ТОРБЕНА ДЛЯ ПОИСКА МЕДИАНЫ В БОЛЬШОМ ОДНОМЕРНОМ МАССИВЕ<br />Гусев Д.И.<br />Владимирский государственный университет<br /><br /><b>Аннотация</b><br />В статье предлагается алгоритм поиска медианы, основанный на известном алгоритме Торбена. Особенностью обоих алгоритмов является то, что при поиске медианы они не требует изменения исходного массива и позволяют читать весь массив последовательно. Приводятся характеристики предлагаемого алгоритма, которые при определенных параметрах показывают производительность более 40% относительно алгоритма Торбена.<br /><br />Скачать: <img style="border: 0px; width: 16px; height: 16px;" src="http://sites.google.com/site/dmitrygusev/system/app/images/attach_icons/icon_pdf.gif" /> <a href="http://sites.google.com/site/dmitrygusev/histogram-based-median-search.pdf?attredirects=0&d=1">Текст статьи</a> (241 КБ)Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-43430763787401437542010-01-25T17:59:00.000+03:002010-01-25T18:31:34.258+03:00Histogram-based median searchРеализация алгоритма поиска медианы в большом одномерном массиве чисел.<br />Это измененный вариант известного алгоритма Торбена.<br />Привожу этот алгоритм здесь, чтобы на него можно было сослаться.<br />Сам алгоритм приводится без пояснений, пояснения и характеристики производительности позже выложу здесь же в виде статьи.<br /><br /><div align="left" class="java"><br /><table border="0" cellpadding="3" cellspacing="0" bgcolor="#ffffff"><br /> <tr><br /> <td nowrap="nowrap" valign="top" align="left"><br /> <code><br /><font color="#7f0055"><b>package </b></font><font color="#000000">anjlab.cubics.aggregate.median;</font><br /><font color="#ffffff"></font><br /><font color="#7f0055"><b>import </b></font><font color="#000000">java.util.Arrays;</font><br /><font color="#ffffff"></font><br /><font color="#3f5fbf">/**</font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* Histogram-based implementation of median search algorithm.</font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* </font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* Based on N. Devillard's implementation of Torben Mogensen's algorithm </font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* (</font><font color="#3f3fbf">{@linkplain http://ndevilla.free.fr/median/median.pdf}</font><font color="#3f5fbf">).</font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* </font><br /><font color="#ffffff"> </font><font color="#3f5fbf">* </font><font color="#7f9fbf">@author </font><font color="#3f5fbf">Dmitry Gusev </font><br /><font color="#ffffff"> </font><font color="#3f5fbf">*/</font><br /><font color="#7f0055"><b>public class </b></font><font color="#000000">HistogramBasedMedianFinder </font><font color="#000000">{</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>private final </b></font><font color="#7f0055"><b>int </b></font><font color="#000000">K; </font><font color="#3f7f5f">// number of ranges to create in histogram</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>private final </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">epsilon;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#000000">HistogramBasedMedianFinder</font><font color="#000000">() {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">(</font><font color="#990000">15</font><font color="#000000">, </font><font color="#990000">0.000000001d</font><font color="#000000">)</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#000000">HistogramBasedMedianFinder</font><font color="#000000">(</font><font color="#7f0055"><b>int </b></font><font color="#000000">k, </font><font color="#7f0055"><b>double </b></font><font color="#000000">epsilon</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">.K = k;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">.epsilon = epsilon;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">search</font><font color="#000000">(</font><font color="#7f0055"><b>double</b></font><font color="#000000">[] </font><font color="#000000">m</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">n = m.length;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">correction = n % </font><font color="#990000">2 </font><font color="#000000">== </font><font color="#990000">0 </font><font color="#000000">? </font><font color="#990000">1 </font><font color="#000000">: </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>double </b></font><font color="#000000">min, max;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#000000">min = max = m</font><font color="#000000">[</font><font color="#990000">0</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>for </b></font><font color="#000000">(</font><font color="#7f0055"><b>int </b></font><font color="#000000">i = </font><font color="#990000">1</font><font color="#000000">; i < n; i++</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">m</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">] </font><font color="#000000">< min</font><font color="#000000">) </font><font color="#000000">min = m</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">m</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">] </font><font color="#000000">> max</font><font color="#000000">) </font><font color="#000000">max = m</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">leftOutRange = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">rightOutRange = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#000000">Histogram histogram = </font><font color="#7f0055"><b>new </b></font><font color="#000000">Histogram</font><font color="#000000">()</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>while </b></font><font color="#000000">(</font><font color="#7f0055"><b>true</b></font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#000000">histogram.init</font><font color="#000000">(</font><font color="#000000">min, max</font><font color="#000000">)</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>for </b></font><font color="#000000">(</font><font color="#7f0055"><b>int </b></font><font color="#000000">i = </font><font color="#990000">0</font><font color="#000000">; i < n; i++</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#000000">histogram.add</font><font color="#000000">(</font><font color="#000000">m</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">])</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">countInRanges = histogram.totalCount - histogram.others;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">countInRanges == </font><font color="#990000">1</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>return </b></font><font color="#000000">histogram.recentlyAdded;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">incCount = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>for </b></font><font color="#000000">(</font><font color="#7f0055"><b>int </b></font><font color="#000000">i = </font><font color="#990000">0</font><font color="#000000">; i < histogram.rangeCount; i++</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">rangeCount = histogram.counts</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#000000">incCount += rangeCount;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>long </b></font><font color="#000000">rightOutCurrentRange = </font><font color="#000000">(</font><font color="#000000">countInRanges + rightOutRange</font><font color="#000000">) </font><font color="#000000">- incCount;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">incCount + leftOutRange >= rightOutCurrentRange - correction</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#3f7f5f">// Median is in this range. Repeat search in this range</font><br /><font color="#ffffff"> </font><font color="#000000">min = i == </font><font color="#990000">0 </font><font color="#000000">? histogram.start : histogram.ranges</font><font color="#000000">[</font><font color="#000000">i - </font><font color="#990000">1</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">max = histogram.ranges</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">almostSame</font><font color="#000000">(</font><font color="#000000">min, max</font><font color="#000000">)) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>return </b></font><font color="#000000">min;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#000000">leftOutRange += </font><font color="#000000">(</font><font color="#000000">incCount - rangeCount</font><font color="#000000">)</font><font color="#000000">; </font><br /><font color="#ffffff"> </font><font color="#000000">rightOutRange = rightOutCurrentRange;</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>break</b></font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>boolean </b></font><font color="#000000">almostSame</font><font color="#000000">(</font><font color="#7f0055"><b>double </b></font><font color="#000000">a, </font><font color="#7f0055"><b>double </b></font><font color="#000000">b</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>return </b></font><font color="#000000">Math.abs</font><font color="#000000">(</font><font color="#000000">a - b</font><font color="#000000">) </font><font color="#000000">< epsilon;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>private class </b></font><font color="#000000">Histogram </font><font color="#000000">{</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">start;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">end;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>private </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">step;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>double</b></font><font color="#000000">[] </font><font color="#000000">ranges = </font><font color="#7f0055"><b>new </b></font><font color="#7f0055"><b>double</b></font><font color="#000000">[</font><font color="#000000">K + </font><font color="#990000">1</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>long</b></font><font color="#000000">[] </font><font color="#000000">counts = </font><font color="#7f0055"><b>new </b></font><font color="#7f0055"><b>long</b></font><font color="#000000">[</font><font color="#000000">K + </font><font color="#990000">1</font><font color="#000000">]</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>double </b></font><font color="#000000">recentlyAdded;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>long </b></font><font color="#000000">totalCount;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>long </b></font><font color="#000000">others;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>int </b></font><font color="#000000">rangeCount;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>void </b></font><font color="#000000">init</font><font color="#000000">(</font><font color="#7f0055"><b>double </b></font><font color="#000000">start, </font><font color="#7f0055"><b>double </b></font><font color="#000000">end</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">.start = start;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">.end = end;</font><br /><font color="#ffffff"> </font><font color="#000000">Arrays.fill</font><font color="#000000">(</font><font color="#000000">counts, </font><font color="#990000">0</font><font color="#000000">)</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">others = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">totalCount = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">end < start || almostSame</font><font color="#000000">(</font><font color="#000000">start, end</font><font color="#000000">)) {</font><br /><font color="#ffffff"> </font><font color="#000000">rangeCount = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">} </font><font color="#7f0055"><b>else </b></font><font color="#000000">{</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>this</b></font><font color="#000000">.step = </font><font color="#000000">(</font><font color="#000000">end - start</font><font color="#000000">) </font><font color="#000000">/ K;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">idx = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>for </b></font><font color="#000000">(</font><font color="#7f0055"><b>double </b></font><font color="#000000">i = start; i < end; i += step</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>double </b></font><font color="#000000">right = i + step;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">right > end</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#000000">right = end;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">ranges</font><font color="#000000">[</font><font color="#000000">idx++</font><font color="#000000">] </font><font color="#000000">= right;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">rangeCount = idx;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>public </b></font><font color="#7f0055"><b>void </b></font><font color="#000000">add</font><font color="#000000">(</font><font color="#7f0055"><b>double </b></font><font color="#000000">value</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#000000">totalCount++;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">value < start || value > end</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#000000">others++;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>return</b></font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#000000">recentlyAdded = value;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#3f7f5f">// binary search</font><br /><font color="#ffffff"> </font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">low = </font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">high = rangeCount - </font><font color="#990000">1</font><font color="#000000">;</font><br /><font color="#ffffff"></font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>while </b></font><font color="#000000">(</font><font color="#000000">low <= high</font><font color="#000000">) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>int </b></font><font color="#000000">mid = </font><font color="#000000">(</font><font color="#000000">high + low</font><font color="#000000">) </font><font color="#000000">>>> </font><font color="#990000">1</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">value <= ranges</font><font color="#000000">[</font><font color="#000000">mid</font><font color="#000000">]) {</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>if </b></font><font color="#000000">(</font><font color="#000000">mid > </font><font color="#990000">0 </font><font color="#000000">&& value < ranges</font><font color="#000000">[</font><font color="#000000">mid - </font><font color="#990000">1</font><font color="#000000">]) {</font><br /><font color="#ffffff"> </font><font color="#000000">high = mid - </font><font color="#990000">1</font><font color="#000000">; </font><font color="#3f7f5f">// continue search</font><br /><font color="#ffffff"> </font><font color="#000000">} </font><font color="#7f0055"><b>else </b></font><font color="#000000">{</font><br /><font color="#ffffff"> </font><font color="#000000">counts</font><font color="#000000">[</font><font color="#000000">mid</font><font color="#000000">]</font><font color="#000000">++; </font><font color="#3f7f5f">// we've found the range</font><br /><font color="#ffffff"> </font><font color="#7f0055"><b>return</b></font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">} </font><font color="#7f0055"><b>else if </b></font><font color="#000000">(</font><font color="#000000">value > ranges</font><font color="#000000">[</font><font color="#000000">mid</font><font color="#000000">]) {</font><br /><font color="#ffffff"> </font><font color="#000000">low = mid + </font><font color="#990000">1</font><font color="#000000">;</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">}</font><br /><font color="#ffffff"> </font><font color="#000000">} </font><br /><font color="#000000">}</font></code><br /> </td><br /> </tr><br /></table><br /></div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-26337174610413867562010-01-15T01:06:00.000+03:002010-01-15T01:29:13.556+03:00Adobe Reader Team!Сегодня вышло новое обновление Adobe Reader 8.2.0.<br />Как обычно, тихо и незаметно.<br />За все время сколько пользуюсь Reader'ом (с 2000 года, как только появился первый компьютер) ни разу не заглядывал в окошко Credits. Сегодня заглянул.<br /><br />Оказывается в команде Adobe Reader'а почти 1000 человек! (971 если быть точным)<br /><br />Может я никогда не уделял этому внимания, но по-моему это самая большая команда, про которую я слышал. Точнее я слышал про компании с несколькими десятками/сотнями разработчиков, но как-то в общем, без конкретики.<br /><br />А тут в окошке Credits расписаны все команды и упомянут каждый член команды лично!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/S0-XPTOEShI/AAAAAAAAAhg/GbY332YuMFw/s1600-h/credits.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 248px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/S0-XPTOEShI/AAAAAAAAAhg/GbY332YuMFw/s400/credits.png" alt="" id="BLOGGER_PHOTO_ID_5426722365117843986" border="0" /></a><br /><br />Решил ради интереса всех пересчитать, получилось целых 42 команды!<br /><br />Между прочим, судя по (с) в окошке About, Reader'у уже 26-й год! (1984-2010)<br />Мы с ним почти ровесники :)<br /><br />Желаю им и дальше расти и процветать!<br /><br />p.s.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__b4fPTzdGYs/S0-XokY-KeI/AAAAAAAAAho/Gukd1caUOio/s1600-h/teams.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 229px;" src="http://2.bp.blogspot.com/__b4fPTzdGYs/S0-XokY-KeI/AAAAAAAAAho/Gukd1caUOio/s400/teams.png" alt="" id="BLOGGER_PHOTO_ID_5426722799223712226" border="0" /></a><br /><br /><div align="center"><br /><table style="border-collapse: collapse; width: 491px; height: 907px;" border="0" cellpadding="0" cellspacing="0"><col style="width: 281pt;" width="375"> <col style="width: 87pt;" width="116"> <tbody><tr style="height: 15pt;" height="20"> <td style="border-style: solid none; border-color: rgb(79, 129, 189) -moz-use-text-color; border-width: 0.5pt medium; height: 15pt; width: 281pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 700; text-decoration: none; font-family: Calibri;" height="20" width="375">Team</td> <td style="border-style: solid none; border-color: rgb(79, 129, 189) -moz-use-text-color; border-width: 0.5pt medium; width: 87pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 700; text-decoration: none; font-family: Calibri; text-align: right;" width="116"># of members</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Team Engineering</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">141</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Quality Engineering</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">113</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Engineering Management</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">55</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Release Engineering</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">5</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Product Management</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">14</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Marketing and Business Management</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">22</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Acrobat Administration</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">5</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Globalization</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">16</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Prerelease Programs</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">5</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">User Interface</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">14</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Additional Engineering</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">62</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Additional Quality Engineering</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">40</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Additional Engineering Management</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">57</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Additional Product, Marketing, and Business Management</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">9</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Management</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">14</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech Adobe Graphics Manager</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">7</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Adobe Graphics Manager Printing</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">7</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech Adobe XML Engine</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">6</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Color Management</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">4</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Type</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">8</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech PDF Libraries</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">10</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech Architecture</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">12</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Scripting</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">6</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech AMT</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">50</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech AMT Quality Engineering</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">18</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech Metadata</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">4</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Sangam</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">4</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Core Tech Quality Engineering</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">52</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Core Tech Admins</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">8</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Adobe Production Quality Engineering Team</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">20</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Legal</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">7</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Visual Design</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">6</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Adobe Systems Japan</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">13</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Adobe Systems China</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">4</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Type</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">9</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Technical and Customer Support</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">15</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Developer Support</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">18</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Client Services Support</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">26</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Learning Resources</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">43</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Information Technology</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">12</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20">Packaging and Manufacturing</td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" align="right">14</td> </tr> <tr style="height: 15pt;" height="20"> <td style="height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" height="20">Adobe.com Web Team</td> <td style="font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri;" align="right">16</td> </tr> <tr style="height: 15pt;" height="20"> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" height="20"><br /></td> <td style="background: rgb(219, 229, 241) none repeat scroll 0% 0%; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 400; text-decoration: none; font-family: Calibri; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;"><br /></td> </tr> <tr style="height: 15pt;" height="20"> <td class="xl65" style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color rgb(79, 129, 189); border-width: medium medium 0.5pt; height: 15pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 700; text-decoration: none; font-family: Calibri;" height="20">Total</td> <td class="xl65" style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color rgb(79, 129, 189); border-width: medium medium 0.5pt; font-size: 11pt; color: rgb(55, 96, 145); font-weight: 700; text-decoration: none; font-family: Calibri;" align="right">971</td> </tr> </tbody></table><br /></div>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-1713479405719926332009-12-24T12:13:00.001+03:002009-12-24T12:29:25.378+03:00Пару строчек из серии комментарии в кодеВ работе с чужим кодом есть свои прелести :)<br /><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color:#0000FF;">public</span></b> <b><span style="color:#0000FF;">static</span></b> String RUSSIAN_NO_STRING <span style="color:#990000;">=</span> <span style="color:#FF0000;">"НЕТ"</span><span style="color:#990000;">;</span> <i><span style="color:#9A1900;">//</span></i><i><span style="color:#9A1900;"> russion word HET, do not try to correct this string!</span></i></tt></pre><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><i><span style="color:#9A1900;">/**</span></i><br /><i><span style="color:#9A1900;"> *</span></i><b><span style="color:#0000FF;"><P></span></b><i><span style="color:#9A1900;">!!!! Pay attention to similiar (the same) method on PrintHandler.</span></i><br /><i><span style="color:#9A1900;"> * This method might be not used at all, there is quite mess about that.</span></i><br /><i><span style="color:#9A1900;"> </span></i><i><span style="color:#9A1900;">*/</span></i><br /></tt></pre>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com2tag:blogger.com,1999:blog-25040534.post-57708632849959708682009-11-28T17:10:00.000+03:002009-11-30T23:52:30.866+03:00Best Practice: Implementing Telerik RadGrid with Linq(ToSQL)Telerik RadGrid is a very powerful component that allows you to view, edit, order and filter data.<br /><br />I'd like to share my experience using this component with <a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx">linq to sql</a>.<br /><br />Using this component is very straightforward unless your entity contains references to other entities (in other words if your table have foreign keys to other tables, see DB diagram below). Very often such relations have a kind of reference data.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__b4fPTzdGYs/SxE37M5Z6AI/AAAAAAAAAf0/fKQxBzmpLXU/s1600/domain-db.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 114px;" src="http://1.bp.blogspot.com/__b4fPTzdGYs/SxE37M5Z6AI/AAAAAAAAAf0/fKQxBzmpLXU/s400/domain-db.png" alt="" id="BLOGGER_PHOTO_ID_5409166117662484482" border="0" /></a><br /><br />In this case you may meet the following difficulties:<br /><ol><li>ability to display data field of referenced entity (except its ID, of course) in grid column;</li><li>ability to sort and filter data set of your entities by columns which are references to other entities.</li></ol><br /><br /><span style="font-weight: bold;">To understand the cause of these difficulties</span> lets look at simple example.<br /><br />Generated Linq to SQL model for the database schema above will look like the following:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/SxE5fi9pt4I/AAAAAAAAAf8/1vjr1Iiofkg/s1600/domain-classes.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 143px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/SxE5fi9pt4I/AAAAAAAAAf8/1vjr1Iiofkg/s400/domain-classes.png" alt="" id="BLOGGER_PHOTO_ID_5409167841572796290" border="0" /></a><br /><br />Now, to display a list of Books in RadGrid you should implement databinding. To do this you usually subscribe to RadGrid's <a href="http://www.telerik.com/help/aspnet/grid/radgrid-telerik.webcontrols.radgrid-needdatasource_ev.html">OnNeedDataSource event</a> and invoke <code>RadGrid.DataBind()</code> in <code>PageLoad</code> event handler:<br /><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);">protected</span></b> <span style="color: rgb(0, 153, 0);">void</span> <b><span style="color: rgb(0, 0, 0);">Page_Load</span></b><span style="color: rgb(153, 0, 0);">(</span>object sender<span style="color: rgb(153, 0, 0);">,</span> EventArgs e<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>IsPostBack<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">DataBind</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /><br /><b><span style="color: rgb(0, 0, 255);">protected</span></b> <span style="color: rgb(0, 153, 0);">void</span> <b><span style="color: rgb(0, 0, 0);">RadGrid1_NeedDataSource</span></b><span style="color: rgb(153, 0, 0);">(</span>object source<span style="color: rgb(153, 0, 0);">,</span> GridNeedDataSourceEventArgs e<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>e<span style="color: rgb(153, 0, 0);">.</span>IsFromDetailTable<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>e<span style="color: rgb(153, 0, 0);">.</span>RebindReason <span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(153, 0, 0);">=</span> GridRebindReason<span style="color: rgb(153, 0, 0);">.</span>InitialLoad<br /> <span style="color: rgb(153, 0, 0);">|</span><span style="color: rgb(153, 0, 0);">|</span> e<span style="color: rgb(153, 0, 0);">.</span>RebindReason <span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(153, 0, 0);">=</span> GridRebindReason<span style="color: rgb(153, 0, 0);">.</span>ExplicitRebind<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>VirtualItemCount <span style="color: rgb(153, 0, 0);">=</span> Book<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetBooksCount</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <span style="color: rgb(0, 153, 0);">int</span> skip <span style="color: rgb(153, 0, 0);">=</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>CurrentPageIndex <span style="color: rgb(153, 0, 0);">*</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>PageSize<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(0, 153, 0);">int</span> take <span style="color: rgb(153, 0, 0);">=</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>PageSize<span style="color: rgb(153, 0, 0);">;</span><br /><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>DataSource <span style="color: rgb(153, 0, 0);">=</span> Book<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetBooks</span></b><span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">,</span> take<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /></tt></pre><br /><br />Here's our data access methods:<br /><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> <span style="color: rgb(0, 153, 0);">int</span> <b><span style="color: rgb(0, 0, 0);">GetBooksCount</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Count</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /><br /><b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> List<Book> <b><span style="color: rgb(0, 0, 0);">GetBooks</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> skip<span style="color: rgb(153, 0, 0);">,</span> <span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> take<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> var query <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Skip</span></b><span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Take</span></b><span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">ToList</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /><br /><b><span style="color: rgb(0, 0, 255);">private</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> IQueryable<span style="color: rgb(153, 0, 0);"><</span>Book<span style="color: rgb(153, 0, 0);">></span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>DataClasses1DataContext ctx<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> var query <span style="color: rgb(153, 0, 0);">=</span> <span style="color: rgb(153, 0, 0);">(</span>from book in ctx<span style="color: rgb(153, 0, 0);">.</span>Books<br /> select book<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query<span style="color: rgb(153, 0, 0);">;</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /></tt></pre><br /><br />part of <code>*.aspx</code> file that holds RadGrid markup:<br /><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);"><form</span></b> <span style="color: rgb(0, 153, 0);">id</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">form1</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">runat</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">server</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><br /><b><span style="color: rgb(0, 0, 255);"><div></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:RadScriptManager</span> <span style="color: rgb(0, 153, 0);">ID</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">RadScriptManager1</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">runat</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">server</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:RadGrid</span> <span style="color: rgb(0, 153, 0);">ID</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">RadGrid1</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">runat</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">server</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">OnNeedDataSource</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">RadGrid1_NeedDataSource</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowCustomPaging</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowPaging</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><PagerStyle</span></b> <span style="color: rgb(0, 153, 0);">AlwaysVisible</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">Mode</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">NextPrevAndNumeric</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></telerik</span></b><span style="color: rgb(0, 153, 0);">:RadGrid></span><br /><span style="color: rgb(0, 153, 0);"></div></span><br /><span style="color: rgb(0, 153, 0);"></form></span><br /></tt></pre><br /><br />and the resulting grid:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__b4fPTzdGYs/SxFF0ZjKocI/AAAAAAAAAgE/AgKKmvY7uIk/s1600/radgrid-1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 128px;" src="http://3.bp.blogspot.com/__b4fPTzdGYs/SxFF0ZjKocI/AAAAAAAAAgE/AgKKmvY7uIk/s400/radgrid-1.png" alt="" id="BLOGGER_PHOTO_ID_5409181393962574274" border="0" /></a><br /><br />Notice how we implemented pagind with just few lines of code.<br /><br />By default RadGrid created columns and bound them to properties of our Book class (AutoGenerateColumns="True"). But we need to display Pubilsher's Name instead of <code>PublisherID</code>.<br /><br />To do this we need to change <code>AutoGenerateColumns</code> to <code>False</code> and write RadGrid markup by hand.<br /><br /><b></b>Here is the markup:<br /><br /><pre><tt><b><span style="color: rgb(0, 0, 255);"><Columns></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher.Name</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher.Name</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /><b><span style="color: rgb(0, 0, 255);"></Columns><br /><br /></span></b></tt></pre>and code behind:<br /><br /><pre><tt><b><span style="color: rgb(0, 0, 255);">public</span></b> partial <b><span style="color: rgb(0, 0, 255);">class</span></b> Book<br /><span style="color: rgb(255, 0, 0);">{</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> <span style="color: rgb(0, 153, 0);">int</span> <b><span style="color: rgb(0, 0, 0);">GetBooksCount</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Count</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> List<span style="color: rgb(153, 0, 0);"><</span>Book<span style="color: rgb(153, 0, 0);">></span> <b><span style="color: rgb(0, 0, 0);">GetBooks</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> skip<span style="color: rgb(153, 0, 0);">,</span> <span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> take<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /></tt><tt><tt><br /> </tt></tt><tt><tt><span><tt><tt><span><tt><tt><span><tt><tt><span style="color: rgb(153, 0, 0);">// </span></tt></tt></span></tt></tt></span></tt></tt></span></tt></tt><tt><tt><span><tt><tt><span style="color: rgb(153, 0, 0);">Preload Book's Publisher field</span></tt></tt></span></tt></tt><tt><tt><br /></tt></tt><tt><tt> var loadOptions = new DataLoadOptions</tt></tt><tt><tt><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span></tt></tt><tt><tt><tt><tt><span style="color: rgb(153, 0, 0);">;<br /> </span></tt></tt></tt></tt><tt><tt> loadOptions.LoadWith</tt></tt><tt><tt><span style="color: rgb(153, 0, 0);"><</span></tt></tt><tt><tt>Book></tt></tt><tt><tt><tt><tt><span style="color: rgb(153, 0, 0);">(</span></tt></tt></tt></tt><tt><tt>b => b.Publisher</tt></tt><tt><tt><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;<br /> </span></tt></tt><tt><tt> ctx.LoadOptions = loadOptions</tt></tt><tt><tt><tt><tt><span style="color: rgb(153, 0, 0);">;</span></tt></tt></tt></tt><tt><tt><br /><br /></tt></tt><tt> var query <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Skip</span></b><span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Take</span></b><span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query.ToList()<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">private</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> IQueryable<span style="color: rgb(153, 0, 0);"><</span>Book<span style="color: rgb(153, 0, 0);">></span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>DataClasses1DataContext ctx<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> var query <span style="color: rgb(153, 0, 0);">=</span> <span style="color: rgb(153, 0, 0);">(</span>from book in ctx<span style="color: rgb(153, 0, 0);">.</span>Books<br /> select book<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /></tt></pre><br />Here's what we got at this point:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__b4fPTzdGYs/SxJh0tW3aiI/AAAAAAAAAgU/AKkhvcs-6TA/s1600/radgrid-2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 135px;" src="http://2.bp.blogspot.com/__b4fPTzdGYs/SxJh0tW3aiI/AAAAAAAAAgU/AKkhvcs-6TA/s400/radgrid-2.png" alt="" id="BLOGGER_PHOTO_ID_5409493660581980706" border="0" /></a><br /><br />Now we will add support for filter and sorting capabilities. To do this we should set RadGrid's <code>AllowFilteringByColumn</code> and <code>AllowSorting</code> to <code>True</code> and change our DAL methods to support query filtering and ordering.<br /><br />RadGrid gives us very good support here, because it can generate linq string that contains part of linq query's <code>where</code> expression. To get this expression <a href="http://anjlab.com/">we</a> wrote simple <code>RadGridHelper</code> class (see full source code in attachments below).<br /><br />To use RadGrid expressions we need <a href="http://code.msdn.microsoft.com/csharpsamples">DynamicQueriable</a> (<code>CSharpSamples.zip\LinqSamples\DynamicQuery\DynamicQuery\Dynamic.cs</code>) to mix dynamic linq expressions with static queries in DAL.<br /><br />Finishing stroke is to make filtering case insensitive, in order to do this we should set <code>CaseSensitive="False"</code> in RadGrid's <code>GroupingSettings</code>.<br /><br />Below are the resulting code linstings:<br /><br /><b>Resulting RadGrid markup:</b><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:RadGrid</span> <span style="color: rgb(0, 153, 0);">ID</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">RadGrid1</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">runat</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">server</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">OnNeedDataSource</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">RadGrid1_NeedDataSource</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowCustomPaging</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowPaging</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowFilteringByColumn</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AllowSorting</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">AutoGenerateColumns</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">False</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">GridLines</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">None</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><HeaderContextMenu</span></b> <span style="color: rgb(0, 153, 0);">EnableTheming</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><CollapseAnimation</span></b> <span style="color: rgb(0, 153, 0);">Type</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">OutQuint</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">Duration</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">200</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><b><span style="color: rgb(0, 0, 255);"></CollapseAnimation></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></HeaderContextMenu></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><PagerStyle</span></b> <span style="color: rgb(0, 153, 0);">AlwaysVisible</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">Mode</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">NextPrevAndNumeric</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><GroupingSettings</span></b> <span style="color: rgb(0, 153, 0);">CaseSensitive</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">False</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><MasterTableView></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><ExpandCollapseColumn></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><HeaderStyle</span></b> <span style="color: rgb(0, 153, 0);">Width</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">20px</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><b><span style="color: rgb(0, 0, 255);"></HeaderStyle></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></ExpandCollapseColumn></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><Columns></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">SortExpression</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Title</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">SortExpression</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Author</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><telerik</span></b><span style="color: rgb(0, 153, 0);">:GridBoundColumn</span> <span style="color: rgb(0, 153, 0);">UniqueName</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">PublisherName</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">HeaderText</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher</span><span style="color: rgb(255, 0, 0);">"</span><br /> <span style="color: rgb(0, 153, 0);">DataField</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher.Name</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">DataType</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">System.String</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">SortExpression</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">Publisher.Name</span><span style="color: rgb(255, 0, 0);">"</span> <b><span style="color: rgb(0, 0, 255);">/></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></Columns></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></MasterTableView></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><FilterMenu</span></b> <span style="color: rgb(0, 153, 0);">EnableTheming</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">True</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><br /> <b><span style="color: rgb(0, 0, 255);"><CollapseAnimation</span></b> <span style="color: rgb(0, 153, 0);">Type</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">OutQuint</span><span style="color: rgb(255, 0, 0);">"</span> <span style="color: rgb(0, 153, 0);">Duration</span><span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(255, 0, 0);">"</span><span style="color: rgb(255, 0, 0);">200</span><span style="color: rgb(255, 0, 0);">"</span><b><span style="color: rgb(0, 0, 255);">></span></b><b><span style="color: rgb(0, 0, 255);"></CollapseAnimation></span></b><br /> <b><span style="color: rgb(0, 0, 255);"></FilterMenu></span></b><br /><b><span style="color: rgb(0, 0, 255);"></telerik</span></b><span style="color: rgb(0, 153, 0);">:RadGrid></span><br /></tt></pre><br /><br /><b>Resulting code behind</b>:<br /><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);">protected</span></b> <span style="color: rgb(0, 153, 0);">void</span> <b><span style="color: rgb(0, 0, 0);">Page_Load</span></b><span style="color: rgb(153, 0, 0);">(</span>object sender<span style="color: rgb(153, 0, 0);">,</span> EventArgs e<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>IsPostBack<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">DataBind</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /><br /><b><span style="color: rgb(0, 0, 255);">protected</span></b> <span style="color: rgb(0, 153, 0);">void</span> <b><span style="color: rgb(0, 0, 0);">RadGrid1_NeedDataSource</span></b><span style="color: rgb(153, 0, 0);">(</span>object source<span style="color: rgb(153, 0, 0);">,</span> GridNeedDataSourceEventArgs e<span style="color: rgb(153, 0, 0);">)</span><br /><span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>e<span style="color: rgb(153, 0, 0);">.</span>IsFromDetailTable<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> string where <span style="color: rgb(153, 0, 0);">=</span> RadGridHelper<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetFilterExpression</span></b><span style="color: rgb(153, 0, 0);">(</span>RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">,</span> </tt><tt><b><span><tt><b><span style="color: rgb(0, 0, 255);">null</span></b></tt></span></b></tt><tt><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> string orderBy <span style="color: rgb(153, 0, 0);">=</span> RadGridHelper<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetOrderBy</span></b><span style="color: rgb(153, 0, 0);">(</span>RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>e<span style="color: rgb(153, 0, 0);">.</span>RebindReason <span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(153, 0, 0);">=</span> GridRebindReason<span style="color: rgb(153, 0, 0);">.</span>InitialLoad<br /> <span style="color: rgb(153, 0, 0);">|</span><span style="color: rgb(153, 0, 0);">|</span> e<span style="color: rgb(153, 0, 0);">.</span>RebindReason <span style="color: rgb(153, 0, 0);">=</span><span style="color: rgb(153, 0, 0);">=</span> GridRebindReason<span style="color: rgb(153, 0, 0);">.</span>ExplicitRebind<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>VirtualItemCount <span style="color: rgb(153, 0, 0);">=</span> Book<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetBooksCount</span></b><span style="color: rgb(153, 0, 0);">(</span>where<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <span style="color: rgb(0, 153, 0);">int</span> skip <span style="color: rgb(153, 0, 0);">=</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>CurrentPageIndex <span style="color: rgb(153, 0, 0);">*</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>PageSize<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(0, 153, 0);">int</span> take <span style="color: rgb(153, 0, 0);">=</span> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>MasterTableView<span style="color: rgb(153, 0, 0);">.</span>PageSize<span style="color: rgb(153, 0, 0);">;</span><br /><br /> RadGrid1<span style="color: rgb(153, 0, 0);">.</span>DataSource <span style="color: rgb(153, 0, 0);">=</span> Book<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">GetBooks</span></b><span style="color: rgb(153, 0, 0);">(</span>where<span style="color: rgb(153, 0, 0);">,</span> orderBy<span style="color: rgb(153, 0, 0);">,</span> skip<span style="color: rgb(153, 0, 0);">,</span> take<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /></tt></pre><br /><br /><b>Final Book class:</b><br /><br /><!-- Generator: GNU source-highlight 2.1.2 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><span style="color: rgb(0, 0, 255);">public</span></b> partial <b><span style="color: rgb(0, 0, 255);">class</span></b> Book<br /><span style="color: rgb(255, 0, 0);">{</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> <span style="color: rgb(0, 153, 0);">int</span> <b><span style="color: rgb(0, 0, 0);">GetBooksCount</span></b><span style="color: rgb(153, 0, 0);">(</span>string where<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">,</span> where<span style="color: rgb(153, 0, 0);">,</span> null<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Count</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">public</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> List<span style="color: rgb(153, 0, 0);"><</span>Book<span style="color: rgb(153, 0, 0);">></span> <b><span style="color: rgb(0, 0, 0);">GetBooks</span></b><span style="color: rgb(153, 0, 0);">(</span>string where<span style="color: rgb(153, 0, 0);">,</span> string orderBy<span style="color: rgb(153, 0, 0);">,</span> <span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> skip<span style="color: rgb(153, 0, 0);">,</span> <span style="color: rgb(0, 153, 0);">int</span><span style="color: rgb(153, 0, 0);">?</span> take<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> <b><span style="color: rgb(0, 0, 255);">using</span></b> <span style="color: rgb(153, 0, 0);">(</span>var ctx <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 255);">new</span></b> <b><span style="color: rgb(0, 0, 0);">DataClasses1DataContext</span></b><span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> var query <span style="color: rgb(153, 0, 0);">=</span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>ctx<span style="color: rgb(153, 0, 0);">,</span> where<span style="color: rgb(153, 0, 0);">,</span> orderBy<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Skip</span></b><span style="color: rgb(153, 0, 0);">(</span>skip<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>HasValue<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Take</span></b><span style="color: rgb(153, 0, 0);">(</span>take<span style="color: rgb(153, 0, 0);">.</span>Value<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query.ToList()<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">private</span></b> <b><span style="color: rgb(0, 0, 255);">static</span></b> IQueryable<span style="color: rgb(153, 0, 0);"><</span>BookWrapper<span style="color: rgb(153, 0, 0);">></span> <b><span style="color: rgb(0, 0, 0);">GetBooksQuery</span></b><span style="color: rgb(153, 0, 0);">(</span>DataClasses1DataContext ctx<span style="color: rgb(153, 0, 0);">,</span> string where<span style="color: rgb(153, 0, 0);">,</span> string orderBy<span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> var query <span style="color: rgb(153, 0, 0);">=</span> <span style="color: rgb(153, 0, 0);">(</span>from book in ctx<span style="color: rgb(153, 0, 0);">.</span>Books<br /> select book<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>string<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">IsNullOrEmpty</span></b><span style="color: rgb(153, 0, 0);">(</span>where<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">Where</span></b><span style="color: rgb(153, 0, 0);">(</span>where<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /> <b><span style="color: rgb(0, 0, 255);">if</span></b> <span style="color: rgb(153, 0, 0);">(</span><span style="color: rgb(153, 0, 0);">!</span>string<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">IsNullOrEmpty</span></b><span style="color: rgb(153, 0, 0);">(</span>orderBy<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">)</span><br /> <span style="color: rgb(255, 0, 0);">{</span><br /> query <span style="color: rgb(153, 0, 0);">=</span> query<span style="color: rgb(153, 0, 0);">.</span><b><span style="color: rgb(0, 0, 0);">OrderBy</span></b><span style="color: rgb(153, 0, 0);">(</span>orderBy<span style="color: rgb(153, 0, 0);">)</span><span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><br /> <b><span style="color: rgb(0, 0, 255);">return</span></b> query<span style="color: rgb(153, 0, 0);">;</span><br /> <span style="color: rgb(255, 0, 0);">}</span><br /><span style="color: rgb(255, 0, 0);">}</span><br /></tt></pre><br /><br /><b>Resulting RadGrid in action:</b><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__b4fPTzdGYs/SxJrxGPLPlI/AAAAAAAAAgc/br4F3lvSdq8/s1600/radgrid-3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 108px;" src="http://4.bp.blogspot.com/__b4fPTzdGYs/SxJrxGPLPlI/AAAAAAAAAgc/br4F3lvSdq8/s400/radgrid-3.png" alt="" id="BLOGGER_PHOTO_ID_5409504593657413202" border="0" /></a><br /><br /><h3>Attachments</h3><br /><a href="http://dmitry.gusev.googlepages.com/radgridsample-src.zip">radgridsample-src.zip</a> Full project sources + DB (142 KB)<br /><br /><tt><tt></tt></tt>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com5tag:blogger.com,1999:blog-25040534.post-12518682488947664652009-10-29T11:43:00.000+03:002009-10-29T12:34:28.942+03:00Developing Java applications with GAE SDK 1.2.6 and javaagent turned offSince version 1.2.6 Google AppEngine SDK in development mode requires to run JVM with javaagent.<br /><br />If you don't do this you'll get the following exception:<br /><pre><br /><small><br />java.lang.RuntimeException: Unable to locate the App Engine agent.<br />Please use dev_appserver, KickStart, or set the jvm flag:<br /> <font color="red"><b>"-javaagent:<sdk_root>/lib/agent/appengine-agent.jar"</b></font><br /> at com.google.appengine.tools.development.DevAppServerFactory.testAgentIsInstalled(102)<br /> at com.google.appengine.tools.development.DevAppServerFactory.createDevAppServer(77)<br /> at com.google.appengine.tools.development.DevAppServerFactory.createDevAppServer(38)<br /> at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(153)<br /> at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)<br /> at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:113)<br /> at com.google.appengine.tools.development.DevAppServerMain.main(89)<br />Caused by: java.lang.NoClassDefFoundError: com/google/appengine/tools/development/agent/AppEngineDevAgent<br /> at com.google.appengine.tools.development.DevAppServerFactory.testAgentIsInstalled(98)<br /> ... 6 more<br /></small><br /></pre><br /><br />But if you do you may get very strange behaviour of your app. Here's a few of mines I get developing with Tapestry 5.2.0.0-SNAPSHOT:<br /><pre><br /><small><br />java.lang.ClassFormatError: Invalid length 65050 in LocalVariableTable <br /> in class file org/apache/tapestry5/corelib/components/Form<br /> at java.lang.ClassLoader.defineClass1(Native Method)<br /> at java.lang.ClassLoader.defineClass(Unknown Source)<br /> at java.lang.ClassLoader.defineClass(Unknown Source)<br /> at javassist.Loader.findClass(Loader.java:379)<br /> at org.apache.tapestry5.internal.services.ComponentInstantiatorSourceImpl$PackageAwareLoader.findClass(94)<br />...<br /></small><br /></pre><br /><br />I've found a <a href="http://www.nabble.com/-t5--upgrade-to-java-6-and-javassist-td25295834.html">discussion</a> where similiar problem was caused by multiple versions of javassist on CLASSPATH. I tried to find them, but I had only one of it.<br /><br />The other exception is due to previous.<br /><br /><pre><br /><small><br />org.apache.tapestry5.ioc.internal.util.TapestryException: <br /> Failure creating embedded component 'sendInvite' of dmitrygusev.ping.pages.Index: <br /> java.lang.ClassNotFoundException: caught an exception while obtaining a class<br /> file for org.apache.tapestry5.corelib.components.Form" <br /> [at context:Index.tml, line 23]<br /> at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl.createEmbeddedAssembler(316)<br /> at org.apache.tapestry5.internal.pageload.PageLoaderImpl.startComponent(740)<br /><br />...<br /><br />Caused by: java.lang.RuntimeException: Class org.apache.tapestry5.corelib.components.Form contains field(s) <br /> (_$bindingSource, _$environment, _$onActionInfo, _$resources, _$type, _$type_0, _$type_1) <br /> that are not private. You should change these fields to private, and add accessor methods if needed. <br /> at org.apache.tapestry5.internal.services.InternalClassTransformationImpl.verifyFields(293)<br /> at org.apache.tapestry5.internal.services.InternalClassTransformationImpl.preloadMemberNames(255)<br /> at org.apache.tapestry5.internal.services.InternalClassTransformationImpl.<init>(151)<br /> at org.apache.tapestry5.internal.services.ComponentClassTransformerImpl.transformComponentClass(163)<br /> at $ComponentClassTransformer_1249f7f3976.transformComponentClass(...)<br /> at org.apache.tapestry5.internal.services.ComponentInstantiatorSourceImpl.onLoad(205)<br /> at javassist.Loader.findClass(Loader.java:340)<br /> ... 95 more<br /></small><br /></pre><br /><br />This all very strange, because when deployed to Google AppEgine there is no such errors, and this is very similiar to problem with a Security Manager I wrote about in a <a href="http://dmitrygusev.blogspot.com/2009/08/turn-java-security-manager-off-in.html">previous post</a>.<br /><br />To fix it I had to <b>not</b> specify javaagent on JVM start, but to avoid that "Unable to locate the App Engine agent" exception, I created the following class:<br /><br /><!-- Generator: GNU source-highlight 2.1.2<br />by Lorenzo Bettini<br />http://www.lorenzobettini.it<br />http://www.gnu.org/software/src-highlite --><br /><pre><tt><b><font color="#000080">package</font></b> com<font color="#990000">.</font>google<font color="#990000">.</font>appengine<font color="#990000">.</font>tools<font color="#990000">.</font>development<font color="#990000">.</font>agent<font color="#990000">;</font><br /><br /><b><font color="#0000FF">public</font></b> <b><font color="#0000FF">class</font></b> AppEngineDevAgent <font color="#FF0000">{</font><br /><br /> <b><font color="#0000FF">public</font></b> <b><font color="#0000FF">static</font></b> Object <b><font color="#000000">getAgent</font></b><font color="#990000">(</font><font color="#990000">)</font><br /> <font color="#FF0000">{</font><br /> <b><font color="#0000FF">return</font></b> <b><font color="#0000FF">null</font></b><font color="#990000">;</font><br /> <font color="#FF0000">}</font><br /><br /><font color="#FF0000">}</font><br /></tt></pre><br /><br />and putted it to my project:<br /><br /><img style="display:block; margin:0px auto 10px; text-align:center;width: 395px; height: 218px;" src="http://1.bp.blogspot.com/__b4fPTzdGYs/SulbGt_XZQI/AAAAAAAAAfs/qrv6oFRN0WM/s1600/package-explorer.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5397945799362962690" /><br /><br />Now I can run my project without javaagent. Please note, that you may still need to apply <a href="http://dmitrygusev.blogspot.com/2009/08/turn-java-security-manager-off-in.html">patch to Security Manager</a> (its compatible with 1.2.2-6 GAE SDKs) to avoid other potential issues developing with GAE SDK.<br /><br />Its also okay to deploy your app with this class to GAE, since it won't conflict with GAE environment.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com6tag:blogger.com,1999:blog-25040534.post-79930965394256805042009-08-25T15:18:00.000+04:002009-08-25T15:59:46.741+04:00Turn Java Security Manager Off In Google App Engine SDKFor some reasons you might want to turn Java Security Management off for Google Appengine Development Environment.<br /><br />I need this for properly handling of Tapestry5 error page. With Java SecurityManager enabled it produced the following errors:<br /><br /><pre><br />Could not initialize class org.apache.tapestry5.corelib.components.Loop<br /><br />java.lang.NoClassDefFoundError: Could not initialize class<br /> org.apache.tapestry5.corelib.components.Loop<br /><br />java.lang.NoClassDefFoundError:<br /> org/apache/tapestry5/corelib/components/Loop$1<br /></pre><br /><br />To turn it off, you should replace two classes in SDK, that are responsible to installing Security Manager. <br /><br /><ol><li>Close all Eclipse instances</li><br /><li>Locate appengine-tools-api.jar: <code>%YOUR_ECLIPSE_FOLDER%\plugins\com.google.appengine.eclipse.sdkbundle_1.2.2.v200907291526\appengine-java-sdk-1.2.2\lib\appengine-tools-api.jar</code></li><br /><li>Replace original classes <code>com\google\appengine\tools\development\DevAppServerFactory$CustomSecurityManager.class</code> and <code>com\google\apphosting\utils\security\SecurityManagerInstaller.class</code> with <a href="http://dmitry.gusev.googlepages.com/google-appengine-plugin-1.2.2-patch.zip">ones provided below</a> (you may want to do a backup first)</li><br /></ol><br /><br />Thats all. Now after starting App Engine project in eclipse you should see the following output in console:<br /><br /><pre><br />Skip install SecurityManager<br />Create dummy CustomSecurityManager<br />The server is running at http://localhost:8080/<br /></pre><br /><br />Just keep in mind that original App Engine cloud still have those Security Managers installed.<br /><br />FYI here is the sources of those classes:<br /><br /><b>DevAppServerFactory.java</b><br /><pre style='color:#000000;background:#ffffff;'><span style='color:#7f0055; font-weight:bold; '>package</span><span style='color:#7f0055; '> com</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>google</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>appengine</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>tools</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>development</span><span style='color:#7f0055; '>;</span><br /><br /><span style='color:#7f0055; font-weight:bold; '>import</span><span style='color:#7f0055; '> java</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>security</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>Permission</span><span style='color:#7f0055; '>;</span><br /><br /><span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>class</span> DevAppServerFactory {<br /><br /> <span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>static</span> <span style='color:#7f0055; font-weight:bold; '>class</span> CustomSecurityManager <span style='color:#7f0055; font-weight:bold; '>extends</span> <span style='color:#7f0055; font-weight:bold; '>SecurityManager</span> {<br /><br /> @Override<br /> <span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>void</span> checkPermission(<span style='color:#7f0055; font-weight:bold; '>Permission</span> perm) {<br /> <span style='color:#3f7f59; '>// Do nothing</span><br /> }<br /> <br /> <span style='color:#7f0055; font-weight:bold; '>public</span> CustomSecurityManager(DevAppServer devAppServer) {<br /> <span style='color:#7f0055; font-weight:bold; '>System</span>.out.println(<span style='color:#2a00ff; '>"Create dummy CustomSecurityManager"</span>);<br /> }<br /> <br /> }<br /> <br />}<br /></pre><br /><br /><b>SecurityManagerInstaller.java</b><br /><pre style='color:#000000;background:#ffffff;'><span style='color:#7f0055; font-weight:bold; '>package</span><span style='color:#7f0055; '> com</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>google</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>apphosting</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>utils</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>security</span><span style='color:#7f0055; '>;</span><br /><br /><span style='color:#7f0055; font-weight:bold; '>import</span><span style='color:#7f0055; '> java</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>net</span><span style='color:#7f0055; '>.</span><span style='color:#7f0055; '>URL</span><span style='color:#7f0055; '>;</span><br /><br /><span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>class</span> SecurityManagerInstaller {<br /><br /> <span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>static</span> <span style='color:#7f0055; font-weight:bold; '>void</span> install(<span style='color:#7f0055; font-weight:bold; '>URL</span>... urls) {<br /> <span style='color:#7f0055; font-weight:bold; '>System</span>.out.println(<span style='color:#2a00ff; '>"Skip install SecurityManager"</span>);<br /> }<br /> <br />}<br /></pre><br /><br />Download Google App Engine/Java 1.2.2 Security Manager patch <a href="http://dmitry.gusev.googlepages.com/google-appengine-plugin-1.2.2-patch.zip">here</a> (3 KB)Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com3tag:blogger.com,1999:blog-25040534.post-39938199124159578572009-08-07T14:46:00.000+04:002009-08-07T14:57:20.613+04:00.Net Collections Lookup Performance<img style="display:block; margin:0px auto 10px; text-align:center;width: 645px; height: 101px;" src="http://1.bp.blogspot.com/__b4fPTzdGYs/SnwGGNHe0XI/AAAAAAAAAd8/eBhBg8aoGEM/s1600/test-results.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5367171559588811122" /><br /><br /><pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>using</span> System<span style='color:#800080; '>;</span><br /><span style='color:#800000; font-weight:bold; '>using</span> System<span style='color:#808030; '>.</span>Collections<span style='color:#808030; '>.</span>Generic<span style='color:#800080; '>;</span><br /><span style='color:#800000; font-weight:bold; '>using</span> System<span style='color:#808030; '>.</span>Linq<span style='color:#800080; '>;</span><br /><span style='color:#800000; font-weight:bold; '>using</span> NUnit<span style='color:#808030; '>.</span>Framework<span style='color:#800080; '>;</span><br /><br /><span style='color:#800000; font-weight:bold; '>namespace</span> TechNoir<span style='color:#808030; '>.</span>NorCal<span style='color:#808030; '>.</span>BL<span style='color:#808030; '>.</span>Tests<br /><span style='color:#800080; '>{</span><br /> <span style='color:#808030; '>[</span>TestFixture<span style='color:#808030; '>]</span><br /> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#800000; font-weight:bold; '>class</span> PerformanceTests<br /> <span style='color:#800080; '>{</span><br /> <span style='color:#808030; '>[</span>Test<span style='color:#808030; '>]</span><br /> <span style='color:#800000; font-weight:bold; '>public</span> <span style='color:#800000; font-weight:bold; '>void</span> CompareLookupSpeed<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> <span style='color:#800000; font-weight:bold; '>bool</span> warmUp <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#800080; '>;</span><br /><br /> <span style='color:#800000; font-weight:bold; '>for</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> j <span style='color:#808030; '>=</span> <span style='color:#008c00; '>1</span><span style='color:#800080; '>;</span> j <span style='color:#808030; '><</span><span style='color:#808030; '>=</span> <span style='color:#008c00; '>10</span><span style='color:#800080; '>;</span> j<span style='color:#808030; '>+</span><span style='color:#808030; '>+</span><span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> <span style='color:#800000; font-weight:bold; '>int</span> n <span style='color:#808030; '>=</span> j <span style='color:#808030; '>*</span> <span style='color:#008c00; '>1000</span><span style='color:#800080; '>;</span><br /><br /> Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>\nTest {0}; n = {1}\n</span><span style='color:#800000; '>"</span><span style='color:#808030; '>,</span> j<span style='color:#808030; '>,</span> n<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> list<span style='color:#800080; '>;</span><br /> Dictionary<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>object</span><span style='color:#808030; '>></span> dictionary<span style='color:#800080; '>;</span><br /> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> sortedList<span style='color:#800080; '>;</span><br /> IQueryable<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> queryable<span style='color:#800080; '>;</span><br /><br /> PrepareTestData<span style='color:#808030; '>(</span>n<span style='color:#808030; '>,</span> <br /> <span style='color:#800000; font-weight:bold; '>out</span> list<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>out</span> dictionary<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>out</span> sortedList<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>out</span> queryable<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /><br /> DateTime start <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /> <span style='color:#800000; font-weight:bold; '>foreach</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> item <span style='color:#800000; font-weight:bold; '>in</span> list<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> Assert<span style='color:#808030; '>.</span>That<span style='color:#808030; '>(</span>dictionary<span style='color:#808030; '>.</span>ContainsKey<span style='color:#808030; '>(</span>item<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /> DateTime end <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /><br /> Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>IDictionary.ContainsKey : </span><span style='color:#800000; '>"</span> <br /> <span style='color:#808030; '>+</span> <span style='color:#808030; '>(</span>end <span style='color:#808030; '>-</span> start<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>TotalMilliseconds<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /><br /> start <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /> <span style='color:#800000; font-weight:bold; '>foreach</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> item <span style='color:#800000; font-weight:bold; '>in</span> list<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> Assert<span style='color:#808030; '>.</span>That<span style='color:#808030; '>(</span>sortedList<span style='color:#808030; '>.</span>BinarySearch<span style='color:#808030; '>(</span>item<span style='color:#808030; '>)</span> <span style='color:#808030; '>!</span><span style='color:#808030; '>=</span> <span style='color:#808030; '>-</span><span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /> end <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /><br /> Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>List.BinarySearch : </span><span style='color:#800000; '>"</span> <br /> <span style='color:#808030; '>+</span> <span style='color:#808030; '>(</span>end <span style='color:#808030; '>-</span> start<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>TotalMilliseconds<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /><br /> start <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /> <span style='color:#800000; font-weight:bold; '>foreach</span> <span style='color:#808030; '>(</span>var item <span style='color:#800000; font-weight:bold; '>in</span> list<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> Assert<span style='color:#808030; '>.</span>That<span style='color:#808030; '>(</span>list<span style='color:#808030; '>.</span>Contains<span style='color:#808030; '>(</span>item<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /> end <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /><br /> Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>List.Contains : </span><span style='color:#800000; '>"</span> <br /> <span style='color:#808030; '>+</span> <span style='color:#808030; '>(</span>end <span style='color:#808030; '>-</span> start<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>TotalMilliseconds<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /><br /> start <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /> <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>j <span style='color:#808030; '><</span><span style='color:#808030; '>=</span> <span style='color:#008c00; '>3</span><span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> <span style='color:#800000; font-weight:bold; '>foreach</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> item <span style='color:#800000; font-weight:bold; '>in</span> list<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> <span style='color:#800000; font-weight:bold; '>int</span> localItem <span style='color:#808030; '>=</span> item<span style='color:#800080; '>;</span><br /> Assert<span style='color:#808030; '>.</span>That<span style='color:#808030; '>(</span>queryable<span style='color:#808030; '>.</span>Any<span style='color:#808030; '>(</span>i <span style='color:#808030; '>=</span><span style='color:#808030; '>></span> i <span style='color:#808030; '>=</span><span style='color:#808030; '>=</span> localItem<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /> <span style='color:#800080; '>}</span><br /> end <span style='color:#808030; '>=</span> DateTime<span style='color:#808030; '>.</span>Now<span style='color:#800080; '>;</span><br /><br /> Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>IQueryable.Any : </span><span style='color:#800000; '>"</span> <br /> <span style='color:#808030; '>+</span> <span style='color:#808030; '>(</span>end <span style='color:#808030; '>-</span> start<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>TotalMilliseconds<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /><br /> <span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>warmUp<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> warmUp <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>false</span><span style='color:#800080; '>;</span><br /> j<span style='color:#808030; '>-</span><span style='color:#808030; '>-</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /><br /> <span style='color:#800080; '>}</span><br /> <span style='color:#800080; '>}</span><br /><br /> <span style='color:#800000; font-weight:bold; '>private</span> <span style='color:#800000; font-weight:bold; '>static</span> <span style='color:#800000; font-weight:bold; '>void</span> PrepareTestData<span style='color:#808030; '>(</span><br /> <span style='color:#800000; font-weight:bold; '>int</span> n<span style='color:#808030; '>,</span> <br /> <span style='color:#800000; font-weight:bold; '>out</span> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> list<span style='color:#808030; '>,</span> <br /> <span style='color:#800000; font-weight:bold; '>out</span> Dictionary<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>object</span><span style='color:#808030; '>></span> dictionary<span style='color:#808030; '>,</span> <br /> <span style='color:#800000; font-weight:bold; '>out</span> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> sortedList<span style='color:#808030; '>,</span> <br /> <span style='color:#800000; font-weight:bold; '>out</span> IQueryable<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span> queryable<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> list <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> var rand <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> Random<span style='color:#808030; '>(</span><span style='color:#008c00; '>42</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> <span style='color:#800000; font-weight:bold; '>for</span> <span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span> i <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span> i <span style='color:#808030; '><</span> n<span style='color:#800080; '>;</span> i<span style='color:#808030; '>+</span><span style='color:#808030; '>+</span><span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> <span style='color:#800000; font-weight:bold; '>int</span> x<span style='color:#800080; '>;</span><br /> <span style='color:#800000; font-weight:bold; '>do</span><br /> <span style='color:#800080; '>{</span><br /> x <span style='color:#808030; '>=</span> rand<span style='color:#808030; '>.</span>Next<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>.</span>MaxValue<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span> <span style='color:#800000; font-weight:bold; '>while</span> <span style='color:#808030; '>(</span>list<span style='color:#808030; '>.</span>Contains<span style='color:#808030; '>(</span>x<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> list<span style='color:#808030; '>.</span>Add<span style='color:#808030; '>(</span>x<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /><br /> queryable <span style='color:#808030; '>=</span> list<span style='color:#808030; '>.</span>AsQueryable<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> dictionary <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> Dictionary<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>object</span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> <span style='color:#800000; font-weight:bold; '>foreach</span> <span style='color:#808030; '>(</span>var item <span style='color:#800000; font-weight:bold; '>in</span> list<span style='color:#808030; '>)</span><br /> <span style='color:#800080; '>{</span><br /> dictionary<span style='color:#808030; '>.</span>Add<span style='color:#808030; '>(</span>item<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>null</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /><br /><br /> sortedList <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> List<span style='color:#808030; '><</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> sortedList<span style='color:#808030; '>.</span>AddRange<span style='color:#808030; '>(</span>list<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /><br /> sortedList<span style='color:#808030; '>.</span>Sort<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span><br /> <span style='color:#800080; '>}</span><br /> <span style='color:#800080; '>}</span><br /><span style='color:#800080; '>}</span><br /></pre>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0tag:blogger.com,1999:blog-25040534.post-73226811819463627762009-08-03T23:21:00.000+04:002009-08-03T23:27:28.992+04:0018 июля 2008<embed name="wlplayer" src="http://www.wedlife.ru/wlplayer.swf" flashvars="videoid=4061" width="512" height="384" bgcolor="#000000" allowScriptAccess="always" allowFullScreen="true"></embed>Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com9tag:blogger.com,1999:blog-25040534.post-81192455896892295292009-07-28T13:54:00.000+04:002009-07-28T14:06:55.726+04:00Fix msysgit installYou may get the following error during commit in git:<br /><br /><code><br />0 [main] us 0 init_cheap: VirtualAlloc pointer is null, Win32 error 487 AllocationBase 0x0, BaseAddress 0x30540000, RegionSize 0x240000, State 0x10000 C:\dev\bin\git\bin\sh.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 0<br /></code><br /><br />To fix this try the following:<br /><br /><ol><br /><li>Download <a href="http://repo.or.cz/w/msysgit.git?a=blob_plain;f=bin/rebase.exe;hb=full">http://repo.or.cz/w/msysgit.git?a=blob_plain;f=bin/rebase.exe;hb=full</a> (~500 KB)</li><br /><li>Copy this file to the <code>\git\bin</code> folder</li><br /><li>Ensure that no Git related programs are open</li><br /><li>Open a command prompt and navigate to <code>\git\bin</code></li><br /><li>Execute <code>rebase.exe -b 0x40000000 msys-1.0.dll</code></li><br /></ol><br /><br />This should fix up the problem.<br /><br />See <a href="http://code.google.com/p/msysgit/issues/detail?id=180"><strike>Issue 180</strike></a> on msysgit for details.Anonymoushttp://www.blogger.com/profile/11233716929223953153noreply@blogger.com0