tag:blogger.com,1999:blog-78844928252286538212024-03-10T14:54:16.961+05:30CrazyTechThoughtsThis blog is about those crazy (or may be impossible) ideas I get sometimes. I hope some of them are not crazy enough for you to try out.Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.comBlogger24125tag:blogger.com,1999:blog-7884492825228653821.post-74543540806224785162018-06-24T20:20:00.000+05:302018-06-24T20:24:06.597+05:30Build Wine rpm with 32 bit application support<div dir="ltr" style="text-align: left;" trbidi="on">
Wine is a software to allow running Windows applications in Linux, MAC etc. platforms. It is available for installation from package managers like yum (RHEL, CentOS) and apt (Ubuntu). You can find more details on how it works in <a href="https://wiki.winehq.org/Main_Page" target="_blank">Wine wiki</a>.<br />
<br />
But the default Wine package available from package manager does not have support for 32 bit Windows applications. This was the case for me. In Redhat Enterprise Linux 7.3, the wine package did not contain support for 32 bit windows applications. So the only option was to build a separate rpm of wine which will include this support.<br />
<br />
All the steps are executed on a RHEL 7.3 VM (x86_64).<br />
<br />
<b>Step 1</b><br />
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Download and run shell script which will make wine 64
and 32 support for RHEL:</span></div>
<div lang="en-US" style="margin: 0in;">
<a href="https://github.com/zma/usefulscripts/blob/master/script/install-wine-i686-centos7.sh"><span style="font-family: inherit;">https://github.com/zma/usefulscripts/blob/master/script/install-wine-i686-centos7.sh</span></a></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">It
accepts a version no. as CLI parameter e.g. 2.0.3</span></div>
<br />
<br />
<span style="font-family: inherit;">The
script installs wine in </span><span style="font-family: "courier new" , "courier" , monospace;">/usr/local/</span><span style="font-family: inherit;"> directory by default. We can verify the
files that are being copied for wine using "</span><span style="font-family: "courier new" , "courier" , monospace;">cd
/usr/src/wine-2.0.3/wine32/; make -n install</span><span style="font-family: inherit;">" and "</span><span style="font-family: "courier new" , "courier" , monospace;">cd /usr/src/wine-2.0.3/wine64/; make -n
install</span><span style="font-family: inherit;">"</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Step 2</b></span><br />
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Additional steps for adding windows core fonts (optional):</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">yum
install cabextract</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">wget <a href="https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks">https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks</a></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">chmod +x
winetricks</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">sh
winetricks corefonts</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">It
downloads the fonts at </span><span style="font-family: "courier new" , "courier" , monospace;">~/.wine/drive_c/windows/Fonts/</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><b>Step 3</b></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Then do following steps to build rpm:</span></div>
<br />
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">mkdir -p
~/rpmbuild/{RPMS,SRPMS,BUILD,SOURCES,SPECS,tmp}</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cat
<<eof>~/.rpmmacros</eof></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">%_topdir %(echo $HOME)/rpmbuild</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">%_tmppath %{_topdir}/tmp</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">EOF</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cd
~/rpmbuild</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Create
tarball of wine-</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">mkdir -p
wine-2.0.3/usr/</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cd
wine-2.0.3</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cp -r
/usr/local/ usr/</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Then
remove any unused directory that is not created by wine.</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Copy
ms-core font files -</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cp -r
~/.wine/drive_c/windows/Fonts/ usr/local/share/wine/fonts/ms-core</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">cd ..</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">tar -zcvf
wine-2.0.3.tar.gz wine-2.0.3/</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Copy tar
to rpmbuild/SOURCES directory created in above steps.</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Create a
spec (e.g. wine.spec) file in rpmbuild/SPECS directory with following content.</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<script src="https://gist.github.com/sarbajitc/828dfaf4d0515ba4edf1b59ec99ec337.js"></script>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Then
build the rpm using following command -</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: "courier new" , "courier" , monospace;">rpmbuild
-ba rpmbuild/SPECS/wine.spec</span></div>
<div lang="en-US" style="margin: 0in;">
<br /></div>
<div lang="en-US" style="margin: 0in;">
</div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Rpm will
be generated in </span><span style="font-family: "courier new" , "courier" , monospace;">rpmbuild/RPMS/x86_64</span><span style="font-family: inherit;"> directory. This rpm can be installed on other RHEL 7.3 x86_64 machines.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Step 4</b></span><br />
<div lang="en-US" style="font-family: inherit; margin: 0in;">
<span style="font-family: inherit;"><span style="font-family: inherit;">Install x-window system for RHEL in destination
machine:</span></span></div>
<span style="font-family: inherit;">
</span><br />
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><span style="font-family: "courier new" , "courier" , monospace;">yum
install xorg-x11-xauth.x86_64</span></span></div>
<span style="font-family: inherit;"><b><br /></b></span>
<span style="font-family: inherit;">
</span>
<span style="font-family: inherit;"><b>Step 5</b></span><br />
<div lang="en-US" style="font-family: inherit; margin: 0in;">
<span style="font-family: inherit;"><span style="font-family: inherit;">To install the wine rpm do following (it will
automatically resolve all dependency packages):</span></span></div>
<span style="font-family: inherit;">
</span><br />
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;"><span style="font-family: "courier new" , "courier" , monospace;">yum
install wine-2.0.3-1.x86_64.rpm</span></span></div>
<span style="font-family: inherit;"><b><br /></b></span>
<span style="font-family: inherit;">
</span>
<span style="font-family: inherit;"><b>Step 6</b></span><br />
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Start wine for the first time:</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">winecfg</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">(in the
gui select Windows 7 and apply)</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">Then run
windows applications line below -</span></div>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">wine
/path/to/app.exe (for 32 bit binary)</span></div>
<span style="font-family: inherit;">
</span>
<div lang="en-US" style="margin: 0in;">
<span style="font-family: inherit;">wine64
/path/to/app64.exe (for 64 bit binary)</span></div>
<span style="font-family: inherit;"><br /></span></div>
</div>
Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com14tag:blogger.com,1999:blog-7884492825228653821.post-41567669687012265672014-04-11T21:38:00.000+05:302018-06-24T19:59:45.030+05:30Non capturing group in regular expression and it's use<div dir="ltr" style="text-align: left;" trbidi="on">
Recently I have been stuck in a regular expression where I had to use grouping in places, values of which were not required. It won't make sense to explain the problem without the text. So here it is
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">Controller Id Connection Status Connection State Secure Role</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">------------- ----------------- ---------------- ------ ------</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">1 Connected Active No </span><span style="font-family: "courier new" , "courier" , monospace;">Slave</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">25</span><span style="font-family: "courier new" , "courier" , monospace;"> Disconnected Idle No </span><span style="font-family: "courier new" , "courier" , monospace;">Master</span><br />
<br />
<br />
My goal was to get the numeric values at the beginning of the line while still matching the whole line for safety (so that any other numeric values in the output don't match). As you see in the output, each column can contain a value from a list of fixed values. e.g. <span style="font-family: "courier new" , "courier" , monospace;">Connection Status</span> can only contain <span style="font-family: "courier new" , "courier" , monospace;">Connected</span> or <span style="font-family: "courier new" , "courier" , monospace;">Disconnected</span>. That demands the following regular expression -<br />
<br />
<br />
<script src="https://gist.github.com/sarbajitc/0d36e2d1407b2906b8a2d8e92aa67281.js"></script>
<br />
But with the above expression, we are fetching all the columns when all we want is the first column. This is where the non capturing group of regular expression comes into picture. With the help of non capturing groups we can remove them from the matched output while still using the grouping functionality.<br />
<br />
Corrected regular expression is as below -<br />
<br />
<br />
<script src="https://gist.github.com/sarbajitc/180e12632d4836d4b37bb1d224168f99.js"></script>
<br />
By using the "?:" combination just after the parenthesis, we can instruct regular expression engine to not include that group in the matched output. This can be used anywhere we want to use grouping but the value is not needed in the matched output.</div>
Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-22512039739570557422013-02-17T15:45:00.002+05:302018-06-23T09:21:46.447+05:30Simple employee table with OpenStack Horizon DataTable module<div dir="ltr" style="text-align: left;" trbidi="on">
I was working on OpenStack dashboard (aka <a href="http://docs.openstack.org/developer/horizon/">Horizon</a>) few past few months and I will share a simple way to build your data tables based on Horizon.<br />
To give a brief introduction of Horizon, it is the official dashboard project of OpenStack, the cloud operating system. Horizon is a python Django application. It provides pre-defined modules for common web application requirements like tabs, workflow, table etc. From Grizzly release onward Horizon modules are separated from OpenStack specific code. It allows one to use Horizon modules independently.<br />
<br />
To build a data table in Horizon you need to simply create a model class for your data. The important thing to remember here is that <b>the class must have an "id" attribute</b>. Horizon will build rows based on this id. It can be alpha numeric also. Though it is not mandatory to display the id column in the table, you can still have it. Below is the data model for my Employee table -<br />
<br />
<script src="https://gist.github.com/sarbajitc/8fadf68865151cd533a4f25039e425f9.js"></script>
The employee class has 4 attributes - id, name, address and the salary. Each of these attributes can be displayed in a column of our Horizon DataTable. I use below code in my views.py<br />
<br />
<script src="https://gist.github.com/sarbajitc/2dded38c72df501d72ae745de236da7e.js"></script>
We need to create a tables.py with TabledisplayTable class which allows us to map the columns to model attributes. Like this -
<br />
<script src="https://gist.github.com/sarbajitc/a412e4f9af43738573f43a7f2d3eeb89.js"></script>
Finally we need a Django template to render this table. I have used the following code -
<br />
<script src="https://gist.github.com/sarbajitc/db6d9c50744df91192cf426828880407.js"></script>
This should create the Employee table with 2 rows using Horizon DataTable module. Try it out.
</div>
Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com8tag:blogger.com,1999:blog-7884492825228653821.post-40190386934507422852012-02-25T11:25:00.000+05:302018-06-23T09:32:20.714+05:30Get current UTC timestamp in Python<div dir="ltr" style="text-align: left;" trbidi="on">
Converting current time to UTC (GMT) in python is a very common query that is searched in Google but, I did not find a compact answer when I did the search for my work. I figured out the code by some help from Google and some experimentation of my own. I'll share the code, in case it is useful to someone.<br />
<br />
First I'll explain the Epoch time (or POSIX/Unix time) and UTC (Coordinated Universal Time) time format.<br />
Epoch time is calculated as number of seconds elapsed since midnight Jan 1, 1970. It is used in all *nix systems and has become a standard when considering date/time from multiple systems. In python time module allows us to get the current epoch time in local time zone.<br />
<br />
<script src="https://gist.github.com/sarbajitc/63a8ebd5044161560160dc3cf23c168e.js"></script>
UTC time is basically synonymous of GMT. It marks the 0 offset time zone. Time in all other time zones are calculated with positive/negative offset from UTC. It is used in many cases where there are multiple machines, located in different time zones are involved. To get current UTC time in python we use utcnow() function from datetime module. But, if you need the time in seconds you need to do the following -<br />
<script src="https://gist.github.com/sarbajitc/8f8c016618bb9992ee9f07a1189c269c.js"></script>
You can match the correctness of generated time in <a href="http://www.epochconverter.com/">http://www.epochconverter.com/</a> by converting Human date to timestamp in GMT format.</div>
Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com3tag:blogger.com,1999:blog-7884492825228653821.post-71594262588209232302012-01-15T22:57:00.000+05:302012-06-26T23:01:10.582+05:30Upgrade wireshark version in Ubuntu<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://www.wireshark.org/">Wireshark</a> is a great and may be most widely used network protocol analyzer. In last few months I had used it extensively in a network project. Wireshark was a great help in debugging hard to find protocol problems.<br />
<br />
During this project I was using Ubuntu 10.04 as my development environment. I installed wireshark using<br />
sudo apt-get install wireshark<br />
<br />
But default wireshark version provided by Ubuntu 10.04 repository is 1.2.7 which was not suiting my purpose. I needed the newer versions of wireshark which provides some important features for analyzing protocols.<br />
<br />
There are 2 ways to upgrade your wireshark version from the default version provided by Ubuntu -<br />
<br />
<br />
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li>Add a third party repository to your repo conf and you can upgrade the wireshark. But I do not prefer this way as it imposes the restriction of version that can be installed.</li>
<li>Install wireshark from source. This is best way as you can install any version of wireshark in your Ubuntu.</li>
</ul>
<br />
<br />
<div style="text-align: left;">
Here are the steps to follow -</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
</div>
<ol style="text-align: left;">
<li>Download the wireshark source code as per your preferred version.</li>
<li>Extract the source.</li>
<li>Building wireshark from source has multiple dependencies e.g. GTK2+, bison etc. To know the dependencies required by your wireshark version, run below command inside the extracted source directory - <span style="font-family: 'Courier New', Courier, monospace;">dpkg-checkbuilddeps</span></li>
<li>The output of dpkg-checkbuilddeps command will list down the required libraries for building wireshark. Use <span style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install <lib name=""></lib></span> to install all dependencies.</li>
<li>Once all libraries are installed configure wireshark (prefix option installs it in specific directory) - <span style="font-family: 'Courier New', Courier, monospace;">./configure --prefix=/home/myuser/wireshark-custom</span></li>
<li>Run make install.</li>
<li>Once the build is done, you can use wireshark just as out of the box.</li>
</ol>
</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com2tag:blogger.com,1999:blog-7884492825228653821.post-43512820893275135172011-12-25T11:25:00.000+05:302018-06-23T09:36:35.257+05:30Call an external program from MySQL trigger<div dir="ltr" style="text-align: left;" trbidi="on">
MySQL is the choice of many when it comes to database. Its free and quite robust.<br />
During one of our prototype implementations we had a requirement of calling some external processes when there is a change in a MySQL table. MySQL triggers are provided for the same purpose. They get executed when the table is changed in certain ways that is specified by the programmer. Now it is very easy (rather trivial) to do some thing in other MySQL database tables when trigger gets fired. But, our requirement was to call a C program.<br />
<br />
Fortunately MySQL provides a way to implement your own functions, its called User Defined Functions (UDF). The "how to" is <a href="http://dev.mysql.com/doc/refman/5.0/en/adding-udf.html">here</a>. Now that we know, how to define your own functions and call them from MySQL events, we need to write our logic in a C program by following the interface provided by MySQL and we are done.<br />
<br />
Wait a minute. That is already done by somebody. They have made a library of UDFs. One of them, <a href="http://www.mysqludf.org/lib_mysqludf_sys/">LIB_MYSQLUDF_SYS</a> does exactly what we want. It allows you to call an external program from MySQL procedure/trigger. Once you download and untar the files, you'll get an <i>install.sh</i>. Just need to run it but, make sure you have <i>gcc</i> and <i>make</i> before that. The install script copies the library shared object file to <i>/usr/lib</i>. In some 64 bit systems it may be <i>/usr/lib64</i>. Also you need to check MySQL <i>plugin_dir</i> property which points to the directory where the .so file should be placed.<br />
<br />
<br />
Once the UDF is installed successfully, we can use 2 functions to call an external program -<br />
<br />
1. sys_exec : Returns the exit code of the external program.<br />
2. sys_eval : Returns the output from the external program.<br />
<br />
Here is a code snippet which show an example:<br />
<script src="https://gist.github.com/sarbajitc/953e977a29ef0765f4b77a4912f0f453.js"></script>
I have a hello_world program (<i>/home/sarbac/hello_world</i>) which accepts 1 command line argument and writes to a file.<br />
Don't forget to return int from the main function if you are using sys_exec().<br />
<br />
<a href="mailto:dipti262@gmail.com">Deepti Sharma</a> has thoroughly investigated this approach. I thank her for that.<br />
<br /></div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com66tag:blogger.com,1999:blog-7884492825228653821.post-69313831522185138902011-11-11T12:14:00.000+05:302018-06-23T11:06:39.887+05:30Read a log file in tail mode from python<div dir="ltr" style="text-align: left;" trbidi="on">
When you want to develop a log reader application, you'll need to keep reading the log. There is a Linux utility doing exactly the same. Its the <i>tail</i> command. <i>tail</i> blocks on the file till new entries are appended to it.<br />
<br />
I needed the similar functionality in python and there was a small library providing it already. Its called <a href="http://code.activestate.com/recipes/436477/">filetail.py</a>. The program performs tail functionality and also handles log rotation.<br />
<br />
But in my case, the log file used to change (file name) depending on the date. filetail could not handle it as the file name has changed already. To handle this I have made following changes to the filetail code -<br />
<br />
In nextline() method file size should be checked to be less or equal to the cursor position:<br />
<script src="https://gist.github.com/sarbajitc/d545fb102e8f540e54655c75e6b761d3.js"></script>
In _reset() method I have added the logic to re-create the log file name from the current date value and replace it with the original file name:<br />
<script src="https://gist.github.com/sarbajitc/ab312a5107a4ccb240687c25b3f546cf.js"></script>
I apologize for not following standards of coding here. It served the purpose for me.</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-23286824785406009772011-10-16T22:29:00.000+05:302018-06-23T11:22:44.976+05:30jQuery UI dialog without any close option<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
We use jQuery UI for designing web pages in out project. Some times back we had a scenario where the user log in to a dashboard was implemented using jQuery UI <a href="http://jqueryui.com/demos/dialog/">dialog</a> (modal) component. Requirement was that the dashboard page should not be reached without passing the authentication process. But the dialog component of jQuery UI library provides a default X icon at the top left corner of the element which provides an option to close the dialog.<br />
<br />
In our case, we wanted to reload the same page on click of the X icon. So that the user can not escape the login dialog by using the X icon. We achieved this by writing the page reload code inside dialog's close handler. Everything worked fine until we had to handle the successful log in. Once user login succeeds we need to call dialog widget's close handler which reloads the page in turn. Because of this, even after a successful login, user gets the login dialog again.<br />
<br />
The only way to stop this was, to remove the page reload code from the widget's close handler. Then it would require to remove the X icon from the dialog widget so that the close handler can not be invoked by clicking the X icon. But jQuery UI gives no option to build a dialog without close icon.<br />
<br />
Thanks to <a href="mailto:dipti262@gmail.com">Deepti Sharma</a> for finding out a easy solution to the problem. Here is how it looks after the modification -
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7XjEL-cH6QEv-OT0tZDIHExuO713udXHvI-zM-jrkxfXpiJrvoJaBlMN4nLJZr9z5a4QGYtvxox_tslweMlXwu6XVtNEVprMOz2A1uBYxDOTvaObhofnp0yH2ekUcr9Cl3Z2lJo4UFdaN/s1600/dialog-box.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7XjEL-cH6QEv-OT0tZDIHExuO713udXHvI-zM-jrkxfXpiJrvoJaBlMN4nLJZr9z5a4QGYtvxox_tslweMlXwu6XVtNEVprMOz2A1uBYxDOTvaObhofnp0yH2ekUcr9Cl3Z2lJo4UFdaN/s320/dialog-box.jpg" width="320"></a></div>
<br />
<br />
Below is the HTML code for creation of the dialog box.</div>
<script src="https://gist.github.com/sarbajitc/ccdd11ea88cec3243f12335a603b9214.js"></script>
The JavaScript part of code is doing the actual business. First we create the login dialog using jQuery UI API, then we hide the X icon by setting its display property. Here is the code
<script src="https://gist.github.com/sarbajitc/9583cc3895354307fc8464936fe6a269.js"></script>
The important part is the<i> aria-labelledby</i> attribute. It will contain the original div id of the dialog. So, we can find out the correct X icon to hide (there are multiple dialog boxes in the page). Though the code looks dirty, it works.
<br />
Once the close icon is removed, user can only submit the login page but can't close/cancel the login.</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-30641239950942182942011-09-17T21:15:00.000+05:302011-11-05T21:17:04.007+05:30Setup VNC server in Ubuntu 10.04<div dir="ltr" style="text-align: left;" trbidi="on">
I needed a system outside my company firewall to access access some internet based applications. I wanted to use a web browse from that. But all I had was, a cloud node running Ubuntu 10.04 with command line access to it. I installed VNC server in that to run firefox web browser. Steps are below -<br />
<div>
<br /></div>
<div>
<ol style="text-align: left;">
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install xinit</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install x11vnc</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo xinit &</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">x11vnc -safer -localhost -nopw -xkb -once -display :0 &</span></li>
<li>Create a ssh connection from Putty. I have user ssh port forwarding feature to make the connection secure. After configuring normal host name, user id or ssh key etc. go to Connection > SSH > Tunnels section. Input 5902 for Source and localhost:5900 for Destination. Click Add.</li>
<li>Now open this session from Putty.</li>
<li>Download Tightvnc java client and unzip it to some directory.</li>
<li>Run the jar file that was extracted in last step.</li>
<li>In the new window, input 127.0.0.1 for Server and 5902 for port. It should launch another window showing Ubuntu system.</li>
</ol>
<div>
Now you can install any GUI application in Ubuntu and use it through VNC.</div>
</div>
</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com6tag:blogger.com,1999:blog-7884492825228653821.post-16017777662415168512011-08-30T22:29:00.000+05:302018-06-23T11:26:23.737+05:30Run Cherrypy web server in Android<div dir="ltr" style="text-align: left;" trbidi="on">
I was in much need of a way to run Python CGI scripts in Android. Basically I needed a web server capable of running CGI scripts in Android platform but, I found none. Finally I modified my CGI script to suit the Cherrypy web server and it could run on Android.<br />
<br />
I'll try to describe the steps here which I had to figure out myself. The information I found by googling was not completely correct as Android platform has changed from the time of the publication. So, I'll mention the version no. for each software I've used to make sure it is not misunderstood later.<br />
<br />
<br />
<ol style="text-align: left;">
<li>First thing we need is to download the SL4A (r4) software in the Android (2.3) emulator. It can be done from your Android browser by going to the <a href="http://code.google.com/p/android-scripting/">SL4A site</a>. Now install the software in emulator.</li>
<li>Then install Python for Android from the same SL4A site. It'll download an apk of version r4.</li>
<li>Launch SL4A application and check that HelloWorld python script is running. It will make sure that your installation is fine.</li>
<li>Now is the time to install Cherrypy library module. It can be found at <a href="http://www.cherrypy.org/wiki/CherryPyDownload">http://www.cherrypy.org/wiki/CherryPyDownload</a>. I have taken 3.2.0 version. Download the egg for python 2.6.</li>
<li>Now we need to transfer the egg file to Android emulator. Use <i>adb push</i> command to transfer the egg file to <i>/mnt/sdcard/Download</i>.</li>
<li>Launch Python for Android from emulator and click on Import modules. It will list the newly uploaded egg file. Select it and install.</li>
<li>Now we can write a Cherrypy script to be run as CGI. Below is a HelloWorld example taken from Cherrypy tutorial (modified a bit) -
<script src="https://gist.github.com/sarbajitc/1f5ee64fda8efa1d3adf909f19b60515.js"></script>
</li>
<li>The script needs to be transferred to /mnt/sdcard/sl4a/scripts directory in emulator. Then you can launch SL4A and tap the script to run. Debug outputs are visible if you run in SL4A console.</li>
<li>From the Android browser, check the URL http://localhost:8080/. It will say "Hello world".</li>
</ol>
<div>
This the web server set we can place python scripts to access Android phone data and other stuff which can be exposed to the outside clients.<br />
<br />
<br />
EDIT:<br />
Below are the screen shots from the emulator -<br />
<br />
1. Apps list after installing SL4A and Python for Android<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihn1O62yjt0b1bHwtzAQ98eKPxlNzd_XREQTUY7nQ0RDuBSzrnSk2tCeA15Zv4gQvB5sNQL-QCvSHsPE5kCqvSP3uXW5S6KwsKznl2i4Kg2rmdpSzpI3t1py58lSGh9Tm2MfFcxacpo5Ac/s1600/Android_menu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihn1O62yjt0b1bHwtzAQ98eKPxlNzd_XREQTUY7nQ0RDuBSzrnSk2tCeA15Zv4gQvB5sNQL-QCvSHsPE5kCqvSP3uXW5S6KwsKznl2i4Kg2rmdpSzpI3t1py58lSGh9Tm2MfFcxacpo5Ac/s320/Android_menu.jpg" width="320"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
2. Tap on <b>Python for Android</b> icon to launch below screen.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3tdtFfwAuCd1kECcfhc7YLO3kRrqekh6AIY4B_cb_gt_nA_62C_3gC-Kz4aF3cWkKZtFPJand-IRMjLm6UgZbr45fy140SKbpJWyHu1vQHrNAAg1KnXsgaO6nR9d6oT9ZPxDXDRtHVlj/s1600/Python_for_Android.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3tdtFfwAuCd1kECcfhc7YLO3kRrqekh6AIY4B_cb_gt_nA_62C_3gC-Kz4aF3cWkKZtFPJand-IRMjLm6UgZbr45fy140SKbpJWyHu1vQHrNAAg1KnXsgaO6nR9d6oT9ZPxDXDRtHVlj/s320/Python_for_Android.jpg" width="320"></a></div>
<br />
<br />
3. Tap on <b>Import Modules</b> after copying the CherryPy egg in <i>/mnt/sdcard/Download.</i><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYVhpj6HVFQ6nONzBrngXEtZkp7ZaKl5YZ211HRYBanI3_h0x7RJ5EKdu8u8Mi2wMKF0qzpLVlKGLzwKZXWbUgW9QS6LJ9JIbdGiW6LNN5cDVOaAgyVlDJ5bFiF-1EglrU4vlQlOXv7mNu/s1600/Import_module.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYVhpj6HVFQ6nONzBrngXEtZkp7ZaKl5YZ211HRYBanI3_h0x7RJ5EKdu8u8Mi2wMKF0qzpLVlKGLzwKZXWbUgW9QS6LJ9JIbdGiW6LNN5cDVOaAgyVlDJ5bFiF-1EglrU4vlQlOXv7mNu/s320/Import_module.jpg" width="320"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Now tap on CherryPy to install it.</div>
<br /></div>
</div>
Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com7tag:blogger.com,1999:blog-7884492825228653821.post-30304426260375680292011-07-23T11:29:00.000+05:302018-06-23T11:30:42.285+05:30Flexigrid table becomes read only when no rows returned from server - solution<div dir="ltr" style="text-align: left;" trbidi="on"><a href="http://flexigrid.info/">Flexigrid</a> is a popular jQuery plugin which builds multipurpose data grid in web pages. It is a light weight plugin with rich controls. I have used Flexigrid heavily in my project. While using the plugin I faced one problem. It disables the grid when there are no rows in it. This looks like a proper behavior until you need the buttons in the table (Add) to be enabled for the first row to be added.<br />
<br />
To clarify the requirement I had, there is a grid with Add and Delete buttons in it. The first row in the grid will be added through the add button. So, when the table loads for the first time, there is no row and this makes the grid read only. Now, we can not click the add button. It becomes a recursive problem.<br />
<br />
The Flexigrid code that does this -
<script src="https://gist.github.com/sarbajitc/0415e58e78174b3ba1a06887a8091311.js"></script>
I have devised a dirty fix for this problem -
<script src="https://gist.github.com/sarbajitc/9a30961f4c625d49b2be1c47420c5094.js"></script>
Use this code in your document.ready() function.<br />
I tried asking the problem in the Flexigrid mailing list also, but could not get any other solution. So, currently this is the only working solution available. Try it out.</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com4tag:blogger.com,1999:blog-7884492825228653821.post-49608739698147787052011-06-25T16:11:00.003+05:302018-06-23T11:33:52.159+05:30Resolve Hibernate connection timeout issue with MySQL server<div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" style="text-align: left;" trbidi="on">This problem has been faced by many of the developers but the fix is not very common. I had to do some research to find out the problem and solve it.<br />
<div>If you are using a MySQL server, the default connection timeout is 8 hours (tested on MySQL 5.2). This causes a problem in production environment as the database could not be connected overnight. Below is the log trace of the problem -<br />
<br />
<span class="Apple-style-span" style="font-family: inherit; line-height: 15px;"><i>org.hibernate.util.JDBCExceptionReporter: The last packet successfully received from the server was 56697 seconds ago. The last packet sent successfully to the server was 56697 seconds ago, which is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem.</i></span><br />
<br />
<br />
As the description says, we can increase the wait_timeout property of MySQL server but it is not a good idea to keep stale connections open for long time. The 'autoReconnect=true' property did not work for me.<br />
<br />
I figured out the below solution which worked perfectly for me.<br />
First we need to modify our hibernate.cfg.xml file and add the following lines -<br />
<br />
</div></div>
<script src="https://gist.github.com/sarbajitc/cc5f647942a171c0a3ebd2ced6c66e13.js"></script>
You have to add a new file in your classpath called <i>c3p0.properties</i>. The file contains -<br />
<br />
<i>c3p0.testConnectionOnCheckout=true</i><br />
<br />
The last but most important part is to add the required jars in the classpath. You must have hibernate.jar (contains <i>org.hibernate.connection.C3P0ConnectionProvider</i> class) and c3p0.jar.<br />
<br />
This should solve the auto disconnection issue permanently.<br />
<br />
<i>P.S. To test the fix, you can change the wait_timeout property in my.cnf file (<span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; line-height: 23px;"><span class="Apple-style-span" style="font-family: inherit;">/etc/mysql/my.cnf in Linux</span></span>) of MySQL server. Specify a small timeout value of few minutes.</i><br />
<br />
<br />
</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com5tag:blogger.com,1999:blog-7884492825228653821.post-29674645369257780912011-05-11T00:38:00.000+05:302018-06-23T11:40:39.184+05:30A simple REST based web service<div dir="ltr" style="text-align: left;" trbidi="on">REST stands for Representational State Transfer. Roy Fielding, the father of HTTP protocol, had coined the term in his doctoral thesis. REST is not a software, rather it is a concept or an architecture. The biggest use of REST architecture is in WWW (World Wide Web). The services that conforms to REST standard are termed as RESTful services.<br />
<br />
REST based services contain a client and a server. The server contains resources that can be represented by various states. A client initiates the request to server when it is ready to transition it's state. The server responds with the required state.<br />
<br />
The REST based web service is quite popular now. This type of web service is called RESTful web service. In RESTful web service we represent a service by an URI. Common HTTP methods are used to request for a specific state transfer.<br />
<br />
<br />
<table cellpadding="3px"><tbody>
<tr><td>Create</td><td>PUT</td></tr>
<tr><td>Update</td><td>POST</td></tr>
<tr><td>Read</td><td>GET</td></tr>
<tr><td>Remove</td><td>DELETE</td></tr>
</tbody> </table><br />
I have used an open source java library called <a href="http://www.blogger.com/"><span id="goog_663244038"></span>Jersey</a> for creating this simple RESTful web service. Jersey is a production quality JAX-RS (JSR311) implementation. The jars from Jersey distribution need to be added to the <i>WEB_INF/lib</i> directory of your web application. Below is the code for a hello service -
<script src="https://gist.github.com/sarbajitc/1883b7a53180b6f31c4899f48e9b6c8f.js"></script>
Here the service URI will be <i><web application URL>/hello</i> as defined by the <i>Path</i> annotation. The <i>GET</i> annotation marks the service to be called on a HTTP GET request from client. The <i>Produces</i> annotation filters the accept type header in the request to match the correct state to be returned. It takes care of the content that is returned.<br />
<br />
There is one more way to make the same web service. This time I'll only use URI as a representation differentiation. Below is the code-
<script src="https://gist.github.com/sarbajitc/b8b8890b08fb82571acf156b237ff20b.js"></script>
To get a HTML output the client has to make a GET request with <i><web application URL>/hellowithpath/html</i> URI. Here I have only used the Path annotation.<br />
<br />
One more thing remaining is, adding a servlet mapping in the web.xml file of the web application. Add the below mapping-<br />
<script src="https://gist.github.com/sarbajitc/b0af85f74510ab282ee64047a72073de.js"></script>
<br />
<br />
Once you deploy the web application in a server the RESTful services will be started. They can be tested using a browser or a http client program.</div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-42089810412935513782011-04-02T01:44:00.001+05:302018-06-23T11:55:47.630+05:30Using web service client behind a http proxy server<div dir="ltr" style="text-align: left;" trbidi="on">Web service is a popular medium of communication between devices over a network. But most of the time you find yourself behind a http proxy server to connect to the network. Proxy servers are often found in company networks. The main reasons for their introduction are - security, resource caching, auditing etc. But ultimately they block unauthorized access to internet from the inside network. This leads to the problem we are going to solve now.<br />
<br />
We are going to use w3schools temperature converter service (<a href="http://www.w3schools.com/webservices/tempconvert.asmx?WSDL">WSDL download</a>) for testing. Make sure you are actually running this code behind a http proxy server. You also need to know the proxy server's host name and the port no. I'll assume that you can generate the client stubs using JAX-WS (or some other tool). I have used <i>wsconsume</i> tool to generated my stubs.<br />
<br />
In my case, <i>com.w3schools.TempConvert</i> is the implementation class and <i>com.w3schools.TempConvertSoap</i> is the interface. Then I have a <i>com.w3schools.client.WSClient</i> class which is the actual client.<br />
<br />
The trick here is to initialise a new instance of <span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: inherit;"><i>java.net.ProxySelector</i> class in WSClient code with your proxy settings.
To achieve that you need to write a class which extends </span></span><span class="Apple-style-span" style="white-space: pre;"><i>java.net.ProxySelector</i></span><span class="Apple-style-span" style="white-space: pre;">. See below -</span>
<script src="https://gist.github.com/sarbajitc/2ad1e1e974e9bd5176de1ca3a2581743.js"></script>
<span class="Apple-style-span" style="white-space: pre;">With MyProxySelector class being ready we can set this default proxy in the WSClient code. Like this -</span>
<script src="https://gist.github.com/sarbajitc/fa32155306a8da918db3a88952515cc4.js"></script>
<span class="Apple-style-span" style="white-space: pre;">Now you can invoke the WSClient to use w3school web service even from behind a proxy.</span></div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com4tag:blogger.com,1999:blog-7884492825228653821.post-24053824144968666652011-03-15T00:10:00.000+05:302018-06-23T12:20:26.093+05:30Write your first JAXWS web service<div dir="ltr" style="text-align: left;" trbidi="on">Today I'll try to explain how easily one can build a JAX-WS web service. Web Services are very popular now-a-days. They are used every where. But I found it difficult to write my first web service with jax-ws, partly because I was trying myself and partly because I could not get a simple explanation of steps. That is why I'll try to show the simplest web service possible using jaxws.<br />
<br />
First thing first, what do you need to build your first jax-ws web service.<br />
<div style="text-align: left;"></div><ol style="text-align: left;"><li>JDK 1.6 (I used update 23)</li>
<li>Eclipse IDE (you can use some other IDE as well)</li>
<li>Are you kidding? nothing else.</li>
</ol>JAX-WS 2.0 is actually Sun's (now Oracle) reference implementation of Web Service stack. It is bundled with JDK 6 and above.<br />
<div style="text-align: left;"><br />
</div><div style="text-align: left;">First you need to create a Java project in Eclipse. Then create a class called <i>com.ws.HelloService</i>. This will be our web service class. Have a public method in this class which will be exposed as web service. Below is the code -</div><div style="text-align: left;"><br />
</div><div style="text-align: left;"><br />
</div>
<script src="https://gist.github.com/sarbajitc/57a26cd4578c31e9157d618e58467b0c.js"></script>
<div style="text-align: left;"><br />
</div><div style="text-align: left;">The catch here is the <i>@WebService</i> annotation. This is the key. It tells jaxws engine that the HelloService is a web service class. By default jax-ws exposes all public methods of a class. So, in our case it will expose sayHello operation.<br />
Now our service code is ready. It needs to be deployed to some HTTP server for testing. Fortunately, JDK 6 comes with Jakarta Commons HTTP client. We can directly deploy the service in this server. Create a separate class for this -<br />
<script src="https://gist.github.com/sarbajitc/91e730606942eb3f036ea9a86950c197.js"></script>
Run this class. Thats it. We are done with deployment. You can check the WSDL document at <ws url><ws url="">?wsdl location. Invoke the service with some name. It will return Hello + name.</ws></div></div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com2tag:blogger.com,1999:blog-7884492825228653821.post-61714997832152200272011-01-29T23:02:00.001+05:302018-06-23T12:29:19.052+05:30Get JSON data response with JQuery Form plugin for a file upload form<div dir="ltr" style="text-align: left;" trbidi="on"><br />
My latest project involves JQuery for UI development. Frankly speaking, I did not have much idea of JQuery before. But I found it very easy to understand. All APIs are well documented with lots of examples available on Internet. The best feature of JQuery is its plugins. There are thousands of plugins available to play with. For every need of my web app I could find a plugin.<br />
<br />
In my web app I am using <a href="http://jquery.malsup.com/form/">JQuery Form plugin</a> to submit the forms through AJAX. The return from my servlet is JSON object. The form plugin works great for all my forms. Well almost all, there is a HTML form which has a file upload box along with other input fields. This form was not able to get the response in JSON format. Though it worked in Google Chrome, but Firefox was presenting me with a file save dialog box.<br />
I did a lot of googling to find out whats going on. Finally I observed that the problem is with HTTP headers that the form submit request has. Here are the headers captured by Chrome<br />
<div style="text-align: left;"></div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP067JPQOn4-uX_1Mz1EA0BrYXOrS-ikJkJMEgISg06vVk4oL-w-gFIZAfi20AJlvqP4AafwebaGxWsdRqeEJJYBgLGo2AF95VyclYFogWF9nBVwpe9KtdChlHSMk7OeiNJPUSo1ve-9vS/s1600/request.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP067JPQOn4-uX_1Mz1EA0BrYXOrS-ikJkJMEgISg06vVk4oL-w-gFIZAfi20AJlvqP4AafwebaGxWsdRqeEJJYBgLGo2AF95VyclYFogWF9nBVwpe9KtdChlHSMk7OeiNJPUSo1ve-9vS/s640/request.jpg" width="640"></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Request headers captured by Chrome</td></tr>
</tbody></table><br />
<br />
<br />
As you can see the <i>Accept</i> request header does not contain <i>application/json</i>. That is why the response JSON object is not understood by the browser and it pops up a file save dialog.<br />
When I checked the source code of JQuery Form plugin, I found that in case of a multipart form (i.e. form having file items) the plugin does not use ajax to submit the form. Rather it uses an IFRAME element. So the form submission is a normal GET/POST request. Here is the part of plugin code that does it -<br />
<script src="https://gist.github.com/sarbajitc/7443f9aeef1b5c7e99f5ef52b4423cd9.js"></script>
<div dir="ltr" style="text-align: left;" trbidi="on"><br />
Basically its a normal HTTP request not ajax call. So the <i>Accept</i> header is set to <i>application/xml, text/html</i> etc. But the response from the servlet has a <i>Content-Type</i> as <i>application/json</i>. So, browser opens a save as dialog.<br />
<br />
To solve this issue in a proper fashion we need to modify the plugin code to upload the file through an ajax request. But files can not be transmitted through ajax. Due to this limitation I had to find another solution which is not as clean as the above one but it will do the job.<br />
<br />
The solution is to set the response <i>Content-Type</i> as <i>text/plain</i>. To do this I used below code<br />
<script src="https://gist.github.com/sarbajitc/97e82063a458df03625f868711576762.js"></script>
I checked the request header <i>Accept</i> to see if browser can accept a JSON. If yes, then set the response <i>Content -Type</i> to <i>application/json</i>. Otherwise set it to <i>text/plain</i>. This technique will fool the browser as it falls among the requested types. After this change I captured the response headers<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh69Dys-IULnrRAzArtzy3P-79uP_yxCWQfBj_t7G2_fHjJUyL9C_cJwjUpYk6DPGOldCKbBTP92VoWPSiHJex1dqS7TBoOkWhtSrciBrusPJhPcU9CHThzbYlXYs2edjp-UlaG3mkriS5m/s1600/response.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh69Dys-IULnrRAzArtzy3P-79uP_yxCWQfBj_t7G2_fHjJUyL9C_cJwjUpYk6DPGOldCKbBTP92VoWPSiHJex1dqS7TBoOkWhtSrciBrusPJhPcU9CHThzbYlXYs2edjp-UlaG3mkriS5m/s1600/response.jpg"></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Response headers captured by Chrome</td></tr>
</tbody></table><br />
<br />
<br />
We need to make one more change in the client side code.<br />
<script src="https://gist.github.com/sarbajitc/9cb542849c33133ca216aa2afd7726db.js"></script>
This is important because, without the <i>dataType</i> property, the response will be treated as a text by the plugin. So, the client side script that works on the response of the form submit will not work as it will get a string instead of JSON object.<br />
<br />
I checked the method in Firefox 3.6, Chrome 8.0, Internet Explorer 8 and Opera. It worked. I could also maintain my servlet's response type as <i>application/json</i> for all other forms (which does not have a file upload). I hope this works for you too.</div></div>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com12tag:blogger.com,1999:blog-7884492825228653821.post-29892494069414233802010-12-31T12:47:00.000+05:302018-06-23T12:32:13.921+05:30log4j.xml - A sample configurationI could not post anything last month though all the time I was dying to post something. The reason behind this was I change in my profession profile. Actually, I changed my employer. All of the last month I was busy in official work and to settle down in my new office.<br />
The last week of the year is normally a holiday in the new company. So, I could rest a while in my home and able to write the blog post.<br />
<br />
Though I had a couple of other topics in mind but writing them will take more time which I don't want to spend during the festivities. So, I'll discuss about a simple but useful thing.<br />
How many of us in Java sphere use log4j for logging? You know the answer. log4j is a very popular logging framework. Configuring log4j is quite simple. Still when you get the task of doing it, you try to find an example (I do the same). That is why I'll show a simple log4j configuration to print to a file.<br />
<br />
<script src="https://gist.github.com/sarbajitc/abaa3b4f290c4e918163307cb57b669b.js"></script>
There are 2 ways to configure log4j, log4j.properties and log4j.xml. I prefer the xml format.<br />
In this example I have configured the log4j to generate logs in apache tomcat's log directory (the application is a web app). Also I have channeled hibernate logs to the same log file.<br />
Another important feature which is used very often is rollingFileAppender. It can roll your log files when they reach their limits.<br />
To use this example you need a log4j.jar (I used 1.2.16). Hibernate (3.6.0) uses self4j logging APIs. So, you'll need self4j-log4j.jar. It can be downloaded from <a href="http://www.slf4j.org/">self4j site</a>. I have defined a CONSOLE appender to display log messages in system console. You can add it to root logger to enable the console logging. That's all for this sample log4j.xml.<br />
<br />
<i>I hope the New Year 2011 brings best for everyone.</i>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-6033183107155439062010-10-29T01:36:00.000+05:302018-06-23T12:40:04.765+05:30Strings in Switch statements - a new JDK 7 featureJDK 7 is the next release of Java language. There are lot of expectations from this release. For the first time Java is being modeled outside Sun Microsystems. Now JDK 7 has got a net host, <a href="http://openjdk.java.net/">openJdk</a> community.<br />
<br />
There are quite a few features planned in JDK 7. Some of them may prove to be a milestone for Java language. But my personal liking is a very small feature rather project called <a href="http://openjdk.java.net/projects/coin/">Project Coin</a>. Coin serves to add small language features to Java which will make programmer's life easy. The JavaOne 2010 presentation for Project Coin lists the following features as accepted ones in JDK 7 time frame.<br />
<br />
<br />
<ul><li>Binary literals and underscores in literals</li>
<li>Strings in switch</li>
<li>Varargs warnings</li>
<li>Diamond</li>
<li>Multi-catch and more precise rethrow</li>
<li>try-with-resources (formerly known as Automatic Resource Management, ARM)</li>
</ul><div><br />
Out of these features, the most attractive to me was "Strings in switch". This is something I've longed for from my college days. I mean, though it was not Java (it was C) still I dreamed of writing switch statements with strings. Finding a unique hashcode for each string to be switched was tedious. In Java 5, usage of Enum constants in a switch statement was allowed. Still it did not fit.</div><div>Why do you use a switch block? Simple, when we have many alternative possibilities. See the below code -</div><div><br />
</div><div><br />
</div>
<script src="https://gist.github.com/sarbajitc/f55794600abad8072bff050860aa0895.js"></script>
This method returns no. of days when you pass the name of the month. But till now Java programmers used to write the method in this way. Some really cool dudes will try to construct an enum and use it in a switch block. But still we need a string comparison in order to set the value to the switch variable. Not too cool.<br />
<br />
Won't it be great if we can do the same code using switch construct. JDK 7 is coming with exactly the same promise. It will allow developers to use strings in switch. Check it out-<br />
<script src="https://gist.github.com/sarbajitc/c65b05465957b3c0cc7e658e379425f5.js"></script>
<br />
This feature requies change in JLS as well as in Java compiler and JRE. The implementation still uses string.hashCode() to find out the integer which can be used in native switch blocks. But now this will be done by java compiler. This will reduce the effort of Java developer and make the code more readable. The detailed strings in switch proposal can be found <a href="http://blogs.sun.com/darcy/entry/project_coin_strings_in_switch">here</a>.Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-74112029477766926352010-09-29T01:19:00.000+05:302018-06-23T12:51:11.039+05:30An unwise attack on the SingletonsFew days back I was disturbed with some maven build issues in office. I got back home pretty late. Already, as you can understand, mood was off. I thought of relaxing by watching a good movie but next day I had an interview scheduled. So, I had to brush up my skills a bit (I don't use them often in office :-) ). The first topic I started with was Singleton pattern. This one is so famous among interviewers that you better be able to explain it.<br />
I had read the pattern many a times already. Nothing to prove the book wrong, never occurred to me. But that day, may be due the horrible mood, I challenged the pattern. I thought I'll find ways to break the pattern down. I wanted to create 2 Singleton instances in same JVM. Thats how the attack began.<br />
<br />
Below is the code for creating a Singleton class<br />
<br />
<script src="https://gist.github.com/sarbajitc/15be87b08404856d87a68819cb67091a.js"></script>
Here is the code to test the pattern<br />
<br />
<script src="https://gist.github.com/sarbajitc/9701d38e1bb9aa1843e9c90fa35e8e3a.js"></script>
I have used <a href="https://visualvm.dev.java.net/">VisualVM</a> (comes as part of JDK 6) tool to check the no. of instances for Singleton class. You just need to pass a VM argument (<i>-Dcom.sun.management.jmxremote</i>) while running the program.<br />
So, far so good. Only one instance.<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNXKuBSaEQrI6EpZCAtf0L_iiS1eH2NNej3sDCNRiLXK7dEkbsSsRZdB9BVMT5eu6aneLPTL6iN2YV7dpJ7j5q-8uokGJ80n-t1tWB9Cd9TqDwX7Au70-Z9qwaicp8MGZtVQ0HG4BtH1Sy/s1600/singleton1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNXKuBSaEQrI6EpZCAtf0L_iiS1eH2NNej3sDCNRiLXK7dEkbsSsRZdB9BVMT5eu6aneLPTL6iN2YV7dpJ7j5q-8uokGJ80n-t1tWB9Cd9TqDwX7Au70-Z9qwaicp8MGZtVQ0HG4BtH1Sy/s320/singleton1.jpg" width="320"></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">This was rather bookish experiment. I knew it would happen. But still tried to make sure my setup is ok. Though the actual action happens next.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Then I tried serialization of the singleton object. I saved the serialized object to a file. Next, I de-serialized the object from file. Hurray!!! 2 Singleton objects are loaded in JVM. The test class code is-</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div>
<script src="https://gist.github.com/sarbajitc/921f39f3e78e45a94dd2fd5a39dd86b3.js"></script>
<br />
Here is the VisualVM output-<br />
<br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaGqXlDGoyiyFv8gHit-lnaoX_3sDSw3zOkI872JAtxaEkZBIgAg2aT2i9Dxp5sYM0BdKqe1ldwM1tJSbl1uvAwpGfXeRUsmK-QZukHuVOpMC9aHyzk_o-mGu4fLJ6BW1PXw7OnYvBe3j7/s1600/singleton2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaGqXlDGoyiyFv8gHit-lnaoX_3sDSw3zOkI872JAtxaEkZBIgAg2aT2i9Dxp5sYM0BdKqe1ldwM1tJSbl1uvAwpGfXeRUsmK-QZukHuVOpMC9aHyzk_o-mGu4fLJ6BW1PXw7OnYvBe3j7/s320/singleton2.jpg" width="320"></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">So, the pattern has been broken. It is not anymore a Singleton. But the question here is, how to prevent this attack. The code goes here -</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><br />
<script src="https://gist.github.com/sarbajitc/2c808d18568ba60ba5cfc4a74ca95db1.js"></script>
I have added a <a href="http://download.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html">readReasolve()</a> method in the modified Singleton class above. This gets called during de-serialization and the singleton static reference is returned.<br />
<br />
<br />
Finally, I tried Java reflection (very elegant way indeed). It is so powerful that you can even call private constructors. See how-<br />
<br />
<script src="https://gist.github.com/sarbajitc/70b2fe9d90a23d1bb6a06169f09071be.js"></script>
Yahooo!!! again success. This time also I was able to create 2 instances of the singleton class. Though by this time I was more oriented to find a solution to this one. Let's see that-<br />
<br />
<script src="https://gist.github.com/sarbajitc/0ae190f9935a7fe3e610a93b70cec84d.js"></script>
In this solution, I have made the private constructor throw InstantiationException when the static reference is not null (yes, constructors can throw exceptions). Thus it will throw an exception if we call the private constructor 2nd time even if in a reflective way.<br />
Is the last solution thread safe? Frankly speaking, I don't know. This part is yet to be explored. There may be some gotchas here. But I am not feeling wise enough to try it now. May be sometime later.Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-57374498236304797772010-08-29T20:48:00.000+05:302010-09-25T22:52:55.835+05:30Generate POM files for a 3rd party artifact in MavenMaven is a popular software project management tool. It is used heavily for building you project deliverables. More information about maven can be found <a href="http://maven.apache.org/">here</a>.<br />
<br />
Maven works on the dependency concept. It essentially means that every project should identify its required artifacts. These artifacts can be found in repositories. Repository is a central place where you keep all your required jars (or other resources). There is a specific structure required to put your artifacts into the repository. We can not just copy every thing at same place. To identify a resource through dependency mentioned in pom.xml, maven looks for the specific structure. Also ther should be a <artifactname-version>.POM file at the same location of the artifact.</artifactname-version><br />
<br />
Normally the artifacts generated by maven build comes with the POM for it. So that, any other project wanting to use this artifact can do that. But if the artifact is created from a build other than maven (e.g. ant, Makefile etc), it will not have the POM generated. So this artifact can not be readily used by maven. We need to use the below command to generate a POM for a 3rd party artifact which does not come with a POM by default.<br />
<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">mvn install:install-file -DgroupId=<i>group-id \</i></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -DartifactId=<i>artifact-id \</i></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -Dversion=<i>version \</i></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -Dpackaging=<i>packaging \</i></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -Dfile=<i>fileToInstall \</i></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"> -DgeneratePom=<i>true</i></span></span><br />
<br />
<br />
<i><br />
</i><br />
Here<i> groupId </i>is a string that identifies the product group. <i>artifactId </i>is the string to identify the artifact from its group. <i>version </i>is the artifact version. <i>packaging </i>is the file type of the artifact (e.g. jar). <i>file </i>attribute holds the complete path to the artifact in your local system. <i>generatePom </i>attribute creates the POM for this artifact.<br />
<br />
This command will create the required directory structure for your 3rd party artifact and generate a POM for it. The output will be copied to your local repository. Now you can use this dependency in your POM to build your project.Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-57118639417617087552010-07-31T21:22:00.000+05:302018-06-23T13:12:54.136+05:30Using Multi threading with DroolsDrools is a very popular rule engine. It is based on Rete algorithm. To understand what is a rule engine and how to use it <a href="http://downloads.jboss.com/drools/docs/4.0.7.19894.GA/html_single/index.html">check here</a>. But here I will assume that you have some working knowledge on Drools.<br />
<br />
What I am going to discuss in this post is 'how to use multi-threading with Drools'. Below is a snippet which creates a KnowledgeBase from a DRL file.<br />
<br />
<br />
<script src="https://gist.github.com/sarbajitc/6b323dfd84e7d48d2aac225fbe57008f.js"></script>
If this method is called from multiple threads I get below exception -<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;"><br />
Exception in thread "Thread-60" [Error: incomplete statement: (possible
use of reserved keyword as identifier: )]
<br />
[Near : {... globals != empt ....}]
<br />
^
<br />
[Line: 0, Column: 0]
<br />
at org.mvel2.MVELInterpretedRuntime.parseAndExecuteInterpreted(*
MVELInterpretedRuntime.java:153*)
<br />
at org.mvel2.MVELInterpretedRuntime.parse(*
MVELInterpretedRuntime.java:44*)
<br />
at org.mvel2.MVEL.eval(*MVEL.java:514*)
<br />
at org.mvel2.templates.res.IfNode.eval(*IfNode.java:61*)
<br />
at org.mvel2.templates.res.TextNode.eval(*TextNode.java:46*)
<br />
at org.mvel2.templates.res.TerminalNode.eval(*TerminalNode.java:39*)
<br />
at org.mvel2.templates.res.ForEachNode.eval(*ForEachNode.java:116*)
<br />
at org.mvel2.templates.res.TextNode.eval(*TextNode.java:46*)
<br />
at org.mvel2.templates.res.TerminalNode.eval(*TerminalNode.java:39*)
<br />
at org.mvel2.templates.res.IfNode.eval(*IfNode.java:64*)
<br />
at org.mvel2.templates.res.TextNode.eval(*TextNode.java:46*)
<br />
at org.mvel2.templates.res.ExpressionNode.eval(*
ExpressionNode.java:53*)
<br />
at org.mvel2.templates.res.TextNode.eval(*TextNode.java:46*)
<br />
at org.mvel2.templates.TemplateRuntime.execute(*
TemplateRuntime.java:195*)
<br />
at org.mvel2.templates.TemplateRuntime.execute(*
TemplateRuntime.java:190*)
<br />
at org.mvel2.templates.TemplateRuntime.execute(*
TemplateRuntime.java:180*)
<br />
at org.mvel2.templates.TemplateRuntime.execute(*
TemplateRuntime.java:169*)
<br />
at
org.drools.rule.builder.dialect.java.AbstractJavaRuleBuilder.generatTemplates(
*AbstractJavaRuleBuilder.java:126*)
<br />
at org.drools.rule.builder.dialect.java.JavaConsequenceBuilder.build(
*JavaConsequenceBuilder.java:128*)
<br />
at org.drools.rule.builder.RuleBuilder.build(*RuleBuilder.java:86*)
<br />
at org.drools.compiler.PackageBuilder.addRule(*
PackageBuilder.java:1159*)
<br />
at org.drools.compiler.PackageBuilder.addPackage(*
PackageBuilder.java:649*)
<br />
at org.drools.compiler.PackageBuilder.addPackageFromDrl(*
PackageBuilder.java:290*)
<br />
at org.drools.compiler.PackageBuilder.addKnowledgeResource(*
PackageBuilder.java:488*)
<br />
at org.drools.builder.impl.KnowledgeBuilderImpl.add(*
KnowledgeBuilderImpl.java:25*)
<br />
at com.myfirm.RuleFlowProcess.init(*RuleFlowProcess.java:25*)
<br />
at com.myfirm.RuleFlowProcess.clone(*RuleFlowProcess.java:53*)
<br />
at com.myfirm.ThreadTest$CloneThread.run(*ThreadTest.java:35*)
<br />
Caused by: *java.lang.NullPointerException*
<br />
at org.mvel2.MVELInterpretedRuntime.parseAndExecuteInterpreted(*
MVELInterpretedRuntime.java:113*)
<br />
... 27 more
</span></span><br />
<br />
<br />
The exception normally occurs at <span class="Apple-style-span" style="font-family: monospace;"><span class="Apple-style-span" style="white-space: pre;">KnowledgeBuilder.add(...) <span class="Apple-style-span" style="font-family: inherit;"><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><span class="Apple-style-span" style="font-size: small;">method</span>. </span></span></span></span>This can happen infrequently depending on the thread behavior. But there is always a chance to find this error in your production environment.<br />
Now the question is, how do we resolve this? One way, is to share the same knowledge base for all threads. But due to synchronized APIs you will not achieve the performance. Threads will run sequentially. There is another simple solution -<br />
<br />
<br />
<script src="https://gist.github.com/sarbajitc/e9e24dfc6b27139c964927bed534da5a.js"></script>
I have used synchronization on current Class object (don't confuse with the new instance of class). There is a single lock available for a Class. So, we can make threads sequential by synchronizing on the class level lock. This will not hit the performance much. Once the KnowledgeBase is created you can run parallel threads for rule execution. No further synchronization required.Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com6tag:blogger.com,1999:blog-7884492825228653821.post-40248475265356227772010-06-19T22:06:00.000+05:302018-06-23T13:23:55.393+05:30How to add new nonCacheable resource by inheriting Tomcat's DefaultServlet<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><span class="Apple-style-span" style="font-size: x-large;">D</span>o you have a web resource in your application which is dynamically generated/modified? And do you use JavaScript/Ajax (i.e. you do not have the resource mapped to a servlet in your application web.xml) to read that resource? If both answers are yes, then you may have seen that the request for the resource does not return the updated file always. The reason is DefaultServlet class of Tomcat which implements a caching technique for resources. If there is a HTTP request to access the resource before 5 sec of the last modification time, DefaultServlet will send the file from its cache (older content).</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">DefaultServlet is a servet provided by Tomcat distribution (and JBoss too). As the name suggests, it is the default choice. If your web application does not map a web resource to some servlet, DefaultServlet serves that resource. Only exception is JSP pages. Check out DefaultServlet <a href="http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/servlets/DefaultServlet.html">Javadoc</a> and <a href="http://www.docjar.com/html/api/org/apache/catalina/servlets/DefaultServlet.java.html">source code</a>. The servlet mapping is defined in Tomcat web.xml which is normally present at </span><span class="Apple-style-span" style="font-family: monospace; font-size: 12px;">$CATALINA_HOME/conf/web.xml. </span><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">In JBoss 5.1.0 GA, we find this at </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">$JBoss_HOME/server/default/deployers/jbossweb.deployer/web.xml</span></span><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">. I have shown the part of</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> web.xml</span><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"> below-</span><br />
<script src="https://gist.github.com/sarbajitc/7e3b76afe0c6f6d4397cc74079b8ba4a.js"></script>
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">The solution is simple. You need to extend the DefaultServlet and ProxyDirContext class of Tomcat and override the nonCacheable array. Below is the example code.</span><br />
<br />
<script src="https://gist.github.com/sarbajitc/7ffd2c1586c4a11becf6ec97848891dc.js"></script>
<br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Override the ProxyDirContext class.</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<script src="https://gist.github.com/sarbajitc/c7653e2df0fd0c4be3352705ebf6e6d1.js"></script>
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Now my web application structure looks like this-</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGs1evhbA4SKS9szHf36YGRUUftaFlomwmY7-SVFmu6UAZTyB1Qvatek3Zt7RO7HGwVOs1aHRXlFVbEzJY9yPkMaIBJSxnR8TGg8zJ-47hf1j2rjyHcKZYhS3TjSwatus9xtqArJqSuLFc/s1600/MyWebApp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGs1evhbA4SKS9szHf36YGRUUftaFlomwmY7-SVFmu6UAZTyB1Qvatek3Zt7RO7HGwVOs1aHRXlFVbEzJY9yPkMaIBJSxnR8TGg8zJ-47hf1j2rjyHcKZYhS3TjSwatus9xtqArJqSuLFc/s320/MyWebApp.jpg"></a></div><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Notice the xml directory which contains app.xml (assume this as dynamic resource). My JSP will load the app.xml using JavaScript (add the function as onload item). As the /xml/ URL pattern is added as nonCacheable, Tomcat will read the resource from file system (not from cache). So, we will always get the updated file content. Here is the script code -</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<script src="https://gist.github.com/sarbajitc/a8f79070a580cd0e9a734d971fa46a82.js"></script>
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Finally the web.xml for this app -</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span>
<script src="https://gist.github.com/sarbajitc/58f5bd9483169e642f11874b165bf0c3.js"></script>
<br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">This approach suffers a performance hit. Do not use this technique for static files.</span>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-8634009485913510932010-05-22T20:11:00.000+05:302010-05-22T20:11:29.910+05:30'Copy attachment from another email' feature in web based email clients<span class="Apple-style-span" style="font-size: x-large;"><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">T</span></span><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">his is purely an experience driven idea. Looks a bit crazy right now. But should be possible to implement this one. Let me brief about the feature I am looking for in web based email clients. To mention a few web based email clients- </span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Gmail</span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">, </span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Yahoomail</span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">, </span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Hotmail</span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"> etc which you use from your browser.</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">Lot of times we send some documents via email. These are called attachments. If you are using a web based email client you have to upload the document to the mail server to attach them in email. The uploading definitely takes time in a slow connection or for a big size attachment. The act gets annoying for me if the same attachment has to be sent in 3 or 4 different emails. Just think of a situation, where I have 3 mails from 3 different contacts requesting for my CV. The easiest way is to reply all of them in a single mail attaching the CV. But what if I don't want to disclose to any contact that I am sending my CV to others as well. I am sure you have been in such a situation many a times. What do you do then? You have to reply to each of them and while doing that you will end up by uploading the same document 3 times.</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">I genuinely feel something can be done here. Once the attachment is uploaded to the server for the 1st time, it is stored there. You can check your </span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">sent items</span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;"> or </span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">drafts </span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">folder. The mail containing the attachment will be there. So, only thing the mail server has to do is, show a '</span><i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">copy attachment from another email</span></i><span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', serif;">' option in new or reply mails. This will be a small but useful feature for web based email clients.</span>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0tag:blogger.com,1999:blog-7884492825228653821.post-77865414248038059472010-05-13T00:31:00.000+05:302010-05-13T00:31:56.052+05:30Starting up<span class="Apple-style-span" style="font-family: georgia;"><span class="Apple-style-span">T</span><span class="Apple-style-span">his is the first blog I'm creating and this is the first post. Feeling a bit nervy. Though its a great experience to write a blog. Initially I felt its not my stuff. But I follow other blogs and really like the whole idea of blogging. Still somehow it took a long time for me to start on this space. As they say, it is never late to start something new, I have started blogging.</span></span><br />
<span class="Apple-style-span" style="font-family: georgia;"><span class="Apple-style-span"><br />
</span></span><br />
<span class="Apple-style-span" style="font-family: georgia;"><span class="Apple-style-span">This blog will be about tech topics that I occurs to me. I'll share my new ideas and hacks. Sometimes I may try to explain some common technology concepts in my own way. I do hope that it becomes useful for somebody.</span></span>Sarbajit Chatterjeehttp://www.blogger.com/profile/07178321902250011434noreply@blogger.com0