<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Blogs de Nologin</title>
	<link>http://blogs.nologin.es/</link>
	<language>en</language>
	<description>Blogs de Nologin - http://blogs.nologin.es/</description>

<item>
	<title>We are the time we left: Novag Citrine under Debian GNU/Linux</title>
	<guid>http://blogs.nologin.es/neklaf/index.php?/archives/1-guid.html</guid>
	<link>http://blogs.nologin.es/neklaf/index.php?/archives/1-Novag-Citrine-under-Debian-GNULinux.html</link>
	<description>This is my first blog entry and I'd like to explain the steps that I followed to play chess with my Novag Citrine connected to my Debian GNU/Linux wheezy box.&lt;br /&gt;
The main reason to connect Citrine with the PC is able to store my games against the machine and this way I can analyze all movements and learn what I did wrong. Moreover you could choose other engines installed in your PC (GNU Chess 4/5, Crafty, Sjeng, ...) to play your games using citrine board as a simple interface, even play on &lt;a href=&quot;http://www.freechess.org/&quot; title=&quot;FICS&quot;&gt;Free Internet Chess Server&lt;/a&gt; with the board.&lt;br /&gt;
&lt;br /&gt;
Really it's not very difficult achieve that Citrine 'talk' with GNU/Linux, mainly because there is a user space driver developed by Maximiliano Pin &lt;a href=&quot;http://savannah.nongnu.org/projects/novagdrv/&quot; title=&quot;Novag Driver&quot;&gt;here&lt;/a&gt; that works very well, so in this entry I only want to collect instructions, step by step, followed in my system.&lt;br /&gt;
&lt;br /&gt;
1. Download novagdrv driver from &lt;a href=&quot;http://download.savannah.gnu.org/releases/novagdrv/novagdrv-0.3.tgz&quot; title=&quot;Novag Driver Sources&quot;&gt;here&lt;/a&gt;:&lt;br /&gt;
&lt;code&gt;$ wget http://download.savannah.gnu.org/releases/novagdrv/novagdrv-0.3.tgz&lt;br /&gt;
$ wget http://download.savannah.gnu.org/releases/novagdrv/novagdrv-0.3.tgz.sig&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
2. In order to verify program which we just downloaded, we must download the project keyring from &lt;a href=&quot;http://savannah.nongnu.org/project/memberlist-gpgkeys.php?group=novagdrv&amp;amp;download=1&quot; title=&quot;Novag Driver key ring&quot;&gt;here&lt;/a&gt;&lt;br /&gt;
File downloaded novagdrv-keyring.gpg&lt;br /&gt;
&lt;br /&gt;
3. Import project keyring (public keys from project members) into your public key store.&lt;br /&gt;
&lt;code&gt;$ gpg --import novagdrv-keyring.gpg&lt;br /&gt;
gpg: key 6002A0BC: public key &quot;Maximiliano Pin &quot; imported&lt;br /&gt;
gpg: Total number processed: 1&lt;br /&gt;
gpg:               imported: 1  (RSA: 1)&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
4. Verify downloaded file:&lt;br /&gt;
&lt;code&gt;$ gpg --verify novagdrv-0.3.tgz.sig novagdrv-0.3.tgz&lt;br /&gt;
gpg: Good signature from ...&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
5. After verify successfully this file we are going to decompress and compile the driver.&lt;br /&gt;
&lt;code&gt;$ tar xvzf novagdrv-0.3.tgz&lt;br /&gt;
$ cd novagdrv-0.3&lt;br /&gt;
$ make&lt;br /&gt;
g++ -g   -c -o main.o main.cc&lt;br /&gt;
g++ -g   -c -o novag.o novag.cc&lt;br /&gt;
g++ -g   -c -o serial.o serial.cc&lt;br /&gt;
g++ -g   -c -o game.o game.cccode&gt;&lt;br /&gt;
g++ -g   -c -o position.o position.cc&lt;br /&gt;
g++ -g -o novagdrv main.o novag.o serial.o game.o position.o&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
6. When we take a look in current directory we discover that novagdrv binary file has been created, and we move binary file into a /usr/local/bin, for example (any place inside our PATH environment variable):&lt;br /&gt;
&lt;code&gt;# mv novagdrv /usr/local/bin&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
7. The driver uses /dev/ttyS0 as default COM device, so if we connect Citrine to other device we previously must create a text file $HOME/.novagdrvrc with this content:&lt;br /&gt;
&lt;code&gt;device=/dev/ttyUSB0&lt;/code&gt;&lt;br /&gt;
We could use a USB to serial RS232 adapter if your computer hasn't a COM device.&lt;br /&gt;
&lt;br /&gt;
8. In order to test the driver you can connect Citrine and run the binary file and if all it's OK you'll see the movements made in the board written on the terminal.&lt;br /&gt;
&lt;code&gt;$ novagdrv &amp;amp;&lt;br /&gt;
e4-e5...&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Once driver works we need applications to analyze and play games. In the first place we are going to install ChessDB.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;CHESSDB&lt;/strong&gt;&lt;br /&gt;
First of all we download sources from &lt;a href=&quot;http://sourceforge.net/projects/chessdb/files/Main%20program/ChessDB-3.6.18/ChessDB-3.6.18.tar.gz/download title=&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
We should get MD5 and SHA1 fingerprints from its download page.&lt;br /&gt;
&lt;code&gt;MD5: 6aee2e4eca26576cbe6e63dc6b8d55db&lt;br /&gt;
SHA1: 456ff217ebdb0f6231a507ce737747c964f77f6e&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
1. Again we check downloaded file integrity.&lt;br /&gt;
&lt;code&gt;$ echo &quot;6aee2e4eca26576cbe6e63dc6b8d55db  ChessDB-3.6.18.tar.gz&quot; &gt; chessdb.md5&lt;br /&gt;
$ md5sum -c chessdb.md5&lt;br /&gt;
ChessDB-3.6.18.tar.gz: OK&lt;/code&gt;&lt;br /&gt;
Also we can check with SHA1 checksum, although obviously it's not necessary verify twice downloaded file.&lt;br /&gt;
&lt;code&gt;$ echo &quot;456ff217ebdb0f6231a507ce737747c964f77f6e  ChessDB-3.6.18.tar.gz&quot; &gt; chessdb.sha1&lt;br /&gt;
$ sha1sum -c chessdb.sha1&lt;br /&gt;
ChessDB-3.6.18.tar.gz: OK&lt;/code&gt;&lt;br /&gt;
2. Decompress and apply patch found with novag user space driver:&lt;br /&gt;
&lt;code&gt;$ tar xvzf ChessDB-3.6.18.tar.gz&lt;br /&gt;
$ patch -p1  ../../driver/novagdrv-0.3/ChessDB-3.6.18-novagdrv.patch&lt;br /&gt;
patching file Makefile.conf&lt;br /&gt;
patching file Makefile.mingw&lt;br /&gt;
patching file tcl/file.tcl&lt;br /&gt;
patching file tcl/lang/english-basic.tcl&lt;br /&gt;
patching file tcl/menus.tcl&lt;br /&gt;
patching file tcl/start.tcl&lt;br /&gt;
patching file tcl/tools/novagdrv.tcl&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Be sure that our system satisfies all software requirements to be able to compile sources files, in my case I had to install two packages:&lt;br /&gt;
&lt;code&gt;# aptitude install tcl8.5-dev tk8.5-dev&lt;/code&gt;&lt;br /&gt;
If you want to test your Tcl/Tk version you can run:&lt;br /&gt;
&lt;code&gt;$ tclsh&lt;br /&gt;
% info patchlevel&lt;br /&gt;
8.5.11&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
3. Edit configure script to add a new location for X11 libraries (I had forgotten to say that my Debian is 64 bits version):&lt;br /&gt;
&lt;code&gt;set x11Path {&lt;br /&gt;
        /usr/lib/x86_64-linux-gnu&lt;br /&gt;
        ...&lt;br /&gt;
}&lt;br /&gt;
$ ./configure&lt;br /&gt;
configure: Makefile configuration program for ChessDB&lt;br /&gt;
    Renaming &quot;Makefile&quot; to &quot;Makefile.bak&quot;&lt;br /&gt;
    Tcl/Tk version: 8.5&lt;br /&gt;
    Your operating system is: Linux 3.1.0-1-amd64&lt;br /&gt;
    Location of &quot;tcl.h&quot;: /usr/include/tcl8.5&lt;br /&gt;
    Location of &quot;tk.h&quot;: /usr/include/tcl8.5&lt;br /&gt;
    Location of Tcl 8.5 library: /usr/lib&lt;br /&gt;
    Location of Tk 8.5 library: /usr/lib&lt;br /&gt;
    Location of X11 library: /usr/lib/x86_64-linux-gnu&lt;br /&gt;
The Makefile configured for your system was written.&lt;br /&gt;
Now just type &quot;make&quot; to compile ChessDB.&lt;br /&gt;
# make install&lt;/code&gt;&lt;br /&gt;
And that's all to ChessDB Debian installation&lt;br /&gt;
&lt;code&gt;$ chessdb&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Tools -&gt; Novag Chess Computer.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;EBOARD&lt;/strong&gt;&lt;br /&gt;
Installation procedure to Eboard is very similar to the previous one so we're going to comment only some steps.&lt;br /&gt;
Download source code from &lt;a href=&quot;http://sourceforge.net/projects/eboard/files/eboard/1.1.1/eboard-1.1.1.tar.bz2/download&quot; title=&quot;Eboard download page&quot;&gt;here&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
1. Apply novag patch:&lt;br /&gt;
&lt;code&gt;$ tar xvjf eboard-1.1.1.tar.bz2&lt;br /&gt;
$ cd eboard-1.1.1&lt;br /&gt;
$ patch -p1  ../../driver/novagdrv-0.3/eboard-1.1.1-novagdrv.patch&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
2. Prepare to compilation process:&lt;br /&gt;
&lt;code&gt;$ ./configure&lt;br /&gt;
configuring eboard 1.1.1...&lt;br /&gt;
checking sanity of install... ok&lt;br /&gt;
testing C++ compiler...&lt;br /&gt;
  trying g++ ... it works&lt;br /&gt;
header verification:&lt;br /&gt;
  all headers found.&lt;br /&gt;
header verification:&lt;br /&gt;
  sys/audioio.h       : no&lt;br /&gt;
checking for IPPROTO_TCP in netinet/in.h... yes&lt;br /&gt;
checking for TCP_NODELAY in netinet/in.h... no&lt;br /&gt;
checking for SOL_TCP in netinet/in.h... no&lt;br /&gt;
checking for IPPROTO_TCP in netinet/tcp.h... no&lt;br /&gt;
checking for TCP_NODELAY in netinet/tcp.h... yes&lt;br /&gt;
checking for SOL_TCP in netinet/tcp.h... yes&lt;br /&gt;
  net options: netinet/tcp.h required, IPPROTO_TCP present.&lt;br /&gt;
looking for pkg-config... /usr/bin/pkg-config&lt;br /&gt;
looking for GTK+ version... 2.24.8, ok&lt;br /&gt;
looking for libpng... 1.2.46, ok&lt;br /&gt;
header verification:&lt;br /&gt;
  all headers found.&lt;br /&gt;
wrote config.h&lt;br /&gt;
wrote config.make&lt;br /&gt;
writing Makefile... ok&lt;br /&gt;
creating eboard-config... ok&lt;br /&gt;
creating eboard.spec... ok&lt;br /&gt;
&lt;br /&gt;
Summary:&lt;br /&gt;
eboard version 1.1.1&lt;br /&gt;
binaries  will be installed to    /usr/local/bin&lt;br /&gt;
man pages will be installed under /usr/local/man&lt;br /&gt;
datafiles will be installed to    /usr/local/share/eboard&lt;br /&gt;
NLS support: yes&lt;br /&gt;
done.&lt;br /&gt;
I found a problem compiling eboard patched sources, message printed out for g++ compiler was:&lt;br /&gt;
Invalid conversion from `const char*' to `char*'&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
3. My dirty solution at this point to fix the problem was to remove 'const' restriction in append method editing two files ntext.h and ntext.cc:&lt;br /&gt;
&lt;code&gt;$ vim ntext.h&lt;br /&gt;
//void append(const char *text, int len, int color);&lt;br /&gt;
void append(char *text, int len, int color);&lt;br /&gt;
$ vim ntext.cc&lt;br /&gt;
//void NText::append(const char *text, int len, int color) {&lt;br /&gt;
void NText::append(char *text, int len, int color) {&lt;br /&gt;
# make clean &amp;amp;&amp;amp; make install&lt;br /&gt;
$ eboard -novagport /dev/ttyUSB0&lt;/code&gt;&lt;br /&gt;
Now it's time to enjoy your Citrine!</description>
	<pubDate>dom, 29 ene 2012 17:05:31 +0000</pubDate>
	<author>nospam@example.com (Aitor Acedo)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Moving Forward to OpenJDK</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/54-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/54-Moving-Forward-to-OpenJDK.html</link>
	<description>&lt;p&gt;If you do not know, &lt;a href=&quot;http://robilad.livejournal.com/90792.html&quot;&gt;Oracle removed the DLJ license from its closed-source JDK implementation&lt;/a&gt; some months ago (Java7 was born without the license and Java6 removed it in U29). The &lt;a href=&quot;http://dlc.sun.com/dlj/DLJ-FAQ.html&quot;&gt;Operating System Distributor License for Java (DLJ)&lt;/a&gt; was a Sun initiative to facilitate the distribution of the JDK/JRE with operating systems based on OpenSolaris or Linux, in general that license let the distros to repackage, distribute and use the JDK.&lt;/p&gt;

&lt;p&gt;The reasons why Oracle removed that license were controversial. Some people thought that Oracle was definitely pushing forward the &lt;a href=&quot;http://openjdk.java.net&quot;&gt;OpenJDK&lt;/a&gt; adoption and others saw dark maneuvers in this change. For one reason or another the truth is Debian (and all the rest of linux distributions) is starting &lt;a href=&quot;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=646524&quot;&gt;the transition from &lt;em&gt;sun-java6-*&lt;/em&gt; to &lt;em&gt;openjdk-6-*&lt;/em&gt; packages&lt;/a&gt;. In my humble opinion OpenJDK is a very good virtual machine and both implementations, OpenJDK and Oracle closed-source JDK, have a lot in common (&lt;a href=&quot;http://blogs.oracle.com/darcy/entry/oscon_jdk_openjdk_state&quot;&gt;Joe Darcy talked about this issue last summer in the OSCON convention&lt;/a&gt;). As you already know the only big difference for end-users and developers is the Java Web Plugin, I wrote before an entry about this particular issue, commenting &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/38-Testing-the-IcedTea-Web-Java-Plugin.html&quot;&gt;the story and the problems of OpenJDK related to the web-plugin implementation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am on vacation right now and I was requested to encrypt my working laptop long time ago (because of security reasons and company procedures), so today I have re-installed my box. Now dual boot linux/windows is not allowed and, in general, the recommended linux setup was so different to the one I had that I have preferred to wipe it out. Actually this is the first time I have an only debian installation. As a collateral effect I have decided to move forward with java (I think it is the correct time cos I have been finishing all my current projects), &lt;em&gt;openjdk-6-jdk&lt;/em&gt; (with icedtea plugin of course) is now my default java implementation. I also think that it is a quite early to start with &lt;em&gt;openjdk-7-jdk&lt;/em&gt;, I will wait till U2 or U4 arrive to wheezy.&lt;/p&gt;

&lt;p&gt;I hope I do not need to install Oracle JDK back again, I really hate installing tar bundles in my Debian boxes. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;OpenJDK is here to stay!&lt;/p&gt;</description>
	<pubDate>sáb, 28 ene 2012 13:35:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Simple but Full Glassfish HA Using Debian</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/53-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/53-Simple-but-Full-Glassfish-HA-Using-Debian.html</link>
	<description>&lt;p&gt;During the past months I has been working in a project of which environment is mainly Windows (that is the reason of &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/52-Compiling-mod_proxy_html-in-Linux-and-Windows.html&quot;&gt;the previous entry about windows mod_proxy_html compilation&lt;/a&gt; &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt; ). Talking with the customer I realized that Windows 2008 provides a simple and out of the box &lt;a href=&quot;http://en.wikipedia.org/wiki/High_availability&quot;&gt;Load Balancing&lt;/a&gt; / &lt;a href=&quot;http://en.wikipedia.org/wiki/Load_balancing_(computing)&quot;&gt;High Availability&lt;/a&gt; mechanism for TCP/IP client/server infrastructures called &lt;a href=&quot;http://en.wikipedia.org/wiki/Network_Load_Balancing_Services&quot;&gt;Network Load Balancing Services (NLBS)&lt;/a&gt;. The customer complained about the lack of a similar solution in Linux (remember this customer is pro-windows). During my working life I have always used hardware load balancers in those situations, so I have never investigated how to implement a simple LB/HA solution which only deals with the OS. If you remember I presented an entry about  &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/32-High-Availability-in-Application-Servers.html&quot;&gt;HA in application servers and using an in-memory repository for session management&lt;/a&gt; some months ago. Today entry is less ambitious and more practical, I just want to setup a full Glassfish HA setup using only Debian (full means with no single point of failure).&lt;/p&gt;

&lt;h3&gt;The solution&lt;/h3&gt;

&lt;p&gt;Looking for information about the problem in the internet, I found lots of LB/HA sample solutions for TCP/IP enviroments in Linux, most of the times they involve two products (&lt;a href=&quot;http://www.howtoforge.com/setting-up-a-high-availability-load-balancer-with-haproxy-keepalived-on-debian-lenny&quot;&gt;see for example this entry&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://www.keepalived.org&quot;&gt;keepalived&lt;/a&gt;. This package provides a &lt;a href=&quot;http://en.wikipedia.org/wiki/Virtual_Router_Redundancy_Protocol&quot;&gt;VRRP (Virtual Router Redundancy Protocol)&lt;/a&gt; implementation stack and a versatile health checking system. So this software can commute a virtual IP between two or more hosts, the health checking system is used to test the servers and decide which one is the master and which one is the backup server. In short keepalived provides High Availability for an IP. In linux there are other more complicated HA techniques to get &lt;a href=&quot;http://en.wikipedia.org/wiki/High-availability_cluster&quot;&gt;a full and typical cluster &lt;/a&gt; (shared storage, typical virtual -eth0:1 style- IPs,...) but I really do not know much about it.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://haproxy.1wt.eu&quot;&gt;haproxy&lt;/a&gt;. A TCP/HTTP software load balancer that, obviously, adds the Load Balancing part to the solution. In internet examples haproxy is commonly used cos it is generic (it can distribute the load for any TCP/IP protocol: LDAP, HTTP, SMTP, IMAP,...).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in this entry a particular case is shown, a Java Application Server (Glassfish), and it is clear that there are better techniques for load balancing two Java Servers. For this reason my solution will use two other packages instead of &lt;em&gt;haproxy&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://tomcat.apache.org/connectors-doc/&quot;&gt;mod_jk&lt;/a&gt;. Finally I decided to use the Apache Tomcat Connector as my software load balancer. Glassfish is a very nice piece of software and it has several connectors that can be added to an Apache server to perform this function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_proxy_http.html&quot;&gt;mod_proxy_http&lt;/a&gt;: General HTTP reverse proxy module for Apache which supports load balancing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html&quot;&gt;mod_proxy_ajp&lt;/a&gt;: Similar to &lt;em&gt;mod_proxy_http&lt;/em&gt; but it manages &lt;a href=&quot;http://en.wikipedia.org/wiki/Apache_JServ_Protocol&quot;&gt;Apache JServ Protocol version 1.3 (AJP13)&lt;/a&gt; to talk with the App Server (Glassfish supports AJP13).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;mod_jk&lt;/strong&gt;: The chosen module also uses &lt;em&gt;AJP13&lt;/em&gt; to connect Apache and the App Server but while &lt;em&gt;mod_proxy_ajp&lt;/em&gt; is developed by the httpd group mod_jk is developed by tomcat guys. Usually &lt;a href=&quot;http://tomcat.apache.org/connectors-doc/reference/workers.html&quot;&gt;it is more configurable and better in terms of failure detection&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTTP Glassfish Load Balancer Plug-in&lt;/strong&gt;. This plugin is the official Oracle Glassfish load balancer module which is not available in the Open Source Edition. For this reason it was not selected for the demo.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://www.apache.org&quot;&gt;Apache&lt;/a&gt;. The famous HTTP web server which is necessary to install mod_jk inside it.&lt;/p&gt;&lt;/li&gt;


&lt;p&gt;So the solution is quite clear now. First of all keepalived gives a virtual IP which commutes between two Apache/mod_jk boxes (only one httpd server works actively, the other one acts as a backup). The package uses scripts to check if the web server is working fine. The httpd box which has the active IP receives the requests and apache/mod_jk pair redistributes them between two Glassfish servers. So the first layer provides only HA and the second layer LB/HA (take into account that the work in the first layer is lighter, the hard process is performed by the App Server).&lt;/p&gt;

&lt;p&gt;My demo environment is the simplest one. Two debian wheezy boxes were virtualized (KVM) inside my laptop: &lt;em&gt;debian1&lt;/em&gt; (192.168.122.21) and &lt;em&gt;debian2&lt;/em&gt; (192.168.122.22). The Linux distribution was installed with the minimal number of packages. Each box will have an Apache/mod_jk and a Glassfish server. Cos the Glassfish 3.1.1 is configured as a cluster &lt;em&gt;debian1&lt;/em&gt; runs the Domain Administrator Server (DAS) too. Replicated session is used (session is sent from one instance to the other when it is changed) but mod_jk uses sticky distribution (the first request is distributed but all the rest from the same source are sent to the same Glassfish server). The keepalived software manages a virtual IP (192.168.122.23) which is assigned to the master host (host with the highest priority). I present a little diagram of my demo solution.&lt;/p&gt;


&lt;div&gt;
&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/diagram.png&quot; alt=&quot;Glassfish HA Demo Solution&quot; /&gt;
&lt;/div&gt;

&lt;h3&gt;OpenJDK Installation&lt;/h3&gt;

&lt;p&gt;A Debian solution deserves &lt;a href=&quot;http://openjdk.java.net/&quot;&gt;OpenJDK&lt;/a&gt; (the open source JVM):&lt;/p&gt;

&lt;pre&gt;
# apt-get install openjdk-6-jdk
&lt;/pre&gt;

&lt;p&gt;Glassfish version 3.1.1 is going to be used and it is known that there are problems with old versions of JavaSE6. That was the reason to choose wheezy (OpenJDK 6b24) instead of squezze (6b18). JDK was installed in both machines.&lt;/p&gt;

&lt;h3&gt;Glassfish Installation&lt;/h3&gt;

&lt;p&gt;The Glassfish installation, although it is not very complicated, requires several steps (I have followed &lt;a href=&quot;http://blog.usul.org/java-ee-6-glassfish-3-1-1-cluster-with-load-balancer-installation/&quot;&gt;this guide&lt;/a&gt;).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I prefer to run glassfish with its own user. So first of all a system user and group were created.&lt;/p&gt;

&lt;pre&gt;
# groupadd glassfish
# useradd -c &quot;Glassfish User&quot; -d /opt/glassfish -g glassfish -m -s /bin/bash glassfish
# passwd glassfish
&lt;/pre&gt;

&lt;p&gt;This step was done in both machines.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;First the linux distribution for Glassfish OpenSource Edition 3.1.1 was downloaded and installed.&lt;/p&gt;

&lt;pre&gt;
$ wget http://download.java.net/glassfish/3.1.1/release/glassfish-3.1.1-unix.sh
$ bash glassfish-3.1.1-unix.sh
&lt;/pre&gt;

&lt;p&gt;Please choose to only install the software (do not configure it). I do not like to put installation screens (I am sure that all of you are intelligent enough to install it). I remark only two questions, where to install it (&lt;em&gt;/opt/glassfish/glassfish3.1.1&lt;/em&gt;) and what java to use (&lt;em&gt;/usr/lib/jvm/java-6-openjdk-amd64&lt;/em&gt;). I completed the installation in both machines.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;A domain (&lt;em&gt;domain1&lt;/em&gt;) was then created in &lt;em&gt;debian1&lt;/em&gt; (all &lt;em&gt;asadmin&lt;/em&gt; commands were launch from &lt;em&gt;/opt/glassfish/glassfish3.1.1/bin&lt;/em&gt;).&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin create-domain --savemasterpassword=true --savelogin=true domain1
Enter admin user name [Enter to accept default &quot;admin&quot; / no password]&gt; admin
Enter the admin password [Enter to accept default of no password]&gt; 
Enter the admin password again&gt; 
Enter the master password [Enter to accept default password &quot;changeit&quot;]&gt; 
Enter the master password again&gt; 
Using default port 4848 for Admin.
Using default port 8080 for HTTP Instance.
Using default port 7676 for JMS.
Using default port 3700 for IIOP.
Using default port 8181 for HTTP_SSL.
Using default port 3820 for IIOP_SSL.
Using default port 3920 for IIOP_MUTUALAUTH.
Using default port 8686 for JMX_ADMIN.
Using default port 6666 for OSGI_SHELL.
Using default port 9009 for JAVA_DEBUGGER.
Distinguished Name of the self-signed X.509 Server Certificate is:
[CN=debian1.demo.kvm,OU=GlassFish,O=Oracle Corporation,L=Santa Clara,ST=California,C=US]
Distinguished Name of the self-signed X.509 Server Certificate is:
[CN=debian1.demo.kvm-instance,OU=GlassFish,O=Oracle Corporation,L=Santa Clara,ST=California,C=US]
No domain initializers found, bypassing customization step
Domain domain1 created.
Domain domain1 admin port is 4848.
Domain domain1 admin user is &quot;admin&quot;.
Login information relevant to admin user name [admin]
for this domain [domain1] stored at
[/opt/glassfish/.asadminpass] successfully.
Make sure that this file remains protected.
Information stored in this file will be used by
asadmin commands to manage this domain.
Command create-domain executed successfully.
&lt;/pre&gt;

&lt;p&gt;In v3 there are no profile types, all domains are equal. After creation &lt;em&gt;domain1&lt;/em&gt; was secured (console uses https instead of plain communication).&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin enable-secure-admin 
Command enable-secure-admin executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;As Glassfish is going to use two working instances inside a cluster I usually delete listeners and servers which are not used by the web console.&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin delete-http-listener http-listener-1
Command delete-http-listener executed successfully.

$ ./asadmin delete-http-listener http-listener-2
Command delete-http-listener executed successfully.

$ ./asadmin delete-virtual-server server
Command delete-virtual-server executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Now Glassfish v3 uses SSH to communicate with remote instances. So &lt;em&gt;debian2&lt;/em&gt; has to be added to the domain (public key is exchanged for future commands):&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin setup-ssh --generatekey=true debian2.demo.kvm
Enter SSH password for glassfish@debian2.demo.kvm&gt; 
Created directory /opt/glassfish/.ssh
/usr/bin/ssh-keygen successfully generated the identification /opt/glassfish/.ssh/id_rsa
Copied keyfile /opt/glassfish/.ssh/id_rsa.pub to glassfish@debian2.demo.kvm
Successfully connected to glassfish@debian2.demo.kvm using keyfile /opt/glassfish/.ssh/id_rsa
Command setup-ssh executed successfully.
&lt;/pre&gt;

&lt;p&gt;And the new node (&lt;em&gt;debian2&lt;/em&gt;) was installed:&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin install-node debian2.demo.kvm
Created installation zip /opt/glassfish/glassfish3.1.1/bin/glassfish298897142999171245.zip
Successfully connected to glassfish@debian2.demo.kvm using keyfile /opt/glassfish/.ssh/id_rsa
GlassFish is already installed on debian2.demo.kvm under /opt/glassfish/glassfish3.1.1.
Command install-node executed successfully.
&lt;/pre&gt;

&lt;p&gt;Cos glassfish was installed in both machines this command does nothing.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;As I said the remote instances are managed via SSH, for this reason there is a new concept called SSH node. These nodes are very different from previous &lt;em&gt;node-agents&lt;/em&gt;, they are not a Java daemon at all, they are just remote hosts which run instances of the domain (so they are a concept and not a real daemon or process). Two nodes, called &lt;em&gt;debian1-ssh&lt;/em&gt; and &lt;em&gt;debian2-ssh&lt;/em&gt;, were created.&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin create-node-ssh --nodehost localhost debian1-ssh
Command create-node-ssh executed successfully.

$ ./asadmin create-node-ssh --nodehost debian2.demo.kvm debian2-ssh
Command create-node-ssh executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Then the cluster (&lt;em&gt;cluster1&lt;/em&gt;) and the two instances (&lt;em&gt;debian1-gf&lt;/em&gt; and &lt;em&gt;debian2-gf&lt;/em&gt;) were also created (each instance was registered in the previous nodes and inside the cluster):&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin create-cluster --systemproperties HTTP_SSL_LISTENER_PORT=8181:HTTP_LISTENER_PORT=8080 cluster1
Command create-cluster executed successfully.

$ ./asadmin create-instance --cluster cluster1 --node debian1-ssh debian1-gf
Command _create-instance-filesystem executed successfully.
Port Assignments for server instance debian1-gf: 
JMX_SYSTEM_CONNECTOR_PORT=18686
JMS_PROVIDER_PORT=17676
ASADMIN_LISTENER_PORT=14848
HTTP_LISTENER_PORT=8080
JAVA_DEBUGGER_PORT=19009
IIOP_SSL_LISTENER_PORT=13820
IIOP_LISTENER_PORT=13700
OSGI_SHELL_TELNET_PORT=16666
HTTP_SSL_LISTENER_PORT=8181
IIOP_SSL_MUTUALAUTH_PORT=13920
The instance, debian1-gf, was created on host localhost
Command create-instance executed successfully.

$ ./asadmin create-instance --cluster cluster1 --node debian2-ssh debian2-gf
Command _create-instance-filesystem executed successfully.
Port Assignments for server instance debian2-gf: 
JMX_SYSTEM_CONNECTOR_PORT=18686
JMS_PROVIDER_PORT=17676
ASADMIN_LISTENER_PORT=14848
HTTP_LISTENER_PORT=8080
JAVA_DEBUGGER_PORT=19009
IIOP_SSL_LISTENER_PORT=13820
IIOP_LISTENER_PORT=13700
OSGI_SHELL_TELNET_PORT=16666
HTTP_SSL_LISTENER_PORT=8181
IIOP_SSL_MUTUALAUTH_PORT=13920
The instance, debian2-gf, was created on host debian2.demo.kvm
Command create-instance executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Once the instances were running (&lt;em&gt;start-local-instance&lt;/em&gt; executed in each node), a new &lt;em&gt;http-listener&lt;/em&gt; was registered to listen for the &lt;em&gt;AJP13&lt;/em&gt; protocol (this port will be used later inside mod_jk workers configuration). &lt;a href=&quot;http://weblogs.java.net/blog/amyroh/archive/2009/06/running_glassfi.html&quot;&gt;More details about this configuration in this link&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin create-http-listener --listenerport 8009 --listeneraddress 0.0.0.0 --defaultvs server --target cluster1 jk-connector
Command create-http-listener executed successfully.

$ ./asadmin set configs.config.cluster1-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true
debian1-gf:
configs.config.cluster1-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

debian2-gf:
configs.config.cluster1-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

configs.config.cluster1-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true
Command set executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt; In order to set the &lt;em&gt;jvmRoute&lt;/em&gt; some java and system properties were added (mod_jk uses this property to perform sticky load balancing, in the first request the value of the &lt;em&gt;jvmRoute&lt;/em&gt; is appended to the &lt;em&gt;JSESSIONID&lt;/em&gt; cookie and the module will use this value to redirect the following requests to the same server). &lt;/p&gt;

&lt;pre&gt;
$ ./asadmin create-jvm-options --target cluster1 &quot;-DjvmRoute=\${AJP_INSTANCE_NAME}&quot;
debian1-gf:
Created 1 option(s)

debian2-gf:
Created 1 option(s)

Created 1 option(s)
Command create-jvm-options executed successfully.

$ ./asadmin create-system-properties --target debian1-gf AJP_INSTANCE_NAME=debian1
Command create-system-properties executed successfully.

$ ./asadmin create-system-properties --target debian2-gf AJP_INSTANCE_NAME=debian2
Command create-system-properties executed successfully.
&lt;/pre&gt;

&lt;p&gt;In glassfish all instances under a cluster share the same configuration, for this reason different values cannot be set to the same java property in each instance. So the trick is to set a different system property (these props can be defined by instance) and assign the java property referencing the system prop.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally the famous &lt;em&gt;clusterjsp&lt;/em&gt; was deloyed with high availability enabled (by default glassfish uses session replication). It seems that &lt;em&gt;clusterjsp&lt;/em&gt; application is not part of the glassfish 3.1.1 distribution (at least in the linux no multi-language bundle I used), so I created this simple &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/clusterjsp.war&quot;&gt;clusterjsp.war&lt;/a&gt; (from a previous ear I have from v2 bundle).&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin deploy --availabilityenabled=true --target cluster1 ~/clusterjsp.war 
Application deployed with name clusterjsp.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;At that time both instances could only be managed with &lt;em&gt;*-local-instance&lt;/em&gt; commands (launching the commands from its own host). I realized that that was because the master password (password for JKS keystores) was not locally saved (although I swear that I had added &lt;em&gt;savemasterpassword&lt;/em&gt; in the domain creation command). To solve that I changed the password in both hosts (I put the same old password cos I just wanted it to be saved in the &lt;em&gt;~/.asadmintruststore&lt;/em&gt; file):&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin change-master-password --savemasterpassword true debian1-ssh
Enter the old master password&gt;
Enter the new master password&gt; 
Enter the new master password again&gt; 
Command change-master-password executed successfully.

$ ./asadmin change-master-password --savemasterpassword true debian2-ssh
Enter the old master password&gt;
Enter the new master password&gt; 
Enter the new master password again&gt; 
Command change-master-password executed successfully.
&lt;/pre&gt;

&lt;p&gt;Finally to not use any password in commands at &lt;em&gt;debian2&lt;/em&gt; machine I saved the user and password information as well in this second host (the user and password is saved in &lt;em&gt;~/.asadminpass&lt;/em&gt; file):&lt;/p&gt;

&lt;pre&gt;
$ ./asadmin --host debian1.demo.kvm --port 4848 login
Enter admin user name [default: admin]&gt; admin
Enter admin password&gt; 
Login information relevant to admin user name [admin]
for host [debian1.demo.kvm] and admin port [4848] stored at
[/opt/glassfish/.asadminpass] successfully.
Make sure that this file remains protected.
Information stored in this file will be used by
asadmin commands to manage the associated domain.
Command login executed successfully.
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally I created a simple startup script which needs to be placed in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/glassfish-inst&quot;&gt;/etc/init.d/glassfish-inst&lt;/a&gt;. This script launches a single instance (DAS instance is not needed to be started at boot time, so only the cluster instance will be started in each machine) and it needs asadmin command to not prompt for anything (see the previous step to save the passwords). After the file is correctly placed and the needed variables changed it must be registered in debian.&lt;/p&gt;

&lt;pre&gt;
# chmod 755 /etc/init.d/glassfish-inst
# update-rc.d glassfish-inst defaults
update-rc.d: using dependency based boot sequencing
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So now we have a clustered (session replicated) application. Besides each cluster instance listens for &lt;em&gt;AJP13&lt;/em&gt; protocol in port 8009. Everything is ready for Apache/mod_jk configuration. In this demo I chose Glassfish but the main concepts (maybe changing some pieces) are the same for any application server. And as a final comment for this part, you already know that I personally recommend not to replicate sessions, this process has a big impact if the sessions are too many, too big and/or too volatile (but also be aware that in that case a server lost means a session lost).&lt;/p&gt;


&lt;h3&gt;Apache/mod_jk Installation&lt;/h3&gt;

&lt;p&gt;Both packages are part of the main Debian repository, so installing them is just a command like this:&lt;/p&gt;

&lt;pre&gt;
# apt-get install apache2 libapache2-mod-jk
&lt;/pre&gt;

&lt;p&gt;Configuration for JK module is placed in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/jk.conf&quot;&gt;/etc/apache2/mods-available/jk.conf&lt;/a&gt;. I just used the debian default but commenting &lt;em&gt;/jk-status&lt;/em&gt; and &lt;em&gt;/jk-manager&lt;/em&gt; locations (I decided to define them inside the site). This config file points to &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/workers.properties&quot;&gt;/etc/libapache2-mod-jk/workers.properties&lt;/a&gt; as the workers configuration file. The important lines in the second file are the following:&lt;/p&gt;

&lt;pre&gt;
worker.list=loadbalancer,jk-status
worker.debian1.port=8009
worker.debian1.host=debian1.demo.kvm
worker.debian1.type=ajp13
worker.debian1.lbfactor=1
worker.debian2.port=8009
worker.debian2.host=debian2.demo.kvm
worker.debian2.type=ajp13
worker.debian2.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=debian1,debian2
worker.loadbalancer.sticky_session=1
worker.jk-status.type=status
&lt;/pre&gt;

&lt;p&gt;There are two workers defined, &lt;em&gt;debian1&lt;/em&gt; and &lt;em&gt;debian2&lt;/em&gt; (the name of the worker has to be the same defined in the &lt;em&gt;jvmRoute&lt;/em&gt; property), using &lt;em&gt;AJP13&lt;/em&gt; protocol on both virtual hosts with port 8009. Another worker &lt;em&gt;loadbalancer&lt;/em&gt; is used to distribute requests between the two previously defined workers. The distribution is configured sticky. Finally the status worker (a page that informs about worker status) is defined with the name &lt;em&gt;jk-status&lt;/em&gt;. No special tuning (timeouts and more) was done.&lt;/p&gt;

&lt;p&gt;Once mod_jk is configured the default site defined in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/default&quot;&gt;/etc/apache2/sites-available/default&lt;/a&gt; adds two new locations to proxy the &lt;em&gt;clusterjsp&lt;/em&gt; app and the status worker:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;Location /jk-status&amp;gt;
        # Inside Location we can omit the URL in JkMount
        JkMount jk-status
        #Order deny,allow
        #Deny from all
        #Allow from 127.0.0.1
    &amp;lt;/Location&amp;gt;

    # mount clusterjsp
    JkMount /clusterjsp loadbalancer
    JkMount /clusterjsp/* loadbalancer
&lt;/pre&gt;

&lt;p&gt;Finally the mod_jk is enabled and apache2 restarted:&lt;/p&gt;

&lt;pre&gt;
# a2enmod jk
# /etc/init.d/apache2 restart
&lt;/pre&gt;

&lt;p&gt;These steps have to be done in both hosts (&lt;em&gt;debian1&lt;/em&gt; and &lt;em&gt;debian2&lt;/em&gt;). And, at this moment, both Apache servers are balancing the two glassfish clustered instances. As mod_jk detects application server failures the LB/HA of glassfish layer is achieved.&lt;/p&gt;

&lt;h3&gt;Keepalived Installation&lt;/h3&gt;

&lt;p&gt;The final package, keepalived, is installed following the debian way:&lt;/p&gt;

&lt;pre&gt;
# apt-get install keepalived
&lt;/pre&gt;

&lt;p&gt;This software has just a little configuration located in &lt;em&gt;/etc/keepalived/keepalived.conf&lt;/em&gt;. This file just contains the following:&lt;/p&gt;

&lt;pre&gt;
vrrp_script chk_http_port {   # Requires keepalived-1.1.13
  script &quot;wget -q -T 1.0 -t 2 --delete-after -O /tmp/test.wget http://localhost:80/index.html&quot;
  interval 5            # check every 5 seconds
  weight 2              # add 2 points of prio if OK
}

vrrp_instance VI_1 {
  interface eth0
  state MASTER          # MASTER debian1, BACKUP debian2
  virtual_router_id 51  # same id in both hosts
  priority 101          # 101 on master, 100 on backup
  virtual_ipaddress {
    192.168.122.23      # virtual IP
  }
  track_script {
    chk_http_port
  }
}
&lt;/pre&gt;

&lt;p&gt;A VRRP instance is defined in eth0 interface. This instance manages the IP 192.168.122.23. Host &lt;em&gt;debian1&lt;/em&gt; is declared MASTER with an initial priority of 101, debian2 is the backup instance with a priority of 100. A script &lt;em&gt;chk_http_port&lt;/em&gt; is executed in both hosts and it assigns two points more. This way if &lt;em&gt;debian1&lt;/em&gt; Apache fails it only has 101 points while debian2 has 102 (100 + 2 added by the check) and the backup server is transitioned to master (the virtual IP moves from &lt;em&gt;debian1&lt;/em&gt; to &lt;em&gt;debian2&lt;/em&gt;). As soon as &lt;em&gt;debian1&lt;/em&gt; Apache runs again (103 points are now assigned to &lt;em&gt;debian1&lt;/em&gt;) this host become the master again. If whole &lt;em&gt;debian1&lt;/em&gt; fails (a hardware failure for example), the multicast packets, which are supposed to be sent by the master server, stop being received by the backup server and therefore its status will be risen to master (check VRRP protocol specification in &lt;a href=&quot;http://www.ietf.org/rfc/rfc2338.txt&quot;&gt;RFC 2338&lt;/a&gt;). Take in mind that keepalived does not use typical virtual IPs (eth0:1 and so on), it does HA using VRRP which manages multicast and ARP. VRRP only works inside the same network (both machines have to be inside the same net). With keepalived the first layer is configured in HA (only one apache is working, the other is just awaiting as a backup server).&lt;/p&gt;

&lt;p&gt;The checking script is very simple, using &lt;a href=&quot;http://www.gnu.org/software/wget/&quot;&gt;wget&lt;/a&gt; a test page from the Apache is retrieved (timeout of one second but with two tries). If wget returns 0, the page was got successfully, in case of any other return code, the page was not returned and the check fails. Never test a glassfish page (doing that you are mixing layers and the results can be very weird). Here you have &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/keepalived.conf.debian1&quot;&gt;master configuration for debian1&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/keepalived.conf.debian2&quot;&gt;backup for debian2&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;As a conclusion I am going to present a video that shows my demo installation. By default &lt;em&gt;debian1&lt;/em&gt; is the master vrrp server and if &lt;em&gt;clusterjsp&lt;/em&gt; page is requested, its apache/mod_jk redirects to any of the glassfish servers (&lt;em&gt;debian1&lt;/em&gt; in the video). Cos the module is configured sticky I can set some attributes in the session and &lt;em&gt;debian1&lt;/em&gt; is always my working glassfish. Now &lt;em&gt;debian1-gf&lt;/em&gt; glassfish instance is stopped and &lt;em&gt;clusterjsp&lt;/em&gt; is redirected to &lt;em&gt;debian2&lt;/em&gt; (now &lt;em&gt;debian1&lt;/em&gt; apache and &lt;em&gt;debian2&lt;/em&gt; glassfish are working). But then &lt;em&gt;debian1&lt;/em&gt; apache is stopped, &lt;em&gt;debian2&lt;/em&gt; transitions to master state (a tail for &lt;em&gt;/var/log/messages&lt;/em&gt; displays keepalived information) and application is still working (now &lt;em&gt;debian2&lt;/em&gt; is doing all the job, apache and glassfish). After restarting &lt;em&gt;debian1&lt;/em&gt; Apache, this host becomes again the master. Finally the virtual machine of &lt;em&gt;debian1&lt;/em&gt; is suddenly stopped, &lt;em&gt;debian2&lt;/em&gt; transitions again to master. Because &lt;em&gt;clusterjsp&lt;/em&gt; application was deployed with session replication the session is never lost in the video.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SimplebutFullGlassfishHAUsingDebian/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;For me it is clear that linux has also a good and simple LB/HA mechanism, keepalived is usually more than enough in typical TCP/IP client/server solutions. With this configuration a virtual IP that commutes between nodes is setup (only HA at the first layer). This layer consists in a software load balancer and, as I commented, usually generic haproxy is used. Nevertheless apache/mod_jk is a much proper solution for AJP13 capable Java Application Servers. The second layer (glassfish in this case) has LB/HA features, cos the load balancer (mod_jk) distributes the load between the two instances at the same time it checks the server status. So the second layer processes requests in parallel. The problem for my customer was that their linux boxes were RedHat6 and &lt;a href=&quot;http://www.8layer8.com/?p=360&quot;&gt;keepalived is not distributed by default in the distro&lt;/a&gt; (it seems that cluster extra software is needed in order to get this package). &lt;/p&gt;

&lt;p&gt;That's why Debian rules! &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;</description>
	<pubDate>sáb, 21 ene 2012 12:27:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Compiling mod_proxy_html in Linux and Windows</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/52-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/52-Compiling-mod_proxy_html-in-Linux-and-Windows.html</link>
	<description>&lt;p&gt;These weeks I am finishing a long project which uses &lt;a href=&quot;http://httpd.apache.org&quot;&gt;Apache&lt;/a&gt; (more precisely &lt;a href=&quot;http://www.oracle.com/technetwork/middleware/ias/index-091236.html&quot;&gt;OHS / Oracle HTTP Server&lt;/a&gt;) in a &lt;a href=&quot;http://en.wikipedia.org/wiki/Reverse_proxy&quot;&gt;reverse proxy configuration&lt;/a&gt;. Usually default apache &lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_proxy.html&quot;&gt;mod_proxy&lt;/a&gt; modules are more than enough to configure a good reverse proxy but, sometimes, a special module called &lt;a href=&quot;http://apache.webthing.com/mod_proxy_html/&quot;&gt;mod_proxy_html&lt;/a&gt; is necessary. When the pages served by the backend server manage absolute links (the ones that start by &lt;em&gt;/&lt;/em&gt; or by the complete &lt;em&gt;protocol://host:port&lt;/em&gt; uri) typical &lt;em&gt;mod_proxy&lt;/em&gt; configuration falls short, because those mods never parse or change the HTML code (just the headers). Obviously &lt;em&gt;mod_proxy_html&lt;/em&gt; does exactly that, parsing and replacing the conflicting links in the html page. It is important to remark that this behavior is not recommended, take in mind that the cost of parsing every HTML is not small.&lt;/p&gt;

&lt;p&gt;My initial idea was only using the module in those applications which were problematic, there were no other solution (like specific application server plugin or a smart proxy uri that fits with the final backend server location) and the customer did not want to modify. But the problem is that &lt;em&gt;mod_proxy_html&lt;/em&gt; is not distributed with the default Apache source bundle (it seems that &lt;a href=&quot;http://bahumbug.wordpress.com/2011/10/28/modules-move-home/&quot;&gt;it will be integrated in forthcoming Apache 2.4 cos it was donated by its creator to the foundation&lt;/a&gt; but currently it should be installed separately). All linux distros distribute the module as a separate package (because, as I explained, it is quite important in some reverse proxy configurations) but this is not the case of OHS. So my only chance was compiling the module by myself.&lt;/p&gt;

&lt;p&gt;Although custom modules are not supported, OHS provides the apxs command to add them to the server at customers own risk and I desperately needed a plan B just in case an app was problematic. But the other painful point was that my OHS server is running in a Windows 2008 host. Cos I have no experience at all compiling in Windows I decided to start smoothly: compiling &lt;em&gt;mod_html_proxy&lt;/em&gt; in an Apache/debian installation, then in a Linux OHS and finally in a Windows OHS. I compiled 3.0.1 version of the module and not current 3.1.2 for several reasons: new version uses two modules (I did not want to compile two times), my first try with 3.1.2 did not work as expected (I spent short time with the problem) and it is the current version in debian (you already know my total confidence in this distribution).&lt;/p&gt;

&lt;h3&gt;Adding mod_proxy_html to Debian/Apache&lt;/h3&gt;

&lt;p&gt;Although debian has a &lt;a href=&quot;http://packages.debian.org/squeeze/libapache2-mod-proxy-html&quot;&gt;libapache2-mod-proxy-html&lt;/a&gt; package I compiled it by myself downloading the debian source package (remember I was training to compile it in OHS later). In order to do that I needed first some development packages: apache and &lt;a href=&quot;http://xmlsoft.org&quot;&gt;libxml&lt;/a&gt; (this module uses &lt;em&gt;libxml&lt;/em&gt; to parse the HTML pages and perform the replacements):&lt;/p&gt;

&lt;pre&gt;
# apt-get install apache2-prefork-dev libxml2-dev
&lt;/pre&gt;

&lt;p&gt;Then the module was compiled and installed:&lt;/p&gt;

&lt;pre&gt;
# apxs2 -c -I /usr/include/libxml2 -I . -i mod_proxy_html.c 
/usr/share/apr-1.0/build/libtool --silent --mode=compile --tag=disable-static x86_64-linux-gnu-gcc -prefer-pic -DLINUX=2 -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -D_REENTRANT -I/usr/include/apr-1.0 -I/usr/include/openssl -I/usr/include/xmltok -pthread     -I/usr/include/apache2  -I/usr/include/apr-1.0   -I/usr/include/apr-1.0  -I/usr/include/libxml2 -I.  -c -o mod_proxy_html.lo mod_proxy_html.c &amp;amp;&amp;amp; touch mod_proxy_html.slo
/usr/share/apr-1.0/build/libtool --silent --mode=link --tag=disable-static x86_64-linux-gnu-gcc -o mod_proxy_html.la  -rpath /usr/lib/apache2/modules -module -avoid-version    mod_proxy_html.lo
/usr/share/apache2/build/instdso.sh SH_LIBTOOL='/usr/share/apr-1.0/build/libtool' mod_proxy_html.la /usr/lib/apache2/modules
/usr/share/apr-1.0/build/libtool --mode=install cp mod_proxy_html.la /usr/lib/apache2/modules/
libtool: install: cp .libs/mod_proxy_html.so /usr/lib/apache2/modules/mod_proxy_html.so
libtool: install: cp .libs/mod_proxy_html.lai /usr/lib/apache2/modules/mod_proxy_html.la
libtool: finish: PATH=&quot;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin&quot; ldconfig -n /usr/lib/apache2/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/lib/apache2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 644 /usr/lib/apache2/modules/mod_proxy_html.so
&lt;/pre&gt;

&lt;p&gt;Some configuration files were created to include the custom module in &lt;a href=&quot;http://www.ducea.com/2006/05/30/managing-apache2-modules-the-debian-way/&quot;&gt;a2enmod/a2dismod debian commands&lt;/a&gt;. So I included the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/proxy_html.load&quot;&gt;/etc/apache2/mods-available/proxy_html.load&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/proxy_html.conf&quot;&gt;/etc/apache2/mods-available/proxy_html.conf&lt;/a&gt; (load the module and default configuration). Once the module was integrated in debian scripts I enabled all the needed ones to perform reverse proxying:&lt;/p&gt;

&lt;pre&gt;
# a2enmod proxy proxy_connect proxy_http proxy_ftp proxy_html
&lt;/pre&gt;

&lt;p&gt;Finally I setup a Location directive which performed a reverse proxy from &lt;em&gt;/proxy-test/&lt;/em&gt; to a Tomcat running in my laptop (I added it to the default site, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/000-default&quot;&gt;/etc/apache2/sites-enabled/000-default&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;
&amp;lt;Location /proxy-test/&amp;gt;
    ProxyPass http://magneto:8080/
    ProxyPassReverse http://magneto:8080/
    SetOutputFilter proxy-html
    ProxyHTMLURLMap http://magneto:8080/ /proxy-test/
    ProxyHTMLURLMap / /proxy-test/
&amp;lt;/Location&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The location proxifies (pass and reverse) all requests from the &lt;em&gt;/proxy-test/&lt;/em&gt; uri to my tomcat installation but with a filter, the &lt;em&gt;proxy-html&lt;/em&gt; one. This filter searches and replaces the two annoying absolute links with our location uri (this is the goal of the &lt;em&gt;ProxyHTMLURLMap&lt;/em&gt; directive). If you need more examples about the configuration please &lt;a href=&quot;http://wiki.uniformserver.com/index.php/Reverse_Proxy_Server:&lt;u&gt;mod_proxy_html#Example_5&lt;/u&gt;-_mod_proxy_html&quot;&gt;&lt;u&gt;mod_proxy_html#Example_5&lt;/u&gt;-_mod_proxy_html&quot;&gt;&lt;u&gt;mod_proxy_html#Example_5&lt;/u&gt;-_mod_proxy_html&quot;&gt;&lt;u&gt;mod_proxy_html#Example_5&lt;/u&gt;-_mod_proxy_html&quot;&gt;check this page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that was all! The Apache worked as a reverse proxy perfectly. I also prepared &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/test.html&quot;&gt;a simple html test page with some conflicting links to test&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;Adding mod_proxy_html to Linux/OHS&lt;/h3&gt;

&lt;p&gt;The second step was doing the same but with OHS in a Linux box. I installed a new Linux KVM virtual box, OHS 11.1.1.5.0 binaries and perform the same actions. This time &lt;em&gt;oracle&lt;/em&gt; system user is used for compiling and installing, and some parameters are different (take into account that I am using the &lt;em&gt;libxml&lt;/em&gt; provided by OHS and not the system one):&lt;/p&gt;

&lt;pre&gt;
$ export ORACLE_HOME=/opt/oracle/middleware/Oracle_WT1
$ export ORACLE_INSTANCE=$ORACLE_HOME/instances/instance1
$ export CONFIG_FILE_PATH=$ORACLE_INSTANCE/config/OHS/ohs1
$ export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/ohs/lib:$LD_LIBRARY_PATH

$ /opt/oracle/middleware/Oracle_WT1/ohs/bin/apxs -I /usr/include/libxml2  -I . -L/opt/oracle/middleware/Oracle_WT1/ohs/lib -lxml2 -c -o mod_proxy_html.so -i mod_proxy_html.c
/opt/oracle/middleware/Oracle_WT1/ohs/build/libtool --tag=CC --mode=compile cc -O    -DNO_RC2 -DNO_RC5 -DNO_IDEA -DBSAFE -fPIC  -DLINUX=260 -DMOD_SSL=206104 -DMOD_PERL -DUSE_PERL_SSI -I/include -DEAPI  -D_LARGEFILE64_SOURCE -DUSE_EXPAT -I../lib/expat-lite -I/opt/oracle/middleware/Oracle_WT1/ohs/include  -I/opt/oracle/middleware/Oracle_WT1/ohs/include   -I/opt/oracle/middleware/Oracle_WT1/ohs/include  -I/usr/include/libxml2 -I.  -c -o mod_proxy_html.lo mod_proxy_html.c &amp;amp;&amp;amp; touch mod_proxy_html.slo
 cc -O -DNO_RC2 -DNO_RC5 -DNO_IDEA -DBSAFE -fPIC -DLINUX=260 -DMOD_SSL=206104 -DMOD_PERL -DUSE_PERL_SSI -I/include -DEAPI -D_LARGEFILE64_SOURCE -DUSE_EXPAT -I../lib/expat-lite -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/usr/include/libxml2 -I. -c mod_proxy_html.c  -fPIC -DPIC -o .libs/mod_proxy_html.o
 cc -O -DNO_RC2 -DNO_RC5 -DNO_IDEA -DBSAFE -fPIC -DLINUX=260 -DMOD_SSL=206104 -DMOD_PERL -DUSE_PERL_SSI -I/include -DEAPI -D_LARGEFILE64_SOURCE -DUSE_EXPAT -I../lib/expat-lite -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/opt/oracle/middleware/Oracle_WT1/ohs/include -I/usr/include/libxml2 -I. -c mod_proxy_html.c -o mod_proxy_html.o &gt;/dev/null 2&gt;&amp;amp;1
/opt/oracle/middleware/Oracle_WT1/ohs/build/libtool --tag=CC --mode=link cc -O    -DNO_RC2 -DNO_RC5 -DNO_IDEA -DBSAFE -fPIC  -o mod_proxy_html.la  -L/opt/oracle/middleware/Oracle_WT1/ohs/lib -lxml2 -rpath /opt/oracle/middleware/Oracle_WT1/ohs/modules -module -avoid-version    mod_proxy_html.lo
rm -fr  .libs/mod_proxy_html.a .libs/mod_proxy_html.la .libs/mod_proxy_html.lai .libs/mod_proxy_html.so
/usr/bin/gcc -shared  .libs/mod_proxy_html.o  -L/opt/oracle/middleware/Oracle_WT1/ohs/lib -lxml2  -Wl,-soname -Wl,mod_proxy_html.so -o .libs/mod_proxy_html.so
ar cru .libs/mod_proxy_html.a  mod_proxy_html.o
ranlib .libs/mod_proxy_html.a
creating mod_proxy_html.la
(cd .libs &amp;amp;&amp;amp; rm -f mod_proxy_html.la &amp;amp;&amp;amp; ln -s ../mod_proxy_html.la mod_proxy_html.la)
/opt/oracle/middleware/Oracle_WT1/ohs/build/instdso.sh SH_LIBTOOL='/opt/oracle/middleware/Oracle_WT1/ohs/build/libtool' mod_proxy_html.la /opt/oracle/middleware/Oracle_WT1/ohs/modules
/opt/oracle/middleware/Oracle_WT1/ohs/build/libtool --mode=install cp -f mod_proxy_html.la /opt/oracle/middleware/Oracle_WT1/ohs/modules/
cp -f .libs/mod_proxy_html.so /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.so
cp -f .libs/mod_proxy_html.lai /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.la
cp -f .libs/mod_proxy_html.a /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.a
ranlib /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.a
chmod 644 /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.a
PATH=&quot;$PATH:/sbin&quot; ldconfig -n /opt/oracle/middleware/Oracle_WT1/ohs/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /opt/oracle/middleware/Oracle_WT1/ohs/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /opt/oracle/middleware/Oracle_WT1/ohs/modules/mod_proxy_html.so
&lt;/pre&gt;

&lt;p&gt;OHS provides the includes for Apache but not for &lt;em&gt;libxml&lt;/em&gt; (they are not part of the distribution). I checked with this simple &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/test.c&quot;&gt;test.c&lt;/a&gt; that the version is a 2.7.x so I just compiled against system headers which were of the same version.&lt;/p&gt;

&lt;p&gt;OHS does not have the beautiful organization of the configuration files that debian uses, so I added the lines directly in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/httpd.linux.conf&quot;&gt;httpd.conf&lt;/a&gt;. They are exactly the same changes I presented before but in raw mode &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;.&lt;/p&gt;

&lt;p&gt;And it worked again! So this step was done very quickly.&lt;/p&gt;


&lt;h3&gt;Adding mod_proxy_html to Windows/OHS&lt;/h3&gt;

&lt;p&gt;This was my final goal but I was sure it was going to be painfully done. I will try to explain all the steps I did but maybe I forget any of them (I did so many things that I am not sure which were necessary and which were useless).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The first point was installing a 2008r2 (evaluation licensed) and the OHS 11.1.1.5.0 (64 bit installation). This was the easy part &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; class=&quot;emoticon&quot; /&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Then the compiler suite was needed. For that I installed the &lt;a href=&quot;http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express&quot;&gt;Visual C++ 2008 Express Edition with SP1&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;The problem with that is this edition only works for win32 compilations (and not for the win64 which I needed). But I read this &lt;a href=&quot;http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvc/thread/38544c63-d12a-4a05-9ea7-5b4124152801/&quot;&gt;great forum post about this issue&lt;/a&gt; and I successfully installed &lt;a href=&quot;http://www.microsoft.com/download/en/details.aspx?id=11310&quot;&gt;Windows SDK for Windows Server 2008 and .NET Framework 3.5&lt;/a&gt; and performed the changes explained in the forum.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I created a new project (Win32 Project / DLL) and I included the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/mod_proxy_html.cpp&quot;&gt;mod_proxy_html.cpp&lt;/a&gt; which is exactly the same used in Linux but with the following include at the beginning (it adds to the project all the needed windows headers):&lt;/p&gt;

&lt;pre&gt;
#include &quot;stdafx.h&quot;
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Starting the compilation of the &lt;em&gt;mod_proxy_html&lt;/em&gt; 3.0.1 file I understood that libraries work different in Windows. DLL files are not enough and you need a LIB file which (I think) define all the symbols of the external library (functions, vars,...). The &lt;em&gt;mod_proxy_html&lt;/em&gt; depends on four external libraries: &lt;em&gt;libxml&lt;/em&gt;, &lt;em&gt;libapr-1&lt;/em&gt;, &lt;em&gt;libaprutil-1&lt;/em&gt; and &lt;em&gt;libhttpd&lt;/em&gt; (&lt;em&gt;libxml&lt;/em&gt; is used to parse HTML pages and the other are typical Apache libraries used in modules). OHS provides all of them but only as DLL files (in &lt;em&gt;%ORACLE_HOME%\ohs\bin&lt;/em&gt;). I suppose that this situation is quite common with third-party software (but do not trust in me, I am not a Windows specialist). Luckily this blog explains &lt;a href=&quot;http://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/&quot;&gt;how to create a LIB file from the DLL&lt;/a&gt; and this forum entry &lt;a href=&quot;http://social.msdn.microsoft.com/Forums/en/Vsexpressvc/thread/84deabaa-ae82-47cc-aac0-592f5a8dfa22&quot;&gt;how to add external libraries to a project&lt;/a&gt; (includes for compiling and libs for linking).&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;As OHS does not provide the &lt;em&gt;libxml&lt;/em&gt; headers (same issue than in Linux) I added an additional directory with my Linux headers. With them the compilation complained about &lt;a href=&quot;http://www.gnu.org/software/libiconv/&quot;&gt;iconv&lt;/a&gt;, as &lt;em&gt;libiconv.dll&lt;/em&gt; is not part of the OHS distribution I supposed that the &lt;em&gt;libxml&lt;/em&gt; provided for Windows is not compiled with &lt;em&gt;iconv&lt;/em&gt; support (quite normal in Windows I guess) so I changed &lt;em&gt;xmlversion.h&lt;/em&gt; header to disable &lt;em&gt;iconv&lt;/em&gt; support (I changed the 1 in the &lt;em&gt;#if&lt;/em&gt; for a 0):&lt;/p&gt;

&lt;pre&gt;
#if 0
#define LIBXML_ICONV_ENABLED
#endif
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;One particular problem was that &lt;em&gt;sockaddr_in6&lt;/em&gt; structure was not found (Apache uses IPV6 and IPV4) at compiling time. After a lot of reading I found that this structure is defined in &lt;em&gt;ws2tcpip.h&lt;/em&gt; and I needed to change the &lt;em&gt;windows.h&lt;/em&gt; provided by the SDK. I commented in the file &lt;em&gt;C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\Windows.h&lt;/em&gt; the following include:&lt;/p&gt;

&lt;pre&gt;
#include &amp;lt;winsock.h&amp;gt;
&lt;/pre&gt;

&lt;p&gt;and replaced it by this one:&lt;/p&gt;

&lt;pre&gt;
#include &amp;lt;ws2tcpip.h&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I suppose that the first one is IPV4 only and the second one is for both (but I really do not know). Besides I commented these lines in project header &lt;em&gt;stdafx.h&lt;/em&gt; (I think these defines hide some include which I needed):&lt;/p&gt;

&lt;pre&gt;
//#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
//#define &amp;#0095;WINSOCKAPI&amp;#0095;
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;With all the previous steps done the module compilation still gave a lot of errors. All those errors were only casts and I fixed all of them one by one &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; class=&quot;emoticon&quot; /&gt;. Finally the module compiled and linked, a beautiful DLL was generated. But it did not work. When the web server was started it gave the following error:&lt;/p&gt;

&lt;pre&gt;
Syntax error on line 248 of C:\\Oracle\\Middleware\\Oracle_WT1\\instances\\instance1\\config\\OHS\\ohs1/httpd.conf: Can't locate API module structure `proxy_html_module' in file C:/Oracle/Middleware/Oracle_WT1/ohs/modules/mod_proxy_html.dll: No error
&lt;/pre&gt;

&lt;p&gt;The Apache server did not find the variable of the module cos the DLL was not generated like the server wanted (the DLL did not expose the module variable). After a lot of time I realized that all my problems commented in this point (cast errors and the module variable) were generated by wrong compiling and linking options. I changed a lot of them and I am not sure which of them are the important ones. For this reason all my changes and the complete command line for compiling and linking are going to be presented (the following table shows all modified -non default- options of the project and the commands, besides &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/mod_proxy_html.vcproj&quot;&gt;here it is the Visual project file&lt;/a&gt;): &lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;&lt;th colspan=&quot;3&quot;&gt;C/C++&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;
     &lt;th rowspan=&quot;3&quot;&gt;General:&lt;/th&gt;
     &lt;td&gt;Additional Directories:&lt;/td&gt;
     &lt;td&gt;C:\Oracle\Middleware\Oracle_WT1\ohs\include&lt;br /&gt;
        C:\User\Administrator\Documents\Visual Studio 2008\Projects\Project1\mod_proxy_html\libxml2&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;td&gt;Debug Information Format:&lt;/td&gt;
       &lt;td&gt;Disabled&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;td&gt;Warning Level:&lt;/td&gt;
       &lt;td&gt;Level 3 (/W3)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th&gt;Optimization:&lt;/th&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/li&gt;&lt;/ol&gt;
      &lt;td&gt;Optimization:&lt;/td&gt;
      &lt;td&gt;Maximize Speed (/O2)&lt;/td&gt;
  
  &lt;tr&gt;
      &lt;th rowspan=&quot;4&quot;&gt;Code Generation:&lt;/th&gt;
      &lt;td&gt;Enable Minimal Rebuild:&lt;/td&gt;
      &lt;td&gt;Yes (/Gm)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;td&gt;Smaller Type Check:&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;td&gt;Basic Runtime Checks:&lt;/td&gt;
       &lt;td&gt;Default&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;td&gt;Runtime Library:&lt;/td&gt;
       &lt;td&gt;Multi-threaded Debug DLL (/MDd)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;th&gt;Precompiled Headers:&lt;/th&gt;
       &lt;td&gt;Create/Use Precompiled Header:&lt;/td&gt;
       &lt;td&gt;Use Precompiled Header (/Yu)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;th rowspan=&quot;2&quot;&gt;Advanced:&lt;/th&gt;
       &lt;td&gt;Compile As:&lt;/td&gt;
       &lt;td&gt;Compile as C Code (TC)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;td&gt;Show Includes:&lt;/td&gt;
       &lt;td&gt;Yes (/showIncludes)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
       &lt;th&gt;Command Line:&lt;/th&gt;
       &lt;td colspan=&quot;2&quot;&gt;/O2 /I &quot;C:\Oracle\Middleware\Oracle_WT1\ohs\include&quot; /I &quot;C:\Users\Administrator\Documents\Visual Studio 2008\Projects\Project1\test\libxml2&quot; /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /D &quot;_USRDLL&quot; /D &quot;MOD_PROXY_HTML_EXPORTS&quot; /D &quot;_WINDLL&quot; /D &quot;_UNICODE&quot; /D &quot;UNICODE&quot; /Gm /EHsc /MDd /Yu&quot;stdafx.h&quot; /Fp&quot;Debug\mod_proxy_html.pch&quot; /Fo&quot;Debug\\&quot; /Fd&quot;Debug\vc90.pdb&quot; /W3 /nologo /c /TC /showIncludes /errorReport:prompt&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;&lt;th colspan=&quot;3&quot;&gt;Linker:&lt;/th&gt;&lt;/tr&gt;
  &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;General:&lt;/th&gt;
      &lt;td&gt;Enable Incremental Linking:&lt;/td&gt;
      &lt;td&gt;No (/INCREMENTAL:NO)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;td&gt;Additional Library Directories:&lt;/td&gt;
      &lt;td&gt;C:\Oracle\Middleware\Oracle_WT1\ohs\bin&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th&gt;Input:&lt;/th&gt;
      &lt;td&gt;Additional Dependencies:&lt;/td&gt;
      &lt;td&gt;libxml2.lib libapr-1.lib libaprutil-1.lib libhttpd.lib&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th&gt;Debugging:&lt;/th&gt;
      &lt;td&gt;Generate Debug Info:&lt;/td&gt;
      &lt;td&gt;Yes (/DEBUG)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th&gt;System:&lt;/th&gt;
      &lt;td&gt;SubSystem:&lt;/td&gt;
      &lt;td&gt;WINDOWS (/SUBSYSTEM:WINDOWS)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th&gt;Optimization:&lt;/th&gt;
      &lt;td&gt;References:&lt;/td&gt;
      &lt;td&gt;Eliminate Unreferenced Data (/OPT:REF)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;th rowspan=&quot;3&quot;&gt;Advanced:&lt;/th&gt;
      &lt;td&gt;Randomized Base Address:&lt;/td&gt;
      &lt;td&gt;Disable Image Randomization (/DYNAMICBASE:NO)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;td&gt;Fixed Base Address:&lt;/td&gt;
      &lt;td&gt;Image must be loaded at a fixed address (/FIXED)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
      &lt;td&gt;Target Machine:&lt;/td&gt;
      &lt;td&gt;MachineX64 (/MACHINE:X64)&lt;/td&gt;
   &lt;/tr&gt;
   &lt;tr&gt;
      &lt;th&gt;Command Line:&lt;/th&gt;
      &lt;td colspan=&quot;2&quot;&gt;/OUT:&quot;C:\Users\Administrator\Documents\Visual Studio 2008\Projects\Project1\mod_proxy_html\Debug\mod_proxy_html.dll&quot; /INCREMENTAL:NO /NOLOGO /LIBPATH:&quot;C:\Oracle\Middleware\Oracle_WT1\ohs\bin&quot; /DLL /MANIFEST /MANIFESTFILE:&quot;Debug\mod_proxy_html.dll.intermediate.manifest&quot; /MANIFESTUAC:&quot;level='asInvoker' uiAccess='false'&quot; /DEBUG /PDB:&quot;c:\Users\Administrator\Documents\Visual Studio 2008\Projects\Project1\mod_proxy_html\Debug\mod_proxy_html.pdb&quot; /SUBSYSTEM:WINDOWS /OPT:REF /DYNAMICBASE:NO /FIXED /NXCOMPAT /MACHINE:X64 /ERRORREPORT:PROMPT libxml2.lib libapr-1.lib libaprutil-1.lib libhttpd.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib&lt;/td&gt;
  &lt;/tr&gt;




&lt;p&gt;After all that hell I finally got a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/mod_proxy_html.dll&quot;&gt;mod_proxy_html.dll&lt;/a&gt; valid for OHS 11.1.1.5.0 (win64) on Windows 2008r2. Again I did the same modifications in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/httpd.windows.conf&quot;&gt;httpd.conf&lt;/a&gt; file and the reverse proxy worked fine. Now a video is presented in which I first access directly to my tomcat installation and request the test page. There it is clear that some links are absolute. Then I change to my windows virtual box using the proxy location. Same tomcat page is shown and now the test HTML have the links modified to point to the correct URI (&lt;em&gt;mod_proxy_html&lt;/em&gt; is in action!). Finally I request the server info page, the Apache is a OHS Windows X64 with my &lt;em&gt;mod_proxy_html.cpp&lt;/em&gt; perfectly loaded.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Compilingmod_proxy_htmlinLinuxandWindows/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;This entry summarizes how to add &lt;em&gt;mod_proxy_html&lt;/em&gt; (a proxy module that modifies the links inside the HTML sent by the backend in order to fix them) to Apache and OHS. The entry shows how to compile the module in Debian/Apache, Linux/OHS and Windows/OHS. My final goal was adding the module to an OHS (64 bits bundle) running in a Windows 2008r2. I usually never work with Windows and I spent so much time doing that that I wanted to preserve the information here. The next time someone tells me how easy Windows is I am going to ask him to compile something, an Apache module for example. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/tongue.png&quot; alt=&quot;:-P&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;May the force be with you!&lt;/p&gt;</description>
	<pubDate>vie, 06 ene 2012 12:02:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Client Certificates In PHP / Oracle Iplanet Web Server</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/49-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/49-Client-Certificates-In-PHP-Oracle-Iplanet-Web-Server.html</link>
	<description>&lt;p&gt;These days I have been working in a customer with the same issue which was discussing in the last series of this blog: &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/47-Certificate-Security-in-JavaEE-Custom-Solution.html&quot;&gt;client certificate login (custom solution)&lt;/a&gt;. The big difference here was that this customer is working with &lt;a href=&quot;http://www.php.net/&quot;&gt;PHP&lt;/a&gt; (last version 5.3) and Oracle Iplanet Web Server 7.0 (formerly Sun Java System Web Server, formerly Sun ONE Web Server, formerly Iplanet Web Server and now included in &lt;a href=&quot;http://www.oracle.com/technetwork/java/webtier/downloads/index.html&quot;&gt;Oracle Fusion Middleware WebTier&lt;/a&gt;). This web server is the last version of the Sun web server which comes from the time of &lt;a href=&quot;http://en.wikipedia.org/wiki/IPlanet&quot;&gt;Sun and Netscape alliance&lt;/a&gt;. It is curious how just when I decided to publish the series this topic has come out to me again and again.&lt;/p&gt;

&lt;p&gt;PHP when is integrated with &lt;a href=&quot;http://httpd.apache.org/&quot;&gt;Apache&lt;/a&gt; (the most common situation) uses some environment variables (&lt;em&gt;SSL_CLIENT_CERT&lt;/em&gt;, &lt;em&gt;SSL_CLIENT_S_DN&lt;/em&gt; and so on) that &lt;a href=&quot;http://httpd.apache.org/docs/2.2/ssl/&quot;&gt;mod_ssl&lt;/a&gt; (module for Apache Web Server to get SSL communication -HTTPS- which relies on &lt;a href=&quot;http://www.openssl.org/&quot;&gt;OpenSSL&lt;/a&gt;) provides to PHP in &lt;em&gt;$_SERVER&lt;/em&gt; array. These vars contain some info about the SSL communication in general and the client certificate in particular, some of them are different parts or fields of the cert and SSL_CLIENT_CERT is the whole certificate, &lt;a href=&quot;http://www.faqs.org/qa/qa-14736.html&quot;&gt;PEM&lt;/a&gt; format (&lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_ssl.html#ssloptions&quot;&gt;see &lt;em&gt;StdEnvVars&lt;/em&gt; option in the documentation for further info&lt;/a&gt;). As always the developer team has its way environment, windows + Apache 2.2 + PHP 5.2, while the pre and production environment of the customer is Solaris 10 + Iplanet 7.0 + PHP 5.3. Obviously the application did not work when it was tested in pre-production (what a strange thing!). The variables that &lt;em&gt;mod_ssl&lt;/em&gt; should inject were not there, which was really confusing for the developers, of course the fact that the web server was an Iplanet and not an Apache did not matter much to them.&lt;/p&gt;

&lt;p&gt;When PHP is compiled against the Iplanet Web Server it uses old &lt;a href=&quot;http://en.wikipedia.org/wiki/Netscape_Server_Application_Programming_Interface&quot;&gt;NSAPI (Netscape Server Application Programming Interface)&lt;/a&gt; to interact with the http daemon. Typical PHP compilation (very short in modules) for this environment is like this:&lt;/p&gt;

&lt;pre&gt;
./configure --prefix=/opt/php-5.3 --with-nsapi=/opt/SUNWwbsvr7 \
    --enable-ftp --with-pear --enable-pdo --with-openssl
&lt;/pre&gt;

&lt;p&gt;The &lt;em&gt;/opt/SUNWwbsvr7&lt;/em&gt; directory is where the Iplanet Web Server is installed, the installtion needs sample applications component because include files are in there. Then you need to configure some files to make the web server process PHP files (see &lt;a href=&quot;http://php.net/manual/en/install.unix.sun.php&quot;&gt;this wiki page for compilation and configuration details&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you check the NSAPI developer guide, &lt;a href=&quot;http://download.oracle.com/docs/cd/E19146-01/821-0787/abvej/index.html&quot;&gt;the client certificate is placed as a request variable&lt;/a&gt; named &lt;em&gt;auth-cert&lt;/em&gt;. This var contains the certificate in &lt;a href=&quot;http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules&quot;&gt;DER&lt;/a&gt; format but encoded into text with &lt;a href=&quot;http://en.wikipedia.org/wiki/Base64&quot;&gt;BASE64&lt;/a&gt;. The &lt;a href=&quot;http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3_8/sapi/nsapi/nsapi.c?view=markup&quot;&gt;nsapi.c&lt;/a&gt; file in PHP source registers this variable in its own environment with another name &lt;em&gt;CLIENT_CERT&lt;/em&gt;. So you can access the certificate (DER + BASE64) like this &lt;em&gt;$_SERVER['CLIENT_CERT']&lt;/em&gt;. Then the certificate can be parsed using some PHP/SSL methods. This sample PHP file performs exactly what I said.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
// header to plain/text
header(&quot;content-type: text/plain&quot;);
// print server vars
print(&quot;SERVER vars:\n&quot;);
print_r($_SERVER);
// get the headers
print(&quot;\n\nHEADERS:\n&quot;);
print_r(getallheaders());
// print certificate parsed by SSL
$pem = &quot;-----BEGIN CERTIFICATE-----\n&quot;
    . $_SERVER['CLIENT_CERT']
    . &quot;\n-----END CERTIFICATE-----\n&quot;;
$cert = openssl_x509_parse($pem);
print(&quot;\n\nCertificate parsed by OpenSSL:\n&quot;);
print_r($cert);
// print some variables from the cert
print(&quot;\n\nGetting some data from the parsed cert:\n&quot;);
print(&quot;name: &quot; . $cert['name'] . &quot;\n&quot;);
print(&quot;subject-&gt;CN: &quot; . $cert['subject']['CN'] . &quot;\n&quot;);
print(&quot;validFrom: &quot; . $cert['validFrom'] . &quot;\n&quot;);
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;As you see the server variable is converted into SSL PEM format (as the certificate is already in BASE64, setting the header and footer line is the only step to transform it into PEM) and then it is parsed and stored into an array by &lt;a href=&quot;http://php.net/manual/en/function.openssl-x509-parse.php&quot;&gt;openssl_x509_parse&lt;/a&gt; function. With this array any field of the certificate can be retrieved easily. &lt;/p&gt;

&lt;p&gt;When finally the application went to production I realized that the PHP web server was behind a proxy (another difference, this time an architectural one). In this case the certificate is not received in the commented way, in this architecture all the SSL stuff (certificate exchange process included) is managed by the proxy and &lt;a href=&quot;https://blogs.oracle.com/dee/entry/forwarding_client_credentials_through_reverse1&quot;&gt;the client certificate is usually forwarded to the backend server using a header&lt;/a&gt; (&lt;em&gt;proxy-auth-cert&lt;/em&gt; in case of iPlanet Web Proxy Server). In this solution &lt;a href=&quot;http://php.net/manual/en/function.getallheaders.php&quot;&gt;getallheaders&lt;/a&gt; PHP function should be used to get the certificate from the specified header and construct the PEM variable exactly in the same way I did in the previous example.&lt;/p&gt;

&lt;p&gt;So with PHP and Oracle Iplanet Web Server (any NSAPI server in general although I do not know anyone else) you obviously cannot use mod_ssl/Apache environment variables, there is another one called &lt;em&gt;CLIENT_CERT&lt;/em&gt; which is the certificate itself in DER + BASE64 (behind a proxy the certificate is usually placed in a header). Once this fact is known it is easy to find a way of getting any certificate field with PHP code (I used a PHP/SSL function to parse the certificate into an array of variables). Please if you are a developer, do not start coding before all the versions, software stack and architecture are perfectly defined, you usually will work twice or even more (and you will drive a lot of people crazy too, people like me).&lt;/p&gt;

&lt;p&gt;Never lose hope!&lt;/p&gt;</description>
	<pubDate>sáb, 17 dic 2011 14:48:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Zuma's Revenge!</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/51-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/51-Zumas-Revenge!.html</link>
	<description>&lt;img class=&quot;serendipity_image_right&quot; src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ZumasRevenge/zumas_revenge_cover.jpg&quot; alt=&quot;Zuma's Revenge! cover&quot; /&gt;

&lt;p&gt;This week I was on vacation. I was on the mood of doing nothing, so I decided to play some PC game. I had very good references of the &lt;a href=&quot;http://www.facebook.com/zumablitz&quot;&gt;Zuma Blitz&lt;/a&gt; that people play in Facebook. Besides I had played before &lt;a href=&quot;http://www.popcap.com/games/pvz/web&quot;&gt;Plants vs Zombies&lt;/a&gt; of the same company (&lt;a href=&quot;http://www.popcap.com/&quot;&gt;PopCap&lt;/a&gt; games). This one was fantastic. So finally I decided to play &lt;a href=&quot;http://www.popcap.com/games/zumasrevenge/web&quot;&gt;Zuma's Revenge!&lt;/a&gt; (PC version of the Facebook one).&lt;/p&gt;

&lt;p&gt;It has been horrible, sometimes I forget how obsessive I am. I quickly got the last level (level 60), just in one game but I died in that stage. The problem is that, when you die, you do not start in the same stage but five levels before (and with only two lifes!). Maybe I am too clumsy, but it was absolutely impossible for me. I played long hours and the best I did was reaching level 60, I did not even fight against the final boss. I realized I had a problem when I dreamt with the damned balls. So today I had only one mission, finishing the game at all cost (I mean, of course, cheating). Finally I got a cheat to slow down the balls (I would have preferred infinite lifes but I just needed to fool myself). Finally I beat the final boss.&lt;/p&gt;

&lt;p&gt;So now it is over. The situation makes me not to trust anymore on PopCap games, I want smooth games, never like this one in which you have to be the fucking &lt;a href=&quot;http://en.wikipedia.org/wiki/Hawkeye_%28comics%29&quot;&gt;hawkeye&lt;/a&gt; to reach the final.&lt;/p&gt;

You are advised!

&lt;p&gt;&lt;span&gt;&lt;b&gt;PS&lt;/b&gt;: Of course both games (Zuma and Plants vs Zombies) work in Linux under &lt;a href=&quot;http://www.winehq.org&quot;&gt;wine&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;</description>
	<pubDate>dom, 11 dic 2011 19:02:29 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Gnome-Shell Extensions</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/50-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/50-Gnome-Shell-Extensions.html</link>
	<description>&lt;p&gt;Some weeks ago I realized that &lt;a href=&quot;http://live.gnome.org/GnomeShell/Design/&quot;&gt;gnome-shell&lt;/a&gt; and all &lt;a href=&quot;http://www.gnome.org/gnome-3/&quot;&gt;gnome3&lt;/a&gt; packages were ready to be installed in my wheezy box. Cos I were (and I still am) very busy with a project I am involved, I decided not to upgrade my system at that moment. &lt;a href=&quot;http://www.phoronix.com/scan.php?page=article&amp;amp;item=gnome_survey_part1&amp;amp;num=1&quot;&gt;I had heard such bad comments about this new version&lt;/a&gt; that I felt afraid about the change (I was very comfortable with my old desktop). But I have always been a loyal gnome user so the previous weekend my new gnome3/gnome-shell environment was installed, tested and customized.&lt;/p&gt;

&lt;p&gt;Obviously the bad comments about the new version are justified in the big differences between both versions. In my opinion plain gnome 3.0 (current version in wheezy), though very eye-candy, is very very restrictive and unproductive in its use. Lots of clicks are wasted to do the same thing you previously did in just one. This annoying fact is very related to the lost of many applets I usually managed (virtual desktop management, menus, launchers, window selector, weather,...), which made your life easier. But finally I discovered that gnome-shell introduces a new idea: &lt;a href=&quot;http://live.gnome.org/GnomeShell/Extensions&quot;&gt;gnome shell extensions&lt;/a&gt;. The gnome-shell uses extensions in a very similar way than firefox does but, right now, there is not a trusted gnome extension repository or a extension manager application (easy installation, auto-update and so on). But it is clear for me that &lt;a href=&quot;http://lwn.net/Articles/459786/&quot;&gt;it is planned for the near future&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I spent short time studying &lt;a href=&quot;http://blog.fpmurphy.com/2011/04/gnome-3-shell-extensions.html&quot;&gt;how extensions work&lt;/a&gt; and finally I realized they are a very good idea. From a technical view a extension consists in some JSON (configuration), JavaScript (code) and CSS (aspect) files (all HTML standards which is a good thing, at least for me). I am sure that you will can easily replace anything you did in gnome2 with a suitable extension in gnome3 but, as always, nowadays all this stuff is quite immature. One important aspect is that these extensions can also be installed in your &lt;em&gt;~/.local&lt;/em&gt; directory (you do not need packages from your linux distribution, although it is sure that some basic extensions will be installed by default in all distros, check this &lt;a href=&quot;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=627515&quot;&gt;debian bug&lt;/a&gt; for example). &lt;/p&gt;

&lt;p&gt;In order to configure gnome-shell and its extensions you better install &lt;em&gt;gnome-tweak-tool&lt;/em&gt; application. But you always can do all configuration using typical &lt;em&gt;gsettings&lt;/em&gt; command or &lt;em&gt;dconf-editor&lt;/em&gt; application (utilities to manage the gnome configuration in general). So once I had understood new gnome-shell stuff I installed the following extensions to be comfortable with my new desktop:&lt;/p&gt;

&lt;h3&gt;Standard gnome-shell-extensions&lt;/h3&gt;

&lt;p&gt;Gnome itself has a &lt;a href=&quot;http://git.gnome.org/browse/gnome-shell-extensions/&quot;&gt;collection of extensions&lt;/a&gt; (these are the ones that I think, at least, are going to be in any linux distro by default). I installed two of them: &lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;dock&lt;/strong&gt;: Shows a dock-style task switcher on the right side of the screen (it replaces my typical launchers and window selectors). Next version 3.2 adds configuration properties for changing the default position and auto-hiding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;user-theme&lt;/strong&gt;: Loads a shell theme from &lt;em&gt;~/.themes/&amp;lt;name&amp;gt;/gnome-shell&lt;/em&gt; (I like to customize my desktop &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt; ).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The installation process is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Get the source from GIT:&lt;/p&gt;

&lt;pre&gt;
$ git clone git://git.gnome.org/gnome-shell-extensions
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Go to tag gnome 3.0.2 (version of my current wheezy gnome-shell):&lt;/p&gt;

&lt;pre&gt;
$ cd gnome-shell-extensions/
$ git checkout 3.0.2
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Autogen, make and install them (only the two extensions):&lt;/p&gt;

&lt;pre&gt;
$ ./autogen.sh --prefix=$HOME/.local --enable-extensions=&quot;user-theme dock&quot;
$ make
$ make install
&lt;/pre&gt;

&lt;li&gt;&lt;p&gt;Right now &lt;a href=&quot;http://www.gnomeshell.com/2011/05/11/gs-extensions-auto-move-windows/&quot;&gt;there is a bug in &lt;em&gt;glib-2.0&lt;/em&gt;&lt;/a&gt; that it does not take into account extended schemas you have in your &lt;em&gt;~/.local/share/glib-2.0/schemas&lt;/em&gt; directory. So you have to copy the new schemas from there to the global directory and compile them:&lt;/p&gt;

&lt;pre&gt;
$ cd ~/.local/share/glib-2.0/schemas/
$ sudo cp org.gnome.shell.extensions.dock.gschema.xml \
  org.gnome.shell.extensions.user-theme.gschema.xml /usr/share/glib-2.0/schemas/
$ sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;All the themes for gnome3 (GTK, window manager or gnome-shell itself) can be download from &lt;a href=&quot;http://gnome-look.org&quot;&gt;gnome-look.org&lt;/a&gt;. They are installed as always inside &lt;em&gt;~/.themes&lt;/em&gt; and &lt;em&gt;~/.icons&lt;/em&gt; directories. Use &lt;em&gt;gnome-tweak-tool&lt;/em&gt; to change any theme.&lt;/li&gt;
&lt;/li&gt;&lt;/ol&gt;

&lt;h3&gt;gnome-shell-weather-extension&lt;/h3&gt;

&lt;p&gt;Another applet I used to add to my gnome2 panel was the weather applet. An equivalent extension is the &lt;a href=&quot;http://www.webupd8.org/2011/10/install-gnome-shell-weather-extension.html&quot;&gt;gnome-shell-weather-extension&lt;/a&gt; done by Simon Legner but it nowadays does not have several locations like the old applet &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; class=&quot;emoticon&quot; /&gt;. The installation is more or less the same:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clone the repository with git (branch 3.0):&lt;/p&gt;

&lt;pre&gt;
$ git clone -b gnome3.0 https://github.com/simon04/gnome-shell-extension-weather
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Install:&lt;/p&gt;

&lt;pre&gt;
$ cd gnome-shell-extension-weather/
$ ./autogen.sh --prefix=$HOME/.local
$ make
$ make install
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Because of the commented glib2 bug you need to include the schemas globally:&lt;/p&gt;

&lt;pre&gt;
$ cd ~/.local/share/glib-2.0/schemas
$ sudo cp org.gnome.shell.extensions.weather.gschema.xml /usr/share/glib-2.0/schemas/
$ sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Then you need to set the city for the weather, &lt;a href=&quot;http://sigizmund.info/woeidinfo/?woeid=madrid&quot;&gt;in my case Madrid&lt;/a&gt;. I did it via &lt;em&gt;gsettings&lt;/em&gt; (you can also use &lt;em&gt;dconf-editor&lt;/em&gt;):&lt;/p&gt;

&lt;pre&gt;
$ gsettings set org.gnome.shell.extensions.weather woeid &quot;'766273'&quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;gnome-shell-workspace-indicator&lt;/h3&gt;

&lt;p&gt;Finally workspaces in default gnome3 needs too many clicks for me (I change working workspace very often to waste time doing that). So I installed &lt;a href=&quot;http://www.webupd8.org/2011/05/gnome-shell-workspace-indicator.html&quot;&gt;another extension that adds workspace selection in gnome-shell toolbar&lt;/a&gt;. This extension has been incorporated to default gnome-shell extensions in latest version 3.2 (but it does not exist in the 3.0.2/wheezy version I installed in the first point).&lt;/p&gt;

&lt;p&gt;The installation is pretty the same:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clone the sources:&lt;/p&gt;

&lt;pre&gt;
$ git clone git://github.com/erick2red/shell-extensions.git
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Generate and install:&lt;/p&gt;

&lt;pre&gt;
$ cd shell-extensions/
$ ./autogen.sh --prefix=$HOME/.local --enable-extensions=&quot;workspace-indicator&quot;
$ make
$ make install
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Installation of the schemas:&lt;/p&gt;

&lt;pre&gt;
$ cd schemas/
$ sudo cp org.gnome.shell.extensions.workspace-indicator.gschema.xml \
  /usr/share/glib-2.0/schemas/
$ sudo glib-compile-schemas /usr/share/glib-2.0/schemas/
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;I prefer wide indicator (with wide indicator you see &lt;em&gt;Workspace 1&lt;/em&gt; instead of the concise &lt;em&gt;1&lt;/em&gt; you get with default configuration):&lt;/p&gt;

&lt;pre&gt;
$ gettings set org.gnome.shell.extensions.workspace-indicator \
  wide-indicator true
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I tried to be comfortable but with the least number of extensions. Think you have to re-add them every time you upgrade gnome-shell version (until there was a better solution: a gnome extension manager infraestructure, distro provided extensions or whatever). My desktop currently has the following aspect.&lt;/p&gt;

 
 



&lt;div class=&quot;highslide-gallery&quot;&gt; 

&lt;a id=&quot;gnome-shell_thumb1&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/theme.png&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/theme.preview.png&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        New theme for my Gnome-Shell (Adwaita-White)
&lt;/div&gt;

&lt;a id=&quot;gnome-shell_thumb2&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/dock.png&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/dock.preview.png&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Dock extension provides a right menu to launch and bring to front apps
&lt;/div&gt;

&lt;a id=&quot;gnome-shell_thumb3&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/weather.png&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/weather.preview.png&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Current weather extension and forecast (Madrid)
&lt;/div&gt;

&lt;a id=&quot;gnome-shell_thumb4&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/workspace.png&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Gnome-ShellExtensions/workspace.preview.png&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Workspace extension to easily change current workspace
&lt;/div&gt;

&lt;/div&gt;

&lt;p&gt;I have written this entry because, as I commented before, I will need to update my extensions when a new version of the gnome-shell arrives (3.2 for example). I hope that shortly some extension management will come to gnome3 and all this stuff will be automatically done (as firefox does), but right now extensions need to be installed manually. There are a lot of them scattered throughout the internet and there are also several links which comment the must-have ones (for example &lt;a href=&quot;http://www.techdrivein.com/2011/10/7-best-gnome-shell-extensions-install.html&quot;&gt;this&lt;/a&gt;, &lt;a href=&quot;http://justinstories.wordpress.com/2011/05/27/five-must-have-gnome-shell-extensions-for-fedora-15/&quot;&gt;this&lt;/a&gt; or &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/ http://ubuntumanual.org/posts/424/top-8-gnome-shell-extensions&quot;&gt;this&lt;/a&gt;). Installation can be independent of the linux distribution (although some basic extensions will come by default for sure). I have only installed four extensions in my desktop: &lt;em&gt;user-theme&lt;/em&gt; support, &lt;em&gt;dock&lt;/em&gt;, &lt;em&gt;weather&lt;/em&gt; and &lt;em&gt;workspace&lt;/em&gt;. You can enable or disable extensions and customize them via &lt;em&gt;gnome-tweak-tool&lt;/em&gt; (coarse-grained changes) and &lt;em&gt;gsettings&lt;/em&gt; or &lt;em&gt;dconf-editor&lt;/em&gt; (fine-grained configuration).&lt;/p&gt;

&lt;p&gt;Finally I got the conclusion that gnome3 and its extensions are a brilliant idea. I think that, with a proper management and repository, its future is awesome but right now gnome3 falls a bit short. In my opinion that is the reason for all the bad comments and the negative impression of many users.&lt;/p&gt;

&lt;p&gt;Long life gnome3!&lt;/p&gt;</description>
	<pubDate>sáb, 19 nov 2011 10:42:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Pon un sol en tu vida: Adobe Flash: The misunderstood ugly guy</title>
	<guid>http://blogs.nologin.es/slopez/archives/30-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/30-Adobe-Flash-The-misunderstood-ugly-guy.html</link>
	<description>Almost everyone hates Flash, and &lt;a href=&quot;http://www.esotech.org/resources/programming/html/the-internet-progresses-adobe-flash-discontinued&quot;&gt;the discontinuation of it's mobile version was seen by many as a triumph&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Being a GNU/Linux user myself, I also suffered all those crappy versions, late releases and crazy development cycles. But, looking back and trying to be fair, I must acknowledge that the availability of a Flash player for the major operating systems has lowered the barrier for multiplatform development for many people, specially for independent companies. And I'm not talking only about embedded videos on websites, but also videogames (like &lt;a href=&quot;http://machinarium.net&quot;&gt;Machinarium&lt;/a&gt; or &lt;a href=&quot;http://thelettervsixtim.es&quot;&gt;VVVVVV&lt;/a&gt;) and applications. In some sense, Flash was more successful than Java at building bridges between platforms.&lt;br /&gt;
&lt;br /&gt;
That said, the failure of Flash on mobile platforms is not surprising at all. Pride seems to be the favorite sin for Adobe. They were barely able to produce decent quality versions for non-mobile platforms, so it was pretty clear their development work force wasn't strong enough to provide properly optimized versions for the more complex Android ecosystem.&lt;br /&gt;
&lt;br /&gt;
Adobe rejected the option of freeing its Flash Player, while keeping Adobe Flash (the content creator) as a commercial product. Apparently, they feared publishing the source code of its player would make easier for its competitors to provide alternative editors. But competition is not a bad thing, as it usually enriches the ecosystem and increases the popularity of a product. And opening the player would have extended Flash to newer platforms, improved the quality of non-Windows versions, and reduced total development cost, giving them more chances to success on mobile platforms. Perhaps they would even won the favor of some other companies (namely Google), which would in turn embed support for Flash on their own products by themselves.&lt;br /&gt;
&lt;br /&gt;
Adobe lost their big chance. Not even them understood the truly potential of their own product.&lt;br /&gt;
&lt;br /&gt;</description>
	<pubDate>dom, 13 nov 2011 09:29:00 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Certificate Security in JavaEE - Standard Solution (Glassfish)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/48-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/48-Certificate-Security-in-JavaEE-Standard-Solution-Glassfish.html</link>
	<description>&lt;p&gt;Today I am going to present the last entry of the series about certificate security in a JavaEE application. If you remember &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/46-Certificate-Security-in-JavaEE-Demo-Setup.html&quot;&gt;the first post dealt with the environment setup&lt;/a&gt; (not very interesting in terms of development but a nice guide about a quick CA and secure server installation) and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/47-Certificate-Security-in-JavaEE-Custom-Solution.html&quot;&gt;the second one commented custom security using client certificates&lt;/a&gt; (the application itself mapped the certificates and real users and groups). This last entry will present client certificates authentication but using standard JavaEE security.&lt;/p&gt;

&lt;p&gt;JavaEE uses security based on roles, each user will have some roles, and depending these roles he can or cannot perform the specific application actions. Talking about what can be protected JavaEE adds security to two types of resources in a direct way: any web resource (pages, servlets,...) and &lt;a href=&quot;http://en.wikipedia.org/wiki/Enterprise_JavaBean&quot;&gt;Enterprise Java Beans (EJB)&lt;/a&gt; (the whole bean and/or specific methods of the bean). The security can be mapped via the deployment descriptor, &lt;em&gt;web.xml&lt;/em&gt; in case of the web resources (&lt;em&gt;security-constraint&lt;/em&gt; directive) and &lt;em&gt;ejb-jar.xml&lt;/em&gt; in case of EJBs (&lt;em&gt;method-permission&lt;/em&gt; and so on), or using annotations (&lt;em&gt;@DeclareRoles&lt;/em&gt;, &lt;em&gt;@RolesAllowed&lt;/em&gt;, &lt;em&gt;@PermitAll&lt;/em&gt; or &lt;em&gt;@DenyAll&lt;/em&gt;). The JavaEE API also offers methods to know the roles of a user and perform a programmatic security (&lt;a href=&quot;http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)&quot;&gt;isUserInRole in HttpServletRequest&lt;/a&gt; and &lt;a href=&quot;http://download.oracle.com/javaee/6/api/javax/ejb/EJBContext.html#isCallerInRole(java.lang.String)&quot;&gt;isCallerInRole in EJBContext&lt;/a&gt;). So the idea is pretty clear, based on the roles of the user the application has to manage its own security which can be declarative (assembler files or annotations), programmatic (API) or both.&lt;/p&gt;

&lt;p&gt;So now that JavaEE security is understood we need to know how the roles are assigned to a specific user. Basically the roles are defined for the application (again assembler file descriptors or annotations) and then they are mapped against users and groups inside some repository. JavaEE manages the concept of realms, which are stores for users and groups associated to the container. The containers perform the mapping between them and the application roles via a proprietary file descriptor (&lt;em&gt;glassfish-web.xml&lt;/em&gt;, &lt;em&gt;weblogic.xml&lt;/em&gt;,...) and/or using the container management console (case of IBM WebSphere). Each application server manages the realms in its own way, they can be more or less powerful (for example weblogic has clearly a much more customizable realms than glassfish or tomcat).&lt;/p&gt;

&lt;p&gt;The last part of theory which needs to be commented is the login issue. Once the JavaEE application has added role restrictions it needs to establish a login method. The standard configures the login inside the &lt;em&gt;login-config&lt;/em&gt; part of the &lt;em&gt;web.xml&lt;/em&gt;. It permits the following methods for authentication: &lt;em&gt;NONE&lt;/em&gt;, &lt;em&gt;BASIC&lt;/em&gt;, &lt;em&gt;DIGEST&lt;/em&gt;, &lt;em&gt;FORM&lt;/em&gt; or &lt;em&gt;CLIENT-CERT&lt;/em&gt;. This login is also associated to a realm in the container. So now it is clear, when an application establishes JavaEE security, it defines a realm, a login method and different roles; the users who try to access the application will need to login first and, in this process, they get all the groups from the selected realm (in JavaEE jargon the user and groups obtained from the realm are called principals); these groups are mapped against the app roles; finally the roles are used to implement security (declarative or programmatic) inside the application. As you see the circle is now closed.&lt;/p&gt;

&lt;p&gt;JavaEE is sometimes quite overelaborated, but be sure that the ideas behind it are very very simple. You can read &lt;a href=&quot;http://download.oracle.com/javaee/6/tutorial/doc/gijrp.html&quot;&gt;the JavaEE tutorial (current version 6) for further information about its security model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going back to our particular case of client certificates, it is clear that &lt;em&gt;CLIENT-CERT&lt;/em&gt; authentication login method has to be selected. And, as it is a standard defined login method, everything should work smoothly, but Glassfish is not the case. What I want you to have in mind is that now all this stuff is in the hands of your container, we are talking about JavaEE, therefore the way login and mapping are handled does not depend on the application but on the container itself.&lt;/p&gt;

&lt;p&gt;I chose glassfish v3 as my application server for this series and &lt;a href=&quot;http://blogs.oracle.com/nasradu8/entry/extend_certificaterealm_with_loginmodule_glassfish&quot;&gt;it has a special &lt;em&gt;certificate&lt;/em&gt; realm&lt;/a&gt;, this realm is always used when &lt;em&gt;CLIENT-CERT&lt;/em&gt; login is specified for an application (this part is not configurable). By default it only gets the subject of the certificate and sets it as the user principal, but nothing else, so forget about ldap, groups or whatever. Nevertheless glassfish joins realm implementations to a &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service&quot;&gt;JAAS (Java Authentication and Authorization Service)&lt;/a&gt; login module context. A JAAS context can specify several (and custom) login modules, this way a custom certificate login module can be implemented to get the user from the certificate and match him to a user in the company repository. This way I defined a new login module inside the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/login.conf&quot;&gt;domains/domain1/config/login.conf&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
certLdapRealm {
       sample.loginmodule.CertLdapLoginModule required realm=ldap;
};
&lt;/pre&gt;

&lt;p&gt;I created a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/CertLdapLoginModule.java&quot;&gt;CertLdapLoginModule.java&lt;/a&gt; which extends &lt;a href=&quot;http://java.net/projects/glassfish/sources/svn/content/tags/3.1.1/security/core/src/main/java/com/sun/appserv/security/AppservCertificateLoginModule.java&quot;&gt;AppservCertificateLoginModule&lt;/a&gt;, an abstract class that glassfish explicitly provides to implement custom certificate login modules. My new class only has to implement the &lt;em&gt;authenticateUser&lt;/em&gt; method, in here, my idea is clear: getting the user from the subject (same as in custom security, the user login is the CN part of the certificate subject) and querying the ldap with it in order to obtain the user and groups. &lt;/p&gt;

&lt;p&gt;I first thought reusing the glassfish &lt;a href=&quot;http://java.net/projects/glassfish/sources/svn/content/tags/3.1.1/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/LDAPRealm.java&quot;&gt;LDAPRealm&lt;/a&gt; for all the ldap stuff but this realm has all methods declared as private and I could not find a way of searching the user. The class is declared final so it cannot be extended either. Finally I copied the class code &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; class=&quot;emoticon&quot; /&gt; and a new &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/LDAPRealm.java&quot;&gt;LDAPRealm.java&lt;/a&gt; was created. It is almost the same code except the method &lt;em&gt;findAndBind&lt;/em&gt;, which now receives a new boolean parameter &lt;em&gt;checkPassword&lt;/em&gt;, if it is false no bind is performed and the user and groups are retrieved without password.&lt;/p&gt;

&lt;p&gt;You have noticed that the &lt;em&gt;certLdapRealm&lt;/em&gt; JAAS definition defines a &lt;em&gt;realm&lt;/em&gt; option parameter, this parameter marks the realm which implements the new &lt;em&gt;LDAPRealm&lt;/em&gt; class. The code inside my custom login class (&lt;em&gt;autheticateUser&lt;/em&gt; method) is the following:&lt;/p&gt;

&lt;pre&gt;
protected void authenticateUser() throws LoginException {
    String realm = (String) _options.get(REALM_OPTION);
    if (realm == null) {
        throw new LoginException(
            &quot;LoginModule has not 'realm' option to get the LDAP realm!&quot;);
    }
    try {
        // get the user from the certificate
        LdapName name = new LdapName(this.getX500Principal().getName());
        String certName = name.getRdn(name.size() - 1).getValue().toString();
        // get the realm
        LDAPRealm ldap = (LDAPRealm) Realm.getInstance(realm);
        if (ldap == null) {
            throw new LoginException(&quot;Realm'&quot; + realm + &quot;' does not exists!&quot;);
        }
        String[] grpList = ldap.findAndBind(certName, null, false);
        // add the short user as a user principal
        // LoginContextDriver sets the cert subject as the name of the user
        // this let the user to set roles based on user (uid) names
        getSubject().getPrincipals().add(new PrincipalImpl(certName));
        // add groups =&gt; commit sets them as group principals
        commitUserAuthentication(grpList);
    } catch (Exception e) {
        throw new LoginException(e.getMessage());
    }
}
&lt;/pre&gt;

&lt;p&gt;The method gets the &lt;em&gt;LDAPRealm&lt;/em&gt; using the specified option. The CN part of the certificate subject is read in order to query the ldap. The custom &lt;em&gt;findAndBind&lt;/em&gt; method is used with &lt;em&gt;false&lt;/em&gt; argument (do not bind the user). If everything goes well the groups that have been returned are passed to be transformed into principals. Check that the user himself is added as a principal before, this is done cos the &lt;em&gt;certificate&lt;/em&gt; realm uses the complete &lt;em&gt;DN&lt;/em&gt; as username (now both ways, complete &lt;em&gt;DN&lt;/em&gt; or just the &lt;em&gt;UID&lt;/em&gt; part can be used in the role mapping file).&lt;/p&gt;

&lt;p&gt;Finally the certificate realm inside glassfish has to be configured to use the new JAAS module. This was done directly in the &lt;em&gt;domain.xml&lt;/em&gt; file (&lt;em&gt;asadmin&lt;/em&gt; can also be used for this configuration):&lt;/p&gt;

&lt;pre&gt;
&amp;lt;auth-realm name=&quot;certificate&quot;
    classname=&quot;com.sun.enterprise.security.auth.realm.certificate.CertificateRealm&quot;&amp;gt;
        &amp;lt;property name=&quot;jaas-context&quot; value=&quot;certLdapRealm&quot;&amp;gt;&amp;lt;/property&amp;gt;
        &amp;lt;property name=&quot;assign-groups&quot; value=&quot;allusers&quot;&amp;gt;&amp;lt;/property&amp;gt;
&amp;lt;/auth-realm&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The &lt;em&gt;jaas-context&lt;/em&gt; property specifies the JAAS context to be used (it was set to &lt;em&gt;certLdapRealm&lt;/em&gt;). The other property &lt;em&gt;assign-groups&lt;/em&gt; are groups that are directly assigned to any user who successfully logs in this realm (they are used in &lt;em&gt;web.xml&lt;/em&gt; for specifying any authenticated user).&lt;/p&gt;

&lt;p&gt;Finally the &lt;em&gt;LDAPRealm&lt;/em&gt; (used inside the custom login module) has to be configured in glassfish too:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;auth-realm name=&quot;ldap&quot; classname=&quot;sample.realm.LDAPRealm&quot;&amp;gt;
    &amp;lt;property name=&quot;directory&quot; value=&quot;ldap://debian.demo.kvm:389&quot;&amp;gt;&amp;lt;/property&amp;gt;
    &amp;lt;property name=&quot;base-dn&quot; value=&quot;dc=demo,dc=kvm&quot;&amp;gt;&amp;lt;/property&amp;gt;
    &amp;lt;property name=&quot;jaas-context&quot; value=&quot;myLdapRealm&quot;&amp;gt;&amp;lt;/property&amp;gt;
    &amp;lt;property name=&quot;search-bind-dn&quot; value=&quot;cn=admin,dc=demo,dc=kvm&quot;&amp;gt;&amp;lt;/property&amp;gt;
    &amp;lt;property name=&quot;search-bind-password&quot; value=&quot;****&quot;&amp;gt;&amp;lt;/property&amp;gt;
    &amp;lt;property name=&quot;assign-groups&quot; value=&quot;allusers&quot;&amp;gt;&amp;lt;/property&amp;gt;
&amp;lt;/auth-realm&amp;gt;
&lt;/pre&gt;

&lt;p&gt;This is a normal configuration for a glassfish &lt;em&gt;LDAPRealm&lt;/em&gt; (except that my class is used instead of the glassfish default). Please check that the realm name is &lt;em&gt;ldap&lt;/em&gt;, exactly the same name which is passed to my &lt;em&gt;certLdapRealm&lt;/em&gt; JAAS context in the &lt;em&gt;login.conf&lt;/em&gt; file. The extra realm and login module classes were packaged into a jar and placed inside &lt;em&gt;domains/domain1/lib&lt;/em&gt; directory (see &lt;a href=&quot;http://blogs.oracle.com/nithya/entry/groups_in_custom_realms&quot;&gt;this article&lt;/a&gt; for more information about custom realms and login modules in glassfish).&lt;/p&gt;

&lt;p&gt;I know that all of this is quite confusing, so I am going to repeat the idea. The default &lt;em&gt;certificate&lt;/em&gt; realm now depends on a custom &lt;em&gt;certLdapRealm&lt;/em&gt; JAAS context. This context executes a custom &lt;em&gt;CertLdapLoginModule&lt;/em&gt; which uses another realm &lt;em&gt;ldap&lt;/em&gt; (custom &lt;em&gt;LDAPRealm&lt;/em&gt; but with minimal differences from the glassfish default) to search the user and his groups in the LDAP repository. In my opinion glassfish realms and login modules are too dependent on each other, they always generate cross references, and that generates some mess.&lt;/p&gt;

&lt;p&gt;So now everything is correctly configured to deploy a JavaEE security application which uses client certificates. I deployed the same application that was used in the custom security entry, but now it does not need all ldap stuff so it is almost an empty app (only some facelets pages and little helper Java classes). The interesting part of this application is inside the descriptor (&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/web.xml&quot;&gt;web.xml&lt;/a&gt;) file. It defines the following constraint:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;security-constraint&amp;gt;
        &amp;lt;display-name&amp;gt;CertSecurityJavaEE constraint&amp;lt;/display-name&amp;gt;
        &amp;lt;web-resource-collection&amp;gt;
            &amp;lt;web-resource-name&amp;gt;Servlet Application&amp;lt;/web-resource-name&amp;gt;
            &amp;lt;url-pattern&amp;gt;/faces/*&amp;lt;/url-pattern&amp;gt;
        &amp;lt;/web-resource-collection&amp;gt;
        &amp;lt;auth-constraint&amp;gt;
            &amp;lt;role-name&amp;gt;allusers&amp;lt;/role-name&amp;gt;
        &amp;lt;/auth-constraint&amp;gt;
        &amp;lt;user-data-constraint&amp;gt;
           &amp;lt;transport-guarantee&amp;gt;CONFIDENTIAL&amp;lt;/transport-guarantee&amp;gt;
        &amp;lt;/user-data-constraint&amp;gt;
    &amp;lt;/security-constraint&amp;gt;
&lt;/pre&gt;

&lt;p&gt;All faces pages (pattern &lt;em&gt;/faces/*&lt;/em&gt;) are declared inside the constraint. The role &lt;em&gt;allusers&lt;/em&gt; is declared as needed to access the application (any user authenticated in the realm). Besides the constraint declares the data as confidential, this means that the application has to be used securely (over HTTPS). The login part is as follows:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;login-config&amp;gt;
        &amp;lt;auth-method&amp;gt;CLIENT-CERT&amp;lt;/auth-method&amp;gt;
        &amp;lt;realm-name&amp;gt;ldap&amp;lt;/realm-name&amp;gt;
        &amp;lt;form-login-config&amp;gt;
            &amp;lt;form-login-page&amp;gt;/faces/login.xhtml&amp;lt;/form-login-page&amp;gt;
            &amp;lt;form-error-page&amp;gt;/faces/login.xhtml&amp;lt;/form-error-page&amp;gt;
        &amp;lt;/form-login-config&amp;gt;
    &amp;lt;/login-config&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I declared &lt;em&gt;CLIENT-CERT&lt;/em&gt; which means the user needs to present a certificate to get access (as I said glassfish uses the &lt;em&gt;certificate&lt;/em&gt; realm for this configuration, and all the previous configuration comes into stage). And finally some roles are defined for the application:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;security-role&amp;gt;
        &amp;lt;description&amp;gt;Users Role&amp;lt;/description&amp;gt;
        &amp;lt;role-name&amp;gt;allusers&amp;lt;/role-name&amp;gt;
    &amp;lt;/security-role&amp;gt;
    &amp;lt;security-role&amp;gt;
        &amp;lt;description&amp;gt;StaticGroup1 Role&amp;lt;/description&amp;gt;
        &amp;lt;role-name&amp;gt;StaticGroup1&amp;lt;/role-name&amp;gt;
    &amp;lt;/security-role&amp;gt;
    &amp;lt;security-role&amp;gt;
        &amp;lt;description&amp;gt;DynGroupPreSales Role&amp;lt;/description&amp;gt;
        &amp;lt;role-name&amp;gt;DynGroupPreSales&amp;lt;/role-name&amp;gt;
    &amp;lt;/security-role&amp;gt;
    &amp;lt;security-role&amp;gt;
        &amp;lt;description&amp;gt;SampleClient1 Role&amp;lt;/description&amp;gt;
        &amp;lt;role-name&amp;gt;SampleClient1&amp;lt;/role-name&amp;gt;
    &amp;lt;/security-role&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The application manages four roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;allusers&lt;/em&gt;: All the users of the application (any authenticated user).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;StaticGroup1&lt;/em&gt;: The static group of the ldap (I used it in the previous entry).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;DynGroupPreSales&lt;/em&gt;: The dynamic group of the ldap (I also used it before).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SampleClient1&lt;/em&gt;: This is an example user role, only the &lt;em&gt;SampleClient1&lt;/em&gt; is part of this role. I added this role to check if my login module handles user short login name (&lt;em&gt;UID&lt;/em&gt; in LDAP) correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I said glassfish used a specific &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/glassfish-web.xml&quot;&gt;glassfish-web.xml&lt;/a&gt; descriptor file to map the roles against the users and groups in the realm, here it is my mapping:&lt;/p&gt;

&lt;pre&gt;
  &amp;lt;security-role-mapping&amp;gt;
    &amp;lt;role-name&amp;gt;allusers&amp;lt;/role-name&amp;gt;
    &amp;lt;group-name&amp;gt;allusers&amp;lt;/group-name&amp;gt;
  &amp;lt;/security-role-mapping&amp;gt;
  &amp;lt;security-role-mapping&amp;gt;
    &amp;lt;role-name&amp;gt;StaticGroup1&amp;lt;/role-name&amp;gt;
    &amp;lt;group-name&amp;gt;StaticGroup1&amp;lt;/group-name&amp;gt;
  &amp;lt;/security-role-mapping&amp;gt;
  &amp;lt;security-role-mapping&amp;gt;
    &amp;lt;role-name&amp;gt;DynGroupPreSales&amp;lt;/role-name&amp;gt;
    &amp;lt;group-name&amp;gt;DynGroupPreSales&amp;lt;/group-name&amp;gt;
  &amp;lt;/security-role-mapping&amp;gt;
  &amp;lt;security-role-mapping&amp;gt;
    &amp;lt;role-name&amp;gt;SampleClient1&amp;lt;/role-name&amp;gt;
    &amp;lt;principal-name&amp;gt;SampleClient1&amp;lt;/principal-name&amp;gt;
  &amp;lt;/security-role-mapping&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Basically I mapped all roles to the so-called LDAP group (remember &lt;em&gt;allusers&lt;/em&gt; is a nonexistent ldap group, which is automatically added by the realm when a user is authenticated, it was defined in the &lt;em&gt;assign-groups&lt;/em&gt; property of both realms) except &lt;em&gt;SampleClient1&lt;/em&gt; which is mapped against the same username (I used the short CN name, the one that is added by my custom login module).&lt;/p&gt;

&lt;p&gt;Now the application is ready, but please think about it, how does it work? When the user access to the application he needs to present a certificate (it is compulsory) and there is no other choice. As you can imagine this is too much restrictive in common situations. In other JavaEE containers a fallback authentication method can be configured (&lt;em&gt;CLIENT-CERT,FORM&lt;/em&gt; for example in weblogic) but not in glassfish. So I decided to deploy the same application twice, one with &lt;em&gt;CLIENT-CERT&lt;/em&gt; authentication (&lt;em&gt;/CertSecurityJavaEE-cert&lt;/em&gt; context) and the other with &lt;em&gt;FORM&lt;/em&gt; (&lt;em&gt;/CertSecurityJavaEE&lt;/em&gt; context). If you check the previously presented login part of the &lt;em&gt;web.xml&lt;/em&gt; the &lt;em&gt;ldap&lt;/em&gt; realm is specified (remember that glassfish uses &lt;em&gt;certificate&lt;/em&gt; realm for &lt;em&gt;CLIENT-CERT&lt;/em&gt; authorization no matter the configuration, so this &lt;em&gt;ldap&lt;/em&gt; realm is only used when &lt;em&gt;FORM&lt;/em&gt; authentication is selected). In order to use my custom &lt;em&gt;LDAPRealm&lt;/em&gt; class here I needed to implement a custom &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/LDAPLoginModule.java&quot;&gt;LDAPLoginModule.java&lt;/a&gt; that extends &lt;a href=&quot;http://java.net/projects/glassfish/sources/svn/content/tags/3.1.1/security/core/src/main/java/com/sun/enterprise/security/auth/login/LDAPLoginModule.java&quot;&gt;glassfish default&lt;/a&gt; (because the damned cross references), but you can ignore this, it is too confusing even for me who implemented the solution.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;CLIENT-CERT&lt;/em&gt; option makes unnecessary the client authentication configuration we did in the secure listener of glassfish (check the first entry of this series). If &lt;em&gt;CLIENT-CERT&lt;/em&gt; authentication method is established for an application the app server automatically requests a client certificate for its context in the secure port. So I unchecked this option and now a user without certificate is able to access the &lt;em&gt;FORM&lt;/em&gt; defined application through the same secure port (the other &lt;em&gt;/CertSecurityJavaEE&lt;/em&gt; context). Besides an HTML error page for 401 error code (Unauthorized) was configured for the application. What does it mean? Now a user who presents a certificate in &lt;em&gt;/CertSecurityJavaEE-cert&lt;/em&gt; but has no mapped user in the LDAP server will receive a custom 401 error page, this page will show a link against the &lt;em&gt;FORM&lt;/em&gt; authenticated application. This is configured (standard way) in the &lt;em&gt;web.xml&lt;/em&gt; file.&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;error-page&amp;gt;
        &amp;lt;error-code&amp;gt;401&amp;lt;/error-code&amp;gt;
        &amp;lt;location&amp;gt;/resources/errorpages/401.html&amp;lt;/location&amp;gt;
    &amp;lt;/error-page&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Here it is the video. Now when I access to the certificate application (&lt;em&gt;/CertSecurityJavaEE-cert&lt;/em&gt;) a certificate is requested. Same as before if I select the revoked certificate (03) firefox requests me to choose another one because it is revoked, if I pick up the valid one (02) I just enter as &lt;em&gt;SampleClient1&lt;/em&gt; (see all the roles are granted and the long certificate subject is used as username). Now I cannot logout cos once you have selected a certificate for a site the browser uses always it for this site (it is the same case than in custom security). Then I clear my sessions in firefox (this logs me out to try again) and I try to enter with a new certificate, created for &lt;em&gt;SampleClient3&lt;/em&gt; with serial number 05 but without a mapped real user, so this time my login module fails to match a user and the 401 page is reached. There I can click the presented link and I access the non-certificate (&lt;em&gt;/CertSecurityJavaEE&lt;/em&gt;) application. Finally I log in using &lt;em&gt;SampleClient2&lt;/em&gt; (remember this user has a revoked certificate but he is a valid user in the LDAP server). He has no role assigned as expected and now the user name is the short one.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;The moral for standard JavaEE certificate login is that it depends on the container implementation, the application just needs to configure &lt;em&gt;CLIENT-CERT&lt;/em&gt; authentication. As you see glassfish realms (and the &lt;em&gt;certificate&lt;/em&gt; one particularly) are quite confusing, there is a lot of mess between realms and login modules and it is specially painful using or extending its default classes (I do not know why but they have a lot of private methods and they are usually declared as final). The best I could do was implementing a custom login module which was associated to the &lt;em&gt;certificate&lt;/em&gt; realm, this login class performs the mapping between certificate and user (groups included). Besides the application was deployed twice, one requests client certificates and the other uses typical username and password login, this way users without a certificate have a less secure but functional way to login. For this entry two projects were developed, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/CertLdapRealm.zip&quot;&gt;the library project with realms and login modules&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-StandardSolutionGlassfish/CertSecurityJavaEE.zip&quot;&gt;the Web Application project&lt;/a&gt;. My personal conclusion is that all of this is so particular for glassfish that a different entry like this one is needed for every JavaEE container. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/sad.png&quot; alt=&quot;:-(&quot; class=&quot;emoticon&quot; /&gt; &lt;/p&gt;

&lt;p&gt;You win some, you lose some. Cheerio!&lt;/p&gt;</description>
	<pubDate>mié, 09 nov 2011 10:33:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Certificate Security in JavaEE - Custom Solution</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/47-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/47-Certificate-Security-in-JavaEE-Custom-Solution.html</link>
	<description>&lt;p&gt;This entry is the second chapter of the JavaEE certificate security series. &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/46-Certificate-Security-in-JavaEE-Demo-Setup.html&quot;&gt;The previous post explained how all the environment was configured&lt;/a&gt; (OpenSSL demo CA and glassfish application server). Now it is time to deploy an application in the container and start using the certificates. This entry will deal with custom security, custom means that the application will use a repository for users and groups by its own, implementing the login classes and not JavaEE standard.&lt;/p&gt;

&lt;p&gt;Before commenting the application let's explain how a web application usually works with certificates. If you remember the first entry, the client certificate is validated by the application server (or the web server in general) before any code of the application is executed (in the video the certificate validation is performed even no application was already deployed in glassfish). Therefore it is concluded that when the request reaches the application the certificate is valid. Here the only problem that remains is who is the user which corresponds to this valid certificate. You have to think that usually a company is going to trust in some CA certs (for example, the national eID, &lt;a href=&quot;http://www.dnielectronico.es&quot;&gt;DNIe&lt;/a&gt; in case of Spain), but the registered users will be stored in a company repository (LDAP, DDBB or whatever). At this point the application needs someway to map certificates and users, usually some data in the issued certificate is used to match the user: some part of the certificate subject (usually the CN or the Email part), an attribute extension (some extra data included in the cert),... It does not matter what field, but the idea is some information stored in the cert will be used to find the real user in the repository (in the previous example of Spainsh eID the ID number, DNI number, would be a good candidate for matching users, obviously the DNI should be a compulsory field at customer/user registration process). &lt;/p&gt;

&lt;p&gt;The other question is when to perform this match between the certificate and the real user in the store, but this problem is solved as in any other login. In a web application with custom security any request should be intercepted to check if the user is logged in, if the request has no user information the user is redirected to the login page. In Java the user information is always stored in a session attribute (the application checks that the username and any other relevant information are inside the session) and the interceptor technique depends on the framework used (a typical &lt;a href=&quot;http://www.oracle.com/technetwork/java/filters-137243.html&quot;&gt;servlet filter&lt;/a&gt; can be the simplest one). If our application is going to use certificates, the interceptor code will also be responsible of matching the user, in case of a successful match the user will be automatically logged in without password prompting.&lt;/p&gt;

&lt;p&gt;In summary custom security needs to map the certificate against a real user inside the typical login interceptor code. My sample application uses an &lt;a href=&quot;http://www.openldap.org/&quot;&gt;OpenLDAP&lt;/a&gt; repository (LDAP is the most common repository for users and groups) and it is implemented using &lt;a href=&quot;http://en.wikipedia.org/wiki/JavaServer_Faces&quot;&gt;JSF (Java Server Faces)&lt;/a&gt; and &lt;a href=&quot;http://www.theserverside.com/news/1373391/Dependency-Injection-in-Java-EE-6-Part-1&quot;&gt;CDI (Context Dependency Injection)&lt;/a&gt;. Instead of a filter &lt;a href=&quot;http://mowyourlawn.com/blog/?p=6&quot;&gt;it will use a JSF phase listener&lt;/a&gt;, if there is a solution in the chosen framework for a specified problem it will always be the recommended way to go (do not mix technologies). The main files in the solution are the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/LoginBean.java&quot;&gt;LoginBean&lt;/a&gt; is a JSF session bean which is used to store the logged user information. As I said Java applications usually use the session to save the information associated with the logged user, in case of JSF, a session Bean is the direct solution.&lt;/p&gt;

&lt;p&gt;This bean has some important methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;login&lt;/em&gt;: The login action method performs typical login. The user introduces username and password in a login page and this page calls this method which finds and binds the user against the LDAP repository (the user is found and then the password is checked). This is the method executed in normal (non-certificate) login. I have used the &lt;a href=&quot;http://dlc.sun.com.edgesuite.net/javaee5/external/shared/ldapbp/jars/&quot;&gt;ldapbp library&lt;/a&gt; (typical Sun, now Oracle, LDAP library) in order to get the user and the groups easily. All the LDAP stuff is executed inside a &lt;a href=&quot;http://en.wikipedia.org/wiki/Singleton_pattern&quot;&gt;Singleton&lt;/a&gt; annotated &lt;a href=&quot;http://en.wikipedia.org/wiki/Enterprise_JavaBean&quot;&gt;EJB (Enterprise JavaBean)&lt;/a&gt; but forget this, it is just a way to acess the sample repository.&lt;/p&gt;

&lt;pre&gt;
public String login() {
    userEntry = ldap.findUser(username, password.toCharArray());
    groupsCache.clear();
    if (userEntry != null) {
        return &quot;index&quot;;
    } else {
        FacesUtils.errorMessage(&quot;loginForm:username&quot;, 
            &quot;login_invalid_username_or_password&quot;);
        return &quot;login&quot;;
    }
}
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;trustedLogin&lt;/em&gt;: Other method of the bean which performs the match between certificates and users. It receives the X509 certificate of the client and with the CN part of the Subject (I have implemented a very simple match condition) it searches the LDAP repository for a matching user. If a valid user is found the method automatically fulfills all the variables in the session bean. This method only executes the login process if the user is not previously logged in (avoiding useless searches and validations).&lt;/p&gt;

&lt;pre&gt;
public String trustedLogin(X509Certificate cert) {
    try {
        // only check if user not logged in
        if (!isLoggedIn()) {
            // get CN part =&gt; it's the last one
            LdapName name = new LdapName(cert.getSubjectDN().getName());
            String certName = name.getRdn(name.size() - 1).getValue().toString();
            // validate via PKIX if configured
            boolean certOK = !validatePKIX || validatePKIX(cert);
            if (certOK) {
                // login without password
                LdapEntry entry = ldap.findUser(certName, null);
                if (entry != null) {
                    username = certName;
                    userEntry = entry;
                    groupsCache.clear();
                }
            }
        }
    } catch (Exception e) {
        logger.error(&quot;Error performing the login&quot;, e);
    }
    return username;
}
&lt;/pre&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;isLoggedIn&lt;/em&gt;: Method that returns if there is an active session of some user. It only checks that the &lt;em&gt;username&lt;/em&gt; and &lt;em&gt;userEntry&lt;/em&gt; variables are filled (both vars are initialized by the two previous methods).

&lt;pre&gt;
public boolean isLoggedIn() {
    return username != null &amp;amp;&amp;amp; userEntry != null;
}
&lt;/pre&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;validatePKIX&lt;/em&gt;: This method &lt;a href=&quot;http://stackoverflow.com/questions/6143646/validate-x509-certificates-using-java-apis&quot;&gt;validates the certificate using OCSP and/or CRL programmatically&lt;/a&gt;. You know that in my demo environment this is already done by the container, but I decided to include this code here just in case of an hypothetical container which does not support these validations. The bean can be configured to perform this extra validation in previous &lt;em&gt;trustedLogin&lt;/em&gt; method, this way the container would do normal validation (trusted CA and valid dates) and the Java application would perform OCSP or CRL (this method uses exactly the same APIs than JSSE/glassfish).&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;isUserInGroup&lt;/em&gt;: The bean performs custom security, this is an equivalent method to standard &lt;a href=&quot;http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#isUserInRole%28java.lang.String%29&quot;&gt;isUserInRole&lt;/a&gt;. It returns &lt;em&gt;true&lt;/em&gt; if the user belongs to the specified LDAP group (static and dynamic groups can be passed because &lt;em&gt;ldapbp&lt;/em&gt; is used). Group membership is cached inside the &lt;em&gt;LoginBean&lt;/em&gt;.&lt;/p&gt;

&lt;pre&gt;
public boolean isUserInGroup(String groupname) {
    // check cache
    String key = groupname.toLowerCase();
    if (groupsCache.containsKey(key)) {
        return groupsCache.get(key);
    } else {
        // read from ldap and set into cache
        boolean res = ldap.isUserInGroup(this.userEntry.getDn(), groupname);
        groupsCache.put(key, res);
        return res;
    }
}
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;logout&lt;/em&gt;: Simple method to delete the session associated to this user.&lt;/p&gt;

&lt;pre&gt;
public String logout() {
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance(
        ).getExternalContext().getSession(false);
    if (session != null) {
        session.invalidate();
    }
    return &quot;logout&quot;;
}
&lt;/pre&gt;

&lt;/li&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;When using CDI for JSF Beans the &lt;em&gt;@ManagedProperty&lt;/em&gt; annotation cannot be used (and I used it a lot to initialize the beans before). In this sample application I tried to figure out how to initialize beans with Injection but I realized there is no direct solution, finally I used a properties file as it is commented in &lt;a href=&quot;http://weblogs.java.net/blog/jjviana/archive/2010/05/18/applicaction-configuration-java-ee-6-using-cdi-simple-example&quot;&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;li&gt;&lt;p&gt;The &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/CertLoginPhaseListener.java&quot;&gt;CertLoginPhaseListener&lt;/a&gt; interceptor. As I commented previously, using JSF the recommended solution for the login interceptor stuff is a JSF Phase Listener (see the link I presented before for further information). These listeners are always executed associated with a JSF request/response phase and therefore can be used as filters. The listener performs the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It recovers the certificate from the request (this is &lt;a href=&quot;http://download.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29&quot;&gt;the normal way of getting the associated certificate in a Java container&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;
X509Certificate[] certs = (X509Certificate[]) 
    req.getAttribute(&quot;javax.servlet.request.X509Certificate&quot;);
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If there is at least one certificate (the client is accessing via the secure https port) the listener calls &lt;em&gt;trustedLogin&lt;/em&gt; to automatically log the user in if it is the case. To do that programmatic &lt;a href=&quot;http://en.wikipedia.org/wiki/Expression_Language&quot;&gt;EL (Expression Language)&lt;/a&gt; is used.&lt;/p&gt;

&lt;pre&gt;
if (certs != null &amp;amp;&amp;amp; certs.length &gt; 0) {
    try {
        // login silently without password via certificate, the trustedLogin
        // performs the login if there is no previous session, certificate is valid
        // and the user is mapped against the ldap
        ExpressionFactory ef = facesContext.getApplication().getExpressionFactory();
        MethodExpression me = ef.createMethodExpression(facesContext.getELContext(),
                &quot;#{loginBean.trustedLogin}&quot;, null, new Class[]{X509Certificate.class});
        me.invoke(facesContext.getELContext(), new Object[]{certs[0]});
    } catch (Exception e) {
        logger.error(&quot;Error checking certificate&quot;, e);
    }
}
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;After that the listener calls &lt;em&gt;isUserLoggedIn&lt;/em&gt; just to check if there is an active session, again EL is used.&lt;/p&gt;

&lt;pre&gt;
ExpressionFactory ef = facesContext.getApplication().getExpressionFactory();
ValueExpression ve = ef.createValueExpression(facesContext.getELContext(), 
    &quot;#{loginBean.loggedIn}&quot;, Boolean.class);
boolean isLoggedIn = (Boolean) ve.getValue(facesContext.getELContext());
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally this &lt;em&gt;boolean&lt;/em&gt; variable can be true (the user previously logged in or he has been automatically logged in by the certificate method) or false (the user has never logged in and there is no certificate or it matched no user). Based on this variable the listener permits the user to continue or redirects him to the login page. It is quite interesting the case of a registered user who tries to access the login page, if this case happens the user is also redirected, but this time to main application page (avoiding any login). Besides if the client has a valid certificate but it did not match any user login page will be presented through the secure port.&lt;/p&gt;

&lt;pre&gt;
if (!loginPage &amp;amp;&amp;amp; !isLoggedIn) {
    // drive the user to the login page
    facesContext.getApplication().getNavigationHandler(
        ).handleNavigation(facesContext, null, &quot;login&quot;);
} else if (loginPage &amp;amp;&amp;amp; isLoggedIn) {
    // already login =&gt; go to main page
    facesContext.getApplication().getNavigationHandler(
        ).handleNavigation(facesContext, null, &quot;index&quot;);
}
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;li&gt;&lt;p&gt;The &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/login.xhtml&quot;&gt;login.xhtml&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/index.xhtml&quot;&gt;index.xhtml&lt;/a&gt; are the facelets pages for the login and the main page. Login is the typical username and password page and the main one simply shows the user logged in and if it belongs to an LDAP static and a dynamic group. These groups were previously loaded into the OpenLDAP repo (&lt;em&gt;SampleClient1&lt;/em&gt; belongs to both groups and &lt;em&gt;SampleClient2&lt;/em&gt; to none of them).&lt;/p&gt;&lt;/li&gt;
&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So today the video exemplifies all possible login methods. If the user accesses the application using non-secure port (8080) the listener detects no certificate and no logged user and it presents a common login page. In this page I log in using &lt;em&gt;SampleClient2&lt;/em&gt; (although his certificate is revoked he is a valid user in the LDAP repository, so he can access the application using normal login and password way). But if I access the https port (8181) and I use the revoked certificate glassfish denies the access. The second time I try with &lt;em&gt;SampleClient1&lt;/em&gt;, now the listener detects my certificate, matches it against the LDAP user (the Subject of this cert is &lt;em&gt;CN=SampleClient1,O=demo.kvm,C=ES&lt;/em&gt; and the CN part is used to find the associated user) and it fulfills the &lt;em&gt;LoginBean&lt;/em&gt; data to silently log me in. Finally the listener redirects the request to the index main page, &lt;em&gt;SampleClient1&lt;/em&gt; user and his groups are shown in the page. As I am using certificate login I cannot logout (the certificate is always detected and the user is logged when he has not an active session). In order to delete my login I clean my cookies and active logins in the browser and I try with another certificate, I created a new certificate for &lt;em&gt;SampleClient3&lt;/em&gt; but this user does not exists in the LDAP repository, this time the listener does not match any user to this new Subject CN and, therefore, login page is presented in the secure port. I enter again as &lt;em&gt;SampleClient2&lt;/em&gt;.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;In summary using certificates as a login method in a custom security application is not very complicated. Mapping the certificate to a real application user is the main part, and, in a custom security application, it is done in the same place in which login interception is done. My &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-CustomSolution/CertSecurityCustom.zip&quot;&gt;sample application NetBeans project can be downloaded&lt;/a&gt; and it just performs all of this with JSF and a phase listener, the users and groups are placed in an OpenLDAP server and the &lt;em&gt;ldapbp&lt;/em&gt; library is used to retrieve group membership easily, the application maps the certificate via the CN part of the subject. Although the application is very simple I think it exemplifies perfectly a certificate login using custom security. Some days ago (when I had already implemented this demo application but not published the entry) I faced a customer who had tried to do the same in a very very weird way (I better do not comment this), that reassured me in publishing this series. Take into account that, although the entry implements the certificate security in Java, it rules in any web application (PHP, Rails, Python or whatever).&lt;/p&gt;

&lt;p&gt;Remember to be smart!&lt;/p&gt;</description>
	<pubDate>sáb, 22 oct 2011 14:38:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Certificate Security in JavaEE - Demo Setup</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/46-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/46-Certificate-Security-in-JavaEE-Demo-Setup.html</link>
	<description>&lt;p&gt;Some days ago I was discussing with a colleague what would be the best way to get certificate security in a JavaEE application. We did not reach any final conclusion so I decided to start a demo environment to test some simple cases. In this post the environment is going to be setup, the CA and the Application Server.&lt;/p&gt;

&lt;p&gt;In order to get a complete infrastructure a &lt;a href=&quot;http://en.wikipedia.org/wiki/Certificate_authority&quot;&gt;CA (Certificate Authority)&lt;/a&gt; with &lt;a href=&quot;http://en.wikipedia.org/wiki/Certificate_revocation_list&quot;&gt;CRL (Certificate Revokation List)&lt;/a&gt; publication and/or &lt;a href=&quot;http://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol&quot;&gt;OCSP (Online Certificate Status Protocol)&lt;/a&gt; checking is needed. As I explained in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/12-Signature-Applet.html&quot;&gt;the first post of the signing applet series&lt;/a&gt; a CA is a trusted company which issues certificates. The other two concepts are mechanisms for validating certificates or, more precisely, to know if a certificate has been revoked. A CRL is a list of revoked certificates and this list is usually accessed via internet. OCSP is a standard protocol to check certificates online. It is clear if some application is going to trust in user certificates, there should be someway to deal with revocations.&lt;/p&gt;

&lt;p&gt;I decided to use &lt;a href=&quot;http://www.openssl.org&quot;&gt;openssl&lt;/a&gt; as a simple but complete CA infrastructure. The famous security library also has some CA capabilities which are perfect for a demo environment. As the JavaEE container I setup Glassfish 3.1.1 (but I think the concepts are valid for any other app server). Of course Debian Squeeze is the chosen OS (installed as a KVM virtual box). The steps for creating the complete infrastructure are the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Creation and configuration of the OpenSSL CA&lt;/span&gt;. For this point I followed &lt;a href=&quot;http://www.phildev.net/ssl/creating_ca.html&quot;&gt;this helpful web page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First of all, openssl package is installed:&lt;/p&gt;

&lt;pre&gt;
# apt-get install openssl
&lt;/pre&gt;

&lt;p&gt;After that the file &lt;em&gt;/etc/ssl/openssl.cnf&lt;/em&gt; has to be modified. Here it is &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-DemoSetup/openssl.cnf&quot;&gt;my modified file&lt;/a&gt; but basically only two options were added to &lt;em&gt;[usr_cert]&lt;/em&gt; section:&lt;/p&gt;

&lt;pre&gt;
authorityInfoAccess = OCSP;URI:http://debian.demo.kvm:3456/
crlDistributionPoints = URI:http://debian.demo.kvm/my.crl
&lt;/pre&gt;

&lt;p&gt;This options add the OCSP and CRL information to the certificate. Both techniques have to be explicitly added to the generated certificates, this way, when something (a browser, app server or whatever) reads the certificate it can check its validity against the specified URLs. As you see my debian demo box is called &lt;em&gt;debian.demo.kvm&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Some directories needed by the CA configuration are created now (CA was located inside &lt;em&gt;/etc/ssl/demoCA&lt;/em&gt; directory which is also specified in &lt;em&gt;openssl.cnf&lt;/em&gt;):&lt;/p&gt;

&lt;pre&gt;
# cd /etc/ssl
# mkdir -p demoCA/newcerts
&lt;/pre&gt;

&lt;p&gt;Some files are also initialized:&lt;/p&gt;

&lt;pre&gt;
# touch /etc/ssl/demoCA/index.txt
# echo 01 &gt; /etc/ssl/demoCA/serial
# echo 01 &gt; /etc/ssl/demoCA/crlnumber
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Creation of the CA certificate&lt;/span&gt;. In this second step the CA certificate is generated (directory is always &lt;em&gt;/etc/ssl&lt;/em&gt; if not specified). The certificate is requested:&lt;/p&gt;

&lt;pre&gt;
# cd /etc/ssl
# openssl req -subj &quot;/C=ES/O=demo.kvm/CN=ca.demo.kvm&quot; -new -newkey rsa:2048 \
  -keyout private/cakey.pem -out careq.pem
Generating a 2048 bit RSA private key
...............................................................+++
.........................+++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
&lt;/pre&gt;

&lt;p&gt;Now the certificate is self-signed against the CA. Please check the extensions &lt;em&gt;v3_ca&lt;/em&gt; option, this is the CA cert and it should not contain OCSP or CRL info (this option makes the command to use the other &lt;em&gt;v3_ca&lt;/em&gt; section which does not contain OCSP or CRL info).&lt;/p&gt;

&lt;pre&gt;
# openssl ca -out cacert.pem -days 365 -keyfile private/cakey.pem -selfsign \
  -extensions v3_ca -infiles careq.pem 
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Sep 16 16:38:41 2011 GMT
            Not After : Sep 15 16:38:41 2012 GMT
        Subject:
            countryName               = ES
            organizationName          = demo.kvm
            commonName                = ca.demo.kvm
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                BC:39:85:FF:DB:6E:46:FF:08:52:32:6F:97:65:91:F6:F4:A9:24:E7
            X509v3 Authority Key Identifier: 
                keyid:BC:39:85:FF:DB:6E:46:FF:08:52:32:6F:97:65:91:F6:F4:A9:24:E7
                DirName:/C=ES/O=demo.kvm/CN=ca.demo.kvm
                serial:01

            X509v3 Basic Constraints: 
                CA:TRUE
Certificate is to be certified until Sep 15 16:38:41 2012 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
&lt;/pre&gt;

&lt;p&gt;Finally the CA cert is exported in DER format (DER format will be better for JKS stores in glassfish) and in PKCS#12 format (a p12 file contains the keys and the certificate, so it can be considered as a backup).&lt;/p&gt;

&lt;pre&gt;
# openssl x509 -in cacert.pem -outform DER -out cacert.der
# openssl pkcs12 -export -out cacert.p12 -in cacert.pem -inkey private/cakey.pem 
Enter pass phrase for private/cakey.pem:
Enter Export Password:
Verifying - Enter Export Password:
&lt;/pre&gt;

&lt;p&gt;The first certificate (the CA one) is ready. This certificate will be used to sign all the others (users and glassfish server).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Creation of two client certificates&lt;/span&gt;. Once the CA cert is generated two client certs are going to be issued, the procedure is very similar but, when signed, the CA certificate is used (instead of self-signing) and now no extensions option is specified (now &lt;em&gt;user_cert&lt;/em&gt; section will be used, with OCSP and CRL info). Again in this point I followed &lt;a href=&quot;http://gagravarr.org/writing/openssl-certs/ca.shtml&quot;&gt;another tutorial&lt;/a&gt;, in this case the rsa keys were generated first and then the certificate was requested, created and transformed to DER and PKCS#12.&lt;/p&gt;

&lt;pre&gt;
# openssl genrsa -out private/client1.key 1024
# openssl req -subj &quot;/C=ES/O=demo.kvm/CN=SampleClient1&quot; -key private/client1.key \
  -new -out client1.req
# openssl ca -in client1.req -cert cacert.pem -keyfile private/cakey.pem -out client1.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Sep 16 16:42:31 2011 GMT
            Not After : Sep 15 16:42:31 2012 GMT
        Subject:
            countryName               = ES
            organizationName          = demo.kvm
            commonName                = SampleClient1
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                36:24:6E:0E:9B:A4:30:FA:85:7B:59:0D:35:DE:09:F0:C1:89:4B:D6
            X509v3 Authority Key Identifier: 
                keyid:BC:39:85:FF:DB:6E:46:FF:08:52:32:6F:97:65:91:F6:F4:A9:24:E7

            Authority Information Access: 
                OCSP - URI:http://debian.demo.kvm:3456/

            X509v3 CRL Distribution Points: 
                URI:http://debian.demo.kvm/my.crl

Certificate is to be certified until Sep 15 16:42:31 2012 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

# openssl x509 -in client1.pem -outform DER -out client1.der
# openssl pkcs12 -export -out client1.p12 -in client1.pem -inkey private/client1.key
Enter pass phrase for private/client1.pem:
Enter Export Password:
Verifying - Enter Export Password:
&lt;/pre&gt;

&lt;p&gt;Doing the same steps a second certificate (client2) was generated. But, in this case, the certificate was then revoked (this way we have a valid and an invalid user certificate for testing).&lt;/p&gt;

&lt;pre&gt;
# openssl ca -revoke client2.pem -keyfile private/cakey.pem -cert cacert.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for private/cakey.pem:
Revoking Certificate 3.
Data Base Updated
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Installing a certificate for glassfish&lt;/span&gt;. Another necessary certificate is the one for the application server ssl socket, working with user certificates always needs a server-side https connection. New version v3 of glassfish only uses JKS java store (so forget about the NSS certificate store which I commented in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/34-Glassfish-Enterprise-Profile-on-Linux-amd64.html&quot;&gt;a previous entry about 2.1.1 version&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The first thing to do is installing java JDK. In debian you need to add the &lt;em&gt;non-free&lt;/em&gt; debian repository in the &lt;em&gt;/etc/apt/sources.list&lt;/em&gt; and install the oracle (closed-source) package:&lt;/p&gt;

&lt;pre&gt;
# apt-get install sun-java6-jdk
&lt;/pre&gt;

&lt;p&gt;If you prefer OpenJDK (open-source) implementation you need to install another package instead (I did not test it but I am sure it would also work smoothly):&lt;/p&gt;

&lt;pre&gt;
# apt-get install openjdk-6-jdk
&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;http://glassfish.java.net/downloads/3.1.1-final.html&quot;&gt;Glassfish 3.1.1 was downloaded&lt;/a&gt;, the full platform ZIP file, and installed (uncompressing the file is the only step). In the virtual debian box glassfish was installed in &lt;em&gt;/opt&lt;/em&gt; directory:&lt;/p&gt;

&lt;pre&gt;
# cd /opt
# unzip ${DOWNLOAD_DIR}/glassfish-3.1.1.zip
# cd /opt/glassfish3/bin
# ./asadmin start-domain
&lt;/pre&gt;

&lt;p&gt;As you see ZIP installation contains a local &lt;em&gt;domain1&lt;/em&gt; domain already configured. The certificate stores are placed in the &lt;em&gt;glassfish/domains/domain1/config&lt;/em&gt; directory. The &lt;em&gt;keystore.jks&lt;/em&gt; file is the store for server certificates and &lt;em&gt;cacerts.jks&lt;/em&gt; the store for trusted CA certificates. Now it is the time to request a new certificate for the https port (glassfish always configures a secure port, port 8181 by default, with a self-signed &lt;em&gt;s1as&lt;/em&gt; certificate, which is going to be replaced).&lt;/p&gt;

&lt;p&gt;The certificate (called &lt;em&gt;server&lt;/em&gt;) is created without password (RETURN was pressed):&lt;/p&gt;

&lt;pre&gt;
# keytool -genkey -alias server -keyalg RSA -keysize 1024 -keystore keystore.jks \
  -dname &quot;CN=debian.demo.kvm,OU=GlassFish,O=demo.kvm,C=ES&quot;
Enter keystore password:  
Enter key password for &amp;lt;server&amp;gt;
	(RETURN if same as keystore password):  
&lt;/pre&gt;

&lt;p&gt;Then the request file is generated:&lt;/p&gt;

&lt;pre&gt;
# keytool -certreq -alias server -keyalg RSA -file /etc/ssl/server.req -keystore keystore.jks
Enter keystore password:  
Enter key password for &amp;lt;server&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Now it is time to sign the request with our CA. Again &lt;em&gt;user_cert&lt;/em&gt; section is used, so OCSP and CRL information will be also added to this certificate (this is not necessary but it is quite nice). The server has to be transformed to DER format to be used in JKS.&lt;/p&gt;

&lt;pre&gt;
# cd /etc/ssl
# openssl ca -in server.req -cert cacert.pem -keyfile private/cakey.pem -out server.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 4 (0x4)
        Validity
            Not Before: Sep 16 16:56:14 2011 GMT
            Not After : Sep 15 16:56:14 2012 GMT
        Subject:
            countryName               = ES
            organizationName          = demo.kvm
            organizationalUnitName    = GlassFish
            commonName                = debian.demo.kvm
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                36:33:F0:39:B6:3C:71:29:E3:0D:25:76:6F:70:46:EE:E5:73:97:C6
            X509v3 Authority Key Identifier: 
                keyid:BC:39:85:FF:DB:6E:46:FF:08:52:32:6F:97:65:91:F6:F4:A9:24:E7

            Authority Information Access: 
                OCSP - URI:http://debian.demo.kvm:3456/

            X509v3 CRL Distribution Points: 
                URI:http://debian.demo.kvm/my.crl

Certificate is to be certified until Sep 15 16:56:14 2012 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

# openssl x509 -in server.pem -outform DER -out server.der
&lt;/pre&gt;

&lt;p&gt;And finally the certificate is imported into the &lt;em&gt;keystore.jks&lt;/em&gt; glassfish store. Cos the certificate is signed by an unknown CA the cacert is also imported in both (user and trusted CA files). So now three commands are executed: import CA file in &lt;em&gt;cacerts.jks&lt;/em&gt;, import CA file into &lt;em&gt;keystore.jks&lt;/em&gt; and finally import the new server certificate in &lt;em&gt;keystore.jks&lt;/em&gt;.&lt;/p&gt;

&lt;pre&gt;
# cd /opt/glassfish3/glassfish/domains/domain1/config
# keytool -import -trustcacerts -alias myca -file /etc/ssl/cacert.der -keystore cacerts.jks
Enter keystore password:  
Owner: CN=ca.demo.kvm,O=demo.kvm,C=ES
Issuer: CN=ca.demo.kvm,O=demo.kvm,C=ES
...
Trust this certificate? [no]:  yes
Certificate was added to keystore

# keytool -import -trustcacerts -alias myca -file /etc/ssl/cacert.der -keystore keystore.jks
Enter keystore password:  
Owner: CN=ca.demo.kvm,O=demo.kvm,C=ES
Issuer: CN=ca.demo.kvm,O=demo.kvm,C=ES
...
Trust this certificate? [no]:  yes
Certificate was added to keystore

# keytool -import -alias server -file /etc/ssl/server.der -keystore keystore.jks
Enter keystore password:  
Certificate reply was installed in keystore
&lt;/pre&gt;

&lt;p&gt;At this point we have a valid certificate with the alias &lt;em&gt;server&lt;/em&gt; ready to be used in the https listener. In the glassfish console (&lt;em&gt;http://debian.demo.kvm:4848&lt;/em&gt;) we select &lt;em&gt;Configuration â†’ server config â†’ Network Config â†’ http-listener-2&lt;/em&gt;. Here we see that security is enable in this listener, clicking the &lt;em&gt;SSL&lt;/em&gt; tab the &lt;em&gt;Client Authentication&lt;/em&gt; checkbox is selected and in the &lt;em&gt;Certificate Nickname&lt;/em&gt; current auto-generated certificate &lt;em&gt;s1as&lt;/em&gt; is changed for the new &lt;em&gt;server&lt;/em&gt; alias.&lt;/p&gt;

&lt;div&gt;
&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-DemoSetup/glassfish-ssl-config.png&quot; alt=&quot;Glassfish SSL configuration&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;This change does not need a reboot of the server. At this moment the 8181 port is using the new certificate (&lt;em&gt;server&lt;/em&gt; alias) but it is also demanding a user certificate (so you only access the welcome page if a user certificate is installed in the browser, it will be done in the last step).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Publication of the CRL and setup of the OCSP server&lt;/span&gt;. The main idea of this demo is that the Application Server (glassfish) was able to validate user certficates. To do that both OCSP and CRL techniques are going to be available.&lt;/p&gt;

&lt;p&gt;Openssl has a minimal (only recommended for testing) OCSP server, &lt;a href=&quot;http://backreference.org/2010/05/09/ocsp-verification-with-openssl/&quot;&gt; we can start the process directly from the command line&lt;/a&gt;. As we have specified port 3456 in the certificate URI the daemon is started as follows (the &lt;em&gt;-text&lt;/em&gt; option dumps communication to the terminal):&lt;/p&gt;

&lt;pre&gt;
# cd /etc/ssl
# openssl ocsp -index demoCA/index.txt -CA cacert.pem -rsigner cacert.pem \
  -rkey private/cakey.pem -port 3456 -text
Enter pass phrase for private/cakey.pem:
Waiting for OCSP client connections...
&lt;/pre&gt;

&lt;p&gt;This way the client certificates can now be checked. The validation process uses the serial number of the certificate (a kind of identifier the CA assigns for every certificate). In the first step a &lt;em&gt;serial&lt;/em&gt; file was initialized to 0x1, this way the CA has been assigning a consecutive number to each generated certificate (0x1 for cacert, 0x2 for client1, 0x3 for client2 and 0x4 for server). The client1 certificate (0x2) is a good one:&lt;/p&gt;

&lt;pre&gt;
# openssl ocsp -issuer cacert.pem -nonce -CAfile cacert.pem \
  -url http://localhost:3456 -serial &quot;0x2&quot;
Response verify OK
0x2: good
	This Update: Sep 16 16:51:49 2011 GMT
&lt;/pre&gt;

&lt;p&gt;But the client2 certificate (0x3) is revoked:&lt;/p&gt;

&lt;pre&gt;
# openssl ocsp -issuer cacert.pem -nonce -CAfile cacert.pem \
  -url http://localhost:3456 -serial &quot;0x3&quot;
Response verify OK
0x3: revoked
	This Update: Sep 16 16:51:51 2011 GMT
	Revocation Time: Sep 16 16:50:19 2011 GMT
&lt;/pre&gt;

&lt;p&gt;CRL is a complementary way of validating certificates, it can be intended as a secondary method to use in case of an OCSP error. The CRL (revocation certificate list) is downloaded using standard http by the checkers (app server, browser,...). This way I decided to install an apache server in the box and then copy the generated file inside document root directory.&lt;/p&gt;

&lt;pre&gt;
# apt-get install apache2
&lt;/pre&gt;

&lt;p&gt;After that the CRL list is generated using openssl:&lt;/p&gt;

&lt;pre&gt;
# cd /etc/ssl
# openssl ca -gencrl -keyfile private/cakey.pem -cert cacert.pem -out my.crl
&lt;/pre&gt;

&lt;p&gt;And it is copied to the apache2 root directory in debian:&lt;/p&gt;

&lt;pre&gt;
# cp /etc/ssl/my.crl /var/www/my.crl
&lt;/pre&gt;

&lt;p&gt;If you check the previous URL set in the certificate was &lt;em&gt;http://debian.demo.kvm/my.crl&lt;/em&gt; which is exactly where my CRL is now. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt; &lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;CRL and OCSP checking in the glassfish server&lt;/span&gt;. By default glassfish server only checks the CA, it must be a trusted one (that is why cacert was imported to &lt;em&gt;cacerts.jks&lt;/em&gt; store) and dates, but it does not validate revocations (neither OCSP nor CRL). &lt;a href=&quot;http://weblogs.java.net/blog/kumarjayanti/archive/2007/11/ssl_and_crl_che.html&quot;&gt;This entry explains how to do it in glassfish v2&lt;/a&gt; but it also works in v3 (the solution consists in activating the checking in JSSE implementation which I suppose works in any server that uses this ssl socket layer).&lt;/p&gt;

&lt;p&gt;In the glassfish console &lt;em&gt;Configurations â†’ server-config â†’ JVM Settings â†’ JVM Options tab&lt;/em&gt; two new options have to be set (&lt;em&gt;-Dcom.sun.net.ssl.checkRevocation=true&lt;/em&gt; and &lt;em&gt;-Dcom.sun.security.enableCRLDP=true&lt;/em&gt;). Restart is required when JVM options are modified.&lt;/p&gt;

&lt;div&gt;
&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-DemoSetup/glassfish-jvm-options.png&quot; alt=&quot;Glassfish JVM options&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;But this options only activate CRL checking and not OCSP. In order to finally have all the validation methods the &lt;em&gt;/usr/lib/jvm/java-6-sun/jre/lib/security/java.security&lt;/em&gt; has to be modified uncommenting the following line (please think that this path varies depending where your JDK is installed, this is the default path for debian Oracle JDK):&lt;/p&gt;

&lt;pre&gt;
ocsp.enable=true
&lt;/pre&gt;

&lt;p&gt;If you check in this file there are more options to customize ocsp validation (I did not spend more time on this).&lt;/p&gt;

&lt;p&gt;Finally glassfish is ready to receive and validate client certificates using both techniques. Java implementation first tries OCSP protocol and, if it fails, the CRL is downloaded (check commented post for further info).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Setting up client certificates&lt;/span&gt;. Now all the server side is ready but our browser needs some certificates, client1 and client2. If you remember both were exported in PKCS#12 format and both p12 files can be directly imported to firefox. Of course remember to also import the &lt;em&gt;cacert.der&lt;/em&gt; as a trusted CA. &lt;/p&gt;

&lt;p&gt;In firefox (iceweasel) 5.0 &lt;em&gt;Edit â†’ Preferences â†’ Advanced Tab â†’ Encryption subtab â†’ View Certificates&lt;/em&gt;. In &lt;em&gt;Your Certificates&lt;/em&gt; tab click the &lt;em&gt;Import&lt;/em&gt; button and select &lt;em&gt;client1.p12&lt;/em&gt; and &lt;em&gt;client2.p12&lt;/em&gt; (the password that you inserted when the certificates were exported is requested at this point).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;cacert.der&lt;/em&gt; is imported in the same window but in &lt;em&gt;Authorities&lt;/em&gt; tab. There click again &lt;em&gt;Import&lt;/em&gt;. Check all the trust settings (web sites, email users and software) when requested.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally all the environment (server and client) is ready to access the glassfish secure port. In the following video I first show that my two certificates are imported and the CA is trusted. Then I access the 8181 port of my debian box, as client certificate was configured the browser asks me which one to use, but I select the revoked certificate (see it has the 03 serial). So the glassfish server does not permit the access (it is revoked!). Trying again I select the other certificate (02 serial) and, this time, welcome glassfish page is shown.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CertificateSecurityinJavaEE-DemoSetup/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;If you recheck this entry I have not done anything yet. Only the environment is ready and no application is deployed inside glassfish. At first moment I was not going to post the setup but it needed so many steps and particular options that I finally decided to publish this entry. Entries in this blog are many times posted just for me, because I want to have a clear guide of what I did. This is one of these times, but of course it is also here for anyone who finds it useful. I have two more entries in mind. In the first one I will try to deploy a custom security application (not using JavaEE security but programmatic). And in the second JavaEE security will be incorporated. But you know, it will depend on my mood and my time.&lt;/p&gt;

&lt;p&gt;Don't change the channel!&lt;/p&gt;</description>
	<pubDate>sáb, 08 oct 2011 13:27:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Tomcat 7 and the Invoker Servlet</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/44-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/44-Tomcat-7-and-the-Invoker-Servlet.html</link>
	<description>&lt;p&gt;Some weeks ago I was on vacation and spent some days in my home town. One afternoon I was with an ex-colleague who requested my help to migrate a Tomcat application (you know, with friends like that...). In summary the application was a huge (lots of classes) and old (I think it runs right now in tomcat 4.1) servlet and JSP web app. He was trying to migrate it to a newer version of tomcat (6 or 7) but he is not a specialist in this matter.&lt;/p&gt;

&lt;p&gt;In summary the main problem was that this application uses the &lt;a href=&quot;http://tomcat.apache.org/tomcat-4.1-doc/catalina/funcspecs/fs-invoker.html&quot;&gt;Invoker Servlet&lt;/a&gt; which I did not even known before. It is a strange Servlet used in previous versions of tomcat which is now deprecated in version 6 and totally removed in 7. It seems that the Invoker is a dynamic servlet which allows run-time loading of other servlets based on class name. Currently &lt;a href=&quot;http://www.coderanch.com/how-to/java/InvokerServlet&quot;&gt;it is considered evil&lt;/a&gt; and that is the reason for its deprecation and clean up. I thought this Servlet needed to be removed but my mate explained me that the application had dozens and dozens of servlets (and references in JPSs too) and it would be a total nightmare. So, focusing in version 6 and after some configurations changes, the application started successfully in tomcat 6 and it begun to work using the Invoker Servlet. My friend still had (and has) a lot of work to do but he needed this little push to start on. Then he kindly paid the beers I deserved. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But turning the issue over in my mind later I decided to find a direct way to replace the Invoker Servlet in tomcat 7. Obviously you can workaround the problem just getting &lt;a href=&quot;http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/InvokerServlet.java?view=markup&quot;&gt;the servlet code&lt;/a&gt; and putting it inside your project but, you know, this is not my way. I am going to try the following two ideas:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;In order to not change any reference to the servlets, all of them need to be mapped following the exact way Invoker does (Invoker uses the path &lt;em&gt;/servlet/servlet.class.fully.qualified.name&lt;/em&gt;). Obviously keeping the class name in the request is not recommended in terms of security but, at least, no dynamic re-thrown and common servlet mapping is used.&lt;/li&gt;

&lt;li&gt;The other snag is that the application can potentially have hundreds of servlets (I know, this is crazy but I am also sure that many of you have seen an application like this at least once in your life). Besides my mate is a bit lazy, &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/tongue.png&quot; alt=&quot;:-P&quot; class=&quot;emoticon&quot; /&gt; so I am sure he is not going to check all the links to find which are the servlets to map in the configuration file. This way my idea is using &lt;a href=&quot;http://www.softwareengineeringsolutions.com/blogs/2010/08/01/programmatic-definition-of-components-in-servlet-specification-3-0/&quot;&gt;new Servlet 3.0 programmatic registration&lt;/a&gt; to search, create and map them. Only servlets under some specified packages will be checked.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;It is important to understand that this is not a good solution (it is still evil although a bit less). Defining and mapping all your servlets in the &lt;em&gt;web.xml&lt;/em&gt; is the best solution and never use the qualified class name as the map name. This workaround needs to be understand as a temporary step that let you use last versions of tomcat with Invoker Servlet applications (huge ones, in little ones just map your servlets).&lt;/p&gt;

&lt;h3&gt;TOMCAT6&lt;/h3&gt;

&lt;p&gt;Once everything is explained I am going to deploy an Invoker Servlet application inside tomcat 6 and then move it to tomcat 7. In order to setup the Invoker inside version 6 you need to uncomment invoker definition and mapping in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/web.xml&quot;&gt;${TOMCAT6_DIR}/conf/web.xml&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;servlet&gt;
        &amp;lt;servlet-name&amp;gt;invoker&amp;lt;/servlet-name&amp;gt;
        &amp;lt;servlet-class&amp;gt;
          org.apache.catalina.servlets.InvokerServlet
        &amp;lt;/servlet-class&amp;gt;
        &amp;lt;init-param&amp;gt;
            &amp;lt;param-name&amp;gt;debug&amp;lt;/param-name&amp;gt;
            &amp;lt;param-value&amp;gt;0&amp;lt;/param-value&amp;gt;
        &amp;lt;/init-param&amp;gt;
        &amp;lt;load-on-startup&amp;gt;2&amp;lt;/load-on-startup&amp;gt;
    &amp;lt;/servlet&amp;gt;

    &amp;lt;servlet-mapping&amp;gt;
        &amp;lt;servlet-name&amp;gt;invoker&amp;lt;/servlet-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/servlet/*&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/servlet-mapping&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The context needs to be defined as privileged (I think tomcat guys do that in order to make clear that this is evil) inside the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/context.xml&quot;&gt;${TOMCAT6_DIR}/conf/context.xml&lt;/a&gt;. You just need to add &lt;em&gt;privileged=&quot;true&quot;&lt;/em&gt; to the context tag:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;Context privileged=&quot;true&quot;&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Finally a simple application was deployed (here it is the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/InvokerSample6.zip&quot;&gt;netbeans project for version 6&lt;/a&gt;). This application has two servlets: &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/InfoServlet.java&quot;&gt;InfoServlet.java&lt;/a&gt; (typical servlet that shows some request variables like url, path, cookies, headers, parameters and so on) and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/HelloServlet.java&quot;&gt;HelloServlet.java&lt;/a&gt; (a servlet that forwards to a JSP and just says hello). Besides I copied both classes in three different packages (&lt;em&gt;sample.invoker.servlet&lt;/em&gt;, &lt;em&gt;sample.invoker.other&lt;/em&gt; and &lt;em&gt;sample.invoker.another&lt;/em&gt;), I like to test Invoker against several packages and servlet classes.&lt;/p&gt;

&lt;h3&gt;TOMCAT7&lt;/h3&gt;

&lt;p&gt;Tomcat 7 supports new Servlet standard version 3.0 and the main idea is to programmatically register the servlets found inside some pre-defined packages. All this code has been placed in a context listener (see the servlet 3.0 link I presented before). The listener needs to be added in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/web-v7.xml&quot;&gt;web.xml&lt;/a&gt; configuration file:&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;listener&amp;gt;
        &amp;lt;listener-class&amp;gt;
            sample.invoker.ctxlistener.InvokerLoadListener
        &amp;lt;/listener-class&amp;gt;
    &amp;lt;/listener&amp;gt;
&lt;/pre&gt;

&lt;p&gt;In order to search for classes that extends &lt;em&gt;HttpServlet&lt;/em&gt; (and implements &lt;em&gt;ContainerServlet&lt;/em&gt;, an interface which is needed by the Invoker Servlet, I try to be as restrictive as possible) I followed &lt;a href=&quot;http://snippets.dzone.com/posts/show/4831&quot;&gt;the idea presented by vtatai in this post&lt;/a&gt;. But I extended it to search through files and jars. Basically the code gets the resources with the specified package using the ClassLoader and then only those which are &lt;em&gt;file:&lt;/em&gt; or &lt;em&gt;jar:&lt;/em&gt; are inspected, reflection is used to check if the class is a servlet. Using an init parameter in the &lt;em&gt;web.xml&lt;/em&gt; you can specify one or more package names to take into account (only servlets under these packages will be registered). 

&lt;pre&gt;
    &amp;lt;context-param&amp;gt;
        &amp;lt;param-name&amp;gt;invoker.packages&amp;lt;/param-name&amp;gt;
        &amp;lt;param-value&amp;gt;
            sample.invoker.servlet,
            sample.invoker.other,
            sample.invoker.another
        &amp;lt;/param-value&gt;
        &amp;lt;description&gt;List of packages to check for servlets (comma separated)&amp;lt;/description&amp;gt;
    &amp;lt;/context-param&amp;gt;
&lt;/pre&gt;

The final part performs the dynamic registration. The complete &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/InvokerLoadListener.java&quot;&gt;InvokerLoadListener.java&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/InvokerSample7.zip&quot;&gt;netbeans project for tomcat 7&lt;/a&gt; can be downloaded.&lt;/p&gt;

&lt;p&gt;Here you see my video. I start tomcat 6 and execute &lt;em&gt;InfoServlet&lt;/em&gt; and &lt;em&gt;HelloServlet&lt;/em&gt; (different packages). Then I stop version 6 and start the version 7 (I did not change ports to have both tomcats running). Executing the same servlets you can check that both results are exactly the same.&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Tomcat7andtheInvokerServlet/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;Today entry tries to explain how to workaround the Tomcat Invoker Servlet in new version 7 (this last version has removed the servlet because of its evilness). The solution uses Servlet 3.0 API, class loaders and reflection to dynamically register all the servlets in the application. It is a bit less insecure (there is no redirection, standard mapping and only servlets under specified packages are included) and, more important, it works inside Tomcat 7. Of course the context listener that searches for servlets can take some time to find all of them, but if your servlets are located in a few packages it is not so much, besides think this code is only executed once at startup.&lt;/p&gt;

&lt;p&gt;David, you owe me another beer!&lt;/p&gt;</description>
	<pubDate>dom, 25 sep 2011 14:24:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Adding Sharing Buttons to the Entries</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/43-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/43-Adding-Sharing-Buttons-to-the-Entries.html</link>
	<description>&lt;p&gt;The other day I read some recommendations about how you can improve your blog impact (I am sorry but I cannot find the link again and besides I think it was in Spanish). One of the main advice was adding the typical sharing buttons to your blog entries (you know, the buttons to share via digg, reddit, &lt;a href=&quot;http://developers.facebook.com/docs/reference/plugins/like/&quot;&gt;facebook like&lt;/a&gt; or &lt;a href=&quot;http://twitter.com/about/resources/tweetbutton&quot;&gt;tweet this&lt;/a&gt;, I am sure you have seen these buttons dozens of times). I am not a fun of social networks (no twitter, my facebook account was requested to be closed,...), I usually read some bookmark pages (&lt;a href=&quot;http://digg.com/&quot;&gt;digg&lt;/a&gt;, &lt;a href=&quot;http://slashdot.org/&quot;&gt;slashdot&lt;/a&gt; or &lt;a href=&quot;http://www.meneame.net/&quot;&gt;Spanish men&amp;eacute;ame&lt;/a&gt;) but always anonymously, and the number of visits to the blog is merely a matter of pride. So, although it really does not matter very much, I am completely agree with that advice, anything that let you spread your entries it is clearly a good idea.&lt;/p&gt;

&lt;p&gt;So from now on when you enter to see a &lt;strong&gt;single&lt;/strong&gt; entry some links to share it will appear just after the post information and before trackbacks and comments. I have just added an &lt;a href=&quot;http://www.addthis.com&quot;&gt;AddThis toolbar&lt;/a&gt; after reading &lt;a href=&quot;http://www.go-beyond-mls.com/social-bookmarking-widgets-addthis-vs-sharethis/&quot;&gt;this blog entry&lt;/a&gt;. I tested nothing, as I said I have no account in any of these sites, so if you detect any problem sharing or bookmarking an entry please comment below.&lt;/p&gt;

&lt;p&gt;Thank you all!&lt;/p&gt;</description>
	<pubDate>mar, 13 sep 2011 15:53:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Testing WebGL</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/42-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/42-Testing-WebGL.html</link>
	<description>&lt;p&gt;One of the common topics  of this blog is the &lt;a href=&quot;http://en.wikipedia.org/wiki/HTML_5&quot;&gt;HTML5&lt;/a&gt; standard and its multiple new features. Today I am going to test &lt;a href=&quot;http://en.wikipedia.org/wiki/WebGL&quot;&gt;WebGL&lt;/a&gt;, which is a standard specification to add 3D graphics in a browser canvas element without using any plug-in or external component (so it is not part of HTML5 itself but depends on it). Obviously this feature is deeply connected to graphic hardware acceleration because any WebGL application needs to be &lt;a href=&quot;http://en.wikipedia.org/wiki/Graphics_processing_unit&quot;&gt;GPU&lt;/a&gt; accelerated in order to run smoothly. WebGL is a breaking new feature in the web world and another element of great controversy among browsers. If you remember, the canvas element was already commented in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html&quot;&gt;a previous series of this blog&lt;/a&gt;, but there only 2D graphics were shown.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.khronos.org/webgl/&quot;&gt;WebGL standard&lt;/a&gt; is being driven by &lt;a href=&quot;http://www.khronos.org&quot;&gt;the Khronos Group&lt;/a&gt; and all players in the web are involved (Apple, Google, Mozilla and Opera) except Microsoft. The corporation headquartered in Redmond rejects this standard and has declared several times that IE will not support it, &lt;a href=&quot;http://blogs.technet.com/b/srd/archive/2011/06/16/webgl-considered-harmful.aspx&quot;&gt;they consider WebGL harmful in terms of security&lt;/a&gt; and they are not totally wrong.&lt;/p&gt;

&lt;p&gt;The summary of the current situation is more or less the following. Chrome (&lt;a href=&quot;http://googlesystem.blogspot.com/2010/12/chrome-9-sandboxes-flash-and-adds-webgl.html&quot;&gt;initial webGL support in version 9&lt;/a&gt;) and firefox (&lt;a href=&quot;http://blog.vlad1.com/2010/12/21/webgl-in-firefox-4-beta-8/&quot;&gt;version 4 also added  WebGL&lt;/a&gt;) support WebGL in Windows (and I think Mac OS) and it is enabled by default. Opera does not support it although there is a &lt;a href=&quot;http://my.opera.com/core/blog/2011/02/28/webgl-and-hardware-acceleration-2&quot;&gt;WebGL preview version&lt;/a&gt; for its version 11.50 only for windows. On Mac OS Safari was adding the support in their WebKit nightly builds but &lt;a href=&quot;http://fairerplatform.com/2011/05/new-in-os-x-lion-safari-5-1-brings-webgl-do-not-track-and-more/&quot;&gt;maybe in Lion WebGL is already supported&lt;/a&gt; (sorry but I am not a Mac OS user). There are some summaries of the supportability matrix, for example &lt;a href=&quot;http://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation&quot;&gt;in the Khronos page&lt;/a&gt; or &lt;a href=&quot;http://learningwebgl.com/blog/?p=11&quot;&gt;in the first chapter of  this tutorial&lt;/a&gt;, but this is a constantly changing subject so please always re-check. Nevertheless the main problem comes in the Linux world. Here there are a lot of problems related to the implementation of many graphic drivers, &lt;a href=&quot;http://www.phoronix.com/scan.php?page=news_item&amp;amp;px=OTAxMw&quot;&gt;firefox reported issues with Linux GPU drivers &lt;/a&gt; and both chrome and &lt;a href=&quot;https://wiki.mozilla.org/Blocklisting/Blocked_Graphics_Drivers&quot;&gt;firefox added a gpu blacklist&lt;/a&gt; to disable some features (WebGL mainly) depending the driver and the OS involved. &lt;a href=&quot;http://www.phoronix.com/scan.php?page=news_item&amp;amp;px=OTc4Nw&quot;&gt;Firefox 6 and 7 are supposed to remove more and more drivers from the blacklist&lt;/a&gt;, same behavior is expected in the next versions of chrome, as soon as linux driver implementations became more reliable. In summary current browsers in Linux hardly support the nvidia binary blob as the only out of the box WebGL driver (at least in my case my two boxes are blacklisted, my desktop uses gallium R300 driver and my laptop classic intel stack).&lt;/p&gt;

&lt;p&gt;After this little introduction I am going to present a quick demo of WebGL. I am very, very interested in porting &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/22-PFC.html&quot;&gt;my PFC project&lt;/a&gt; to a web version. It is incredible to me how a 12 years old project (which had to be run inside a SGI server) can now be run inside a browser. If you remember what I told in that entry, I lost my code and all the data (mesh and textures) because of a broken CD, so this implementation is only a simple demo with new and fixed data (there is a lot of room for improvement). The demo has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fixed height mesh is retrieved using a static json file. This file contains the starting latitude and longitude of the mesh, the number of points (rows and columns), the length or step of each side, the matrix data and a lot of configuration parameters. This mesh is not drawn completely. In OpenGL and WebGL (they are very similar) the idea is simple, all the figures are sent to be drawn and depending the perspective, camera and other elements the engine draws what is needed. But in my PFC the mesh was so big that only a part of it was sent to be drawn. I have followed the same idea in this demo.&lt;/li&gt;

&lt;li&gt;Basic camera management. The camera is implemented using its own axis, this way the camera can turn and move following natural keystrokes and mouse movements.&lt;/li&gt;

&lt;li&gt;Tile representation and painting. In the real application every satellite image was the texture for a tile mesh (50x50 points). This way the part of the mesh that corresponded to an image was painted independently (the application drew each square of mesh with the associated texture). I have implemented the same here but, in the demo, there is only one tile (a 8x8 tile) which is repeated all the time horizontally and vertically (11 times in each direction).&lt;/li&gt;

&lt;li&gt;Easy texture loading. A simple FIFO queue has been implemented to load and unload images. Actually this is not used in the demo cos only one image is used (there is only one tile which is repeated, so only one texture is needed and the queue is never filled).&lt;/li&gt;

&lt;li&gt;Basic ambient and directional light for emulating the sun (in my PFC there were more environmental effects like sky, fog,...).&lt;/li&gt;

&lt;li&gt;Management of the configuration parameters. I have used &lt;a href=&quot;http://www.w3schools.com/html5/html5_form_input_types.asp&quot;&gt;the new input type number which is only supported in some browsers&lt;/a&gt;. HTML5 is everywhere. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole demo is below, integrated in the entry using an iframe. It is a pity that I cannot have at my disposal the real data from my PFC (damn CD). As I said a simple pattern (only 8x8 points) is repeated all the time (11x11 tiles). This way I do not upload a lot of images to the server. How to navigate using keyboard or mouse is explained in the right part of the page.&lt;/p&gt;

&lt;p&gt;Remember what I have said before, in order to test this example you need a modern browser if you use Windows (firefox, chrome or the Opera 11 preview but not IE9). In Linux you need firefox or chromium but usually you need to disable the black list. Debian testing packages have just been upgraded to Chromium 13 and iceweasel 5 respectively and both support WebGL. In chromium the blacklist has to be ignored starting the browser with the following option:&lt;/p&gt;

&lt;pre&gt;
$ chromium --ignore-gpu-blacklist
&lt;/pre&gt;

&lt;p&gt;In Firefox I have changed some webgl settings (in the &lt;em&gt;about:config&lt;/em&gt; page):&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.disabled&lt;/td&gt;
  &lt;td&gt;false (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.force-enabled&lt;/td&gt;
  &lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.force_osmesa&lt;/td&gt;
  &lt;td&gt;false (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.osmesalib&lt;/td&gt;
  &lt;td&gt;/usr/lib/x86_64-linux-gnu/libOSMesa.so.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.prefer-native-gl&lt;/td&gt;
  &lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.shader_validator&lt;/td&gt;
  &lt;td&gt;true (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;webgl.verbose&lt;/td&gt;
  &lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;And the browser has to be executed with the following environment variable:&lt;/p&gt;

&lt;pre&gt;
$ MOZ_GLX_IGNORE_BLACKLIST=1 iceweasel
&lt;/pre&gt;

&lt;p&gt;This entry is doubtless the one that I have spent more time working on it. I was developing the JavaScript code long hours and I have to admit that I started it some time ago (last months I have been quite busy and I was never in the mood to finish it). Documentation about WebGL is very poor and thanks to &lt;a href=&quot;http://learningwebgl.com/blog/?page_id=1217&quot;&gt;this good tutorial&lt;/a&gt; I could start the development, but when you need something special, custom or a mix of things you usually wasted much time just trying to identify how to do it. In summary current WebGL support is quite a mess (much more in the Linux world) but it is an essential feature to move gaming to the web. When I saw that &lt;a href=&quot;http://media.tojicode.com/q3bsp/&quot;&gt;quake was available inside a browser&lt;/a&gt; I was totally shocked. I personally think this technology is unstoppable, no matter how buggy or insecure it was. Needless to say, flash is the current option for all of this, so WebGL should be very buggy and very insecure to be unworthy.&lt;/p&gt;

&lt;p&gt;Long life to the web wars!&lt;/p&gt;</description>
	<pubDate>jue, 08 sep 2011 09:14:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Pon un sol en tu vida: How Intel/AMD (inadvertently) fixed GNU Hurd</title>
	<guid>http://blogs.nologin.es/slopez/archives/29-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/29-How-IntelAMD-inadvertently-fixed-GNU-Hurd.html</link>
	<description>Last Friday, on Hurd's IRC channel at freenode, we've accidentally noticed some machines were able to run certain operations on Hurd as KVM guest up to 10x faster than others. As antrik correctly guessed, this is the effect of Intel's &lt;a href=&quot;http://en.wikipedia.org/wiki/Extended_Page_Table&quot; title=&quot;Extended Pages Tables&quot;&gt;Extended Page Tables&lt;/a&gt;, which allow the guest operating system to deal with it's own page faults. I suppose AMD's &lt;a href=&quot;http://en.wikipedia.org/wiki/Rapid_Virtualization_Indexing&quot; title=&quot;Rapid Virtualization Indexing&quot;&gt;Rapid Virtualization Indexing&lt;/a&gt; could have a similar effect, but I don't have the hardware to be able to test it (please write to the mailing lists if you've been able to check it).&lt;br /&gt;
&lt;br /&gt;
Since most people (including myself) are running Hurd in a virtualized environment, having the ability of taking advantage of this circumstance by moving to hardware with this technology supposes a great improvement, heavily reducing compilation times and increasing the interactivity of the entire system.&lt;br /&gt;
&lt;br /&gt;
Let's see an small example of the difference between running with and without EPT.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Running without EPT (modprove kvm-intel ept=0):&lt;/b&gt;&lt;br /&gt;
&lt;code&gt;root@debian:~# dd if=/dev/zero of=/dev/null bs=256k count=1000&lt;br /&gt;
1000+0 records in&lt;br /&gt;
1000+0 records out&lt;br /&gt;
262144000 bytes (262 MB) copied, 2.08 s, 126 MB/s&lt;/code&gt;&lt;br /&gt;
&lt;b&gt;And with EPT:&lt;/b&gt;&lt;br /&gt;
&lt;code&gt;root@debian:~# dd if=/dev/zero of=/dev/null bs=256k count=1000&lt;br /&gt;
1000+0 records in&lt;br /&gt;
1000+0 records out&lt;br /&gt;
262144000 bytes (262 MB) copied, 0.23 s, 1.1 GB/s&lt;/code&gt;&lt;br /&gt;
I think there will be interesting times for GNU Hurd.&lt;br /&gt;
&lt;br /&gt;</description>
	<pubDate>dom, 04 sep 2011 08:29:00 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Videos Are About to Change (Second Time Lucky)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html</link>
	<description>&lt;p&gt;Long time ago &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/10-Videos-were-About-to-Change.html&quot;&gt;the way videos are presented in this blog were about to change&lt;/a&gt;. I was going to replace my useful flash &lt;a href=&quot;http://flowplayer.org/&quot;&gt;flowplayer&lt;/a&gt; with the new &lt;a href=&quot;http://en.wikipedia.org/wiki/HTML5_video&quot;&gt;HTML5 video tag&lt;/a&gt;. I changed my mind because video were not supported in any stable IE and there was some warfare about the supported codecs in the rest of the browsers.&lt;/p&gt;

&lt;p&gt;At the same time I published that entry google made public the &lt;a href=&quot;http://en.wikipedia.org/wiki/WebM&quot;&gt;WEBM video+audio format&lt;/a&gt;, they created a &lt;a href=&quot;http://www.webmproject.org/&quot;&gt;webm project&lt;/a&gt; and since then the new codec has been quickly adopted by browsers. Only IE and Safari do not support WEBM by default, but this time google solved the issue &lt;a href=&quot;http://blog.chromium.org/2011/01/more-about-chrome-html-video-codec.html&quot;&gt;announcing plugins&lt;/a&gt; for both OS integrated browsers (they are in a very early stage). Microsoft IE9 was released to the public in march of this year, with a lot of the new HTML5 features (included video and audio support). Iceweasel testing package was upgraded to 5.0 last week in Debian (the browser was still at 3.5 version before). Therefore all my requisites to trigger HTML5 solutions are accomplished and there is no reason to not change my videos.&lt;/p&gt;

&lt;p&gt;From now on the videos are going to be presented using the &lt;b&gt;video&lt;/b&gt; tag and only in &lt;b&gt;WEBM&lt;/b&gt; format. Just like this:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;video src=&quot;out.webm&quot; autobuffer controls&amp;gt;
  &amp;lt;img src=&quot;error.png&quot; alt=&quot;Error!&quot; /&amp;gt;
  Your browser does not support the video tag. See this 
  &amp;lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-...&quot;&amp;gt;entry&amp;lt;/a&amp;gt; 
  for more information about how to see the videos in this blog. 
  You can &amp;lt;a href=&quot;out.webm&quot;&amp;gt;download the file&amp;lt;/a&amp;gt; instead.
&amp;lt;/video&amp;gt;
&lt;/pre&gt;

&lt;p&gt;And this is my last video in the new format just as an example (video used in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/40-Backing-Up-Data-Into-an-Encrypted-External-Disk.html&quot;&gt;Backing Up Data Into an Encrypted External Disk&lt;/a&gt; entry):&lt;/p&gt;


&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/categories/error.png&quot; alt=&quot;Error!&quot; /&gt;
Your browser doesn't support the video tag. See this &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html&quot;&gt;entry&lt;/a&gt; for more information about how to see the videos in this blog. You can &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/VideosAreAbouttoChangeSecondTimelucky/out.webm&quot;&gt;download the file&lt;/a&gt; instead.


&lt;p&gt;So maybe you have reached this post because you cannot see my videos. At this moment browser status about video and WEBM is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://www.mozilla.com/&quot;&gt;Firefox&lt;/a&gt;&lt;/b&gt;: Firefox supports both video and WEBM since 4.0 version.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://www.google.com/chrome&quot;&gt;Chrome&lt;/a&gt;&lt;/b&gt;: Both are supported since 6.0.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://www.opera.com/&quot;&gt;Opera&lt;/a&gt;&lt;/b&gt;: Video supported since 10.50, WEBM since 10.60.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://windows.microsoft.com/en-US/internet-explorer/products/ie/home&quot;&gt;IE&lt;/a&gt;&lt;/b&gt;: IE9 supports video tag but WEBM is not a valid format out of the box. You need to install &lt;a href=&quot;https://tools.google.com/dlpage/webmmf&quot;&gt;a plugin offered by the webm project&lt;/a&gt;. Remember that IE9 cannot be installed in Windows XP.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;http://www.apple.com/safari/&quot;&gt;Safari&lt;/a&gt;&lt;/b&gt;: Video is supported since 3.1 but again WEBM needs an external codec. Here there are two options, the &lt;a href=&quot;https://code.google.com/p/webm/downloads/detail?name=WebM%20Component%20Installer.pkg&quot;&gt;plugin from google&lt;/a&gt; and &lt;a href=&quot;http://perian.org&quot;&gt;perian&lt;/a&gt;, an open source &lt;a href=&quot;http://en.wikipedia.org/wiki/QuickTime&quot;&gt;QuickTime&lt;/a&gt; component that adds native support for many popular video formats (it supports webm since 1.2.3). Some friends who have tested both solutions recommend the perian option (it seems perian is very common in the Mac world and google plugin gives some problems right now, sorry but I am not a mac guy).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Others&lt;/b&gt;: If you are using any other browser you are a geek, so I hope that you know what you are doing and how to see an HTML5 video with WEBM format. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a summary, in most cases if you cannot see the videos you only need to upgrade your browser to the last version. Besides if you are using Windows integrated IE9 or Mac OS integrated Safari you need to manually install a WEBM codec plugin (see previous links). Finally if you are using IE8 (or previous) in a Windows XP box I strongly advise you to change your browser for another one (please do not get stuck).&lt;/p&gt;

&lt;p&gt;HTML5 is here! At least for my videos. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/tongue.png&quot; alt=&quot;:-P&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;b&gt;PS&lt;/b&gt;: Thanks to Luis who made some changes in the blog system installation to make this work (adding webm mimetype and IE9 &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/cc288325%28v=vs.85%29.aspx&quot;&gt;compatibility meta tag&lt;/a&gt;). Thanks also to Jaime, Mariano, Nacho, RamĂłn and Victor (both) who tested the options in Mac OS / Safari.&lt;/span&gt;&lt;/p&gt;</description>
	<pubDate>mar, 23 ago 2011 15:41:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Backing Up Data Into an Encrypted External Disk</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/40-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/40-Backing-Up-Data-Into-an-Encrypted-External-Disk.html</link>
	<description>&lt;p&gt;Today entry deals with a common and usually annoying task, backing up your laptop, so this time the post is going to be more useful for me than for anybody else. Last week my company gave me a 2TB &lt;a href=&quot;http://en.wikipedia.org/wiki/USB_3.0&quot;&gt;USB 3.0&lt;/a&gt; disk to make backups of my laptop data. But there is a requirement, the backup File System should be encrypted. As always there is an absolutely clear procedure to make all the task in Windows but not in Linux or Mac. Besides the procedure involves a closed source program (a McAfee application) to encrypt the external disk. In my opinion the requirements have never to mention particular applications and only guarantee the final goal. I can understand that a lot of custom solutions would be a mess for the company (to recover data when a employee leaves the company or whatever) but, please, at least think about all the OSes and provide a step by step procedure for all of them (Windows, Mac and Linux).&lt;/p&gt;

&lt;p&gt;The mate that gave me the disk finally told me that, as I use Linux, I did not have to encrypt the disk. But searching for information over the Internet (I knew nothing about disk encryption before) I realized that this task would not be very difficult. I found two good pages: &lt;a href=&quot;http://ubuntu-tutorials.com/2007/08/17/7-steps-to-an-encrypted-partition-local-or-removable-disk/&quot;&gt;7 Steps To An Encrypted Partition (local or removable disk)&lt;/a&gt; and &lt;a href=&quot;http://www.danieleocchipinti.com/blog-linux-php-lamp-web/linux/redhat-centos/setting-up-an-encrypted-volume-on-an-external-hard-drive-on-centos&quot;&gt;Setting up an encrypted volume on an external hard drive on CentOS&lt;/a&gt;. I also found a video of &lt;a href=&quot;http://www.youtube.com/watch?v=Z9pn2PYbDdA&quot;&gt;how to install Debian on a encrypted root file system&lt;/a&gt; (this task has nothing to do with the backup but I think it will be the next requirement for my laptop). So I finally decided to encrypt the disk anyways. This entry summarizes the setup for the two tasks using Debian, encrypting the disk and performing the backup.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;Step 1.&lt;/span&gt; The first step is configuring the partitions inside the disk. I will use two partitions, one encrypted (for the backup and confidential or customer data) and other not (for general use). The first time I plugged the disk my Debian box recognized it as &lt;em&gt;/dev/sdb&lt;/em&gt;, so from here the &lt;em&gt;/dev/sdb1&lt;/em&gt; will be the encrypted and &lt;em&gt;/dev/sdb2&lt;/em&gt; the normal partition.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;pre&gt;
# fdisk /dev/sdb
&lt;/pre&gt;

&lt;p&gt;I deleted the FAT32 partition the disk came with and created two new ones. First partition (&lt;em&gt;/dev/sdb1&lt;/em&gt;) of 1TB:&lt;/p&gt;

&lt;pre&gt;
Partition number (1-4, default 1): 
Using default value 1
First sector (2048-3907029167, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-3907029167, default 3907029167): +1024G
&lt;/pre&gt;

&lt;p&gt;And the second one (&lt;em&gt;/dev/sdb2&lt;/em&gt;) with the rest of the disk:&lt;/p&gt;

&lt;pre&gt;
Partition number (1-4, default 2): 
Using default value 2
First sector (2147485696-3907029167, default 2147485696): 
Using default value 2147485696
Last sector, +sectors or +size{K,M,G} (2147485696-3907029167, default 3907029167): 
Using default value 3907029167
&lt;/pre&gt;

&lt;p&gt;After saving the changes the disk presents the following two partitions:&lt;/p&gt;

&lt;pre&gt;
# fdisk -l /dev/sdb

Disk /dev/sdb: 2000.4 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders, total 3907029168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xee7a7a06

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048  2147485695  1073741824   83  Linux
/dev/sdb2      2147485696  3907029167   879771736   83  Linux
&lt;/pre&gt;


&lt;li&gt;
&lt;p&gt;&lt;span&gt;Step 2.&lt;/span&gt; It seems that for encrypted devices it is compulsory to write some random data in the partition (it is easier to decrypt a blank initialized disk). For this step there are various options (see the links I presented before) but I finally executed the &lt;em&gt;badblocks&lt;/em&gt; command:&lt;/p&gt;

&lt;pre&gt;
# badblocks -c 10240 -s -t random -v -w /dev/sdb1
&lt;/pre&gt;

&lt;p&gt;Take care, in my 1TB partition this step took hours (my disk is giving around 26MB/s write rate).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Step 3.&lt;/span&gt; Now it is time to create the encrypted file system in the &lt;em&gt;/dev/sdb1&lt;/em&gt; disk partition. The method used in Linux to encrypt File Systems uses the &lt;em&gt;dm-crypt&lt;/em&gt; kernel module and creates a virtual device below &lt;em&gt;/dev/mapper&lt;/em&gt; (it is a kind of wrapper over the real &lt;em&gt;/dev/sdb1&lt;/em&gt; but encrypting the data before writing on disk).&lt;/p&gt;

&lt;p&gt;First of all the package for the management command needs to be installed, the module has to be loaded in the kernel and added to the &lt;em&gt;/etc/modules&lt;/em&gt; file (modules in this file are loaded at boot time).&lt;/p&gt;

&lt;pre&gt;
# apt-get install cryptsetup
# modprobe dm-crypt
# echo &quot;dm-crypt&quot; &gt;&gt; /etc/modules
&lt;/pre&gt;

&lt;p&gt;Once the module is in place the new encrypted mapper is created above &lt;em&gt;/dev/sdb1&lt;/em&gt;. I have used default values and normal password setup (it is also possible to use a key file instead of a password, see this &lt;a href=&quot;https://wiki.archlinux.org/index.php/System_Encryption_with_LUKS#Using_LUKS_to_Format_Partitions_with_a_Keyfile&quot;&gt;archlinux page for more information about this&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;
# cryptsetup luksFormat -v -y /dev/sdb1 

WARNING!
========
This will overwrite data on /dev/sdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: 
Verify passphrase: 
Command successful.
&lt;/pre&gt;

&lt;p&gt;The default cypher is &lt;em&gt;aes-cbc-essiv:sha256&lt;/em&gt;, &lt;em&gt;sha1&lt;/em&gt; for password hashing and &lt;em&gt;256&lt;/em&gt; for key size (all this values can be changed using &lt;em&gt;-c&lt;/em&gt;, &lt;em&gt;-h&lt;/em&gt; and &lt;em&gt;-s&lt;/em&gt; options of the command respectively). This is the summary for my device.&lt;/p&gt;

&lt;pre&gt;
# cryptsetup luksDump /dev/sdb1 
LUKS header information for /dev/sdb1

Version:       	1
Cipher name:   	aes
Cipher mode:   	cbc-essiv:sha256
Hash spec:     	sha1
Payload offset:	4096
MK bits:       	256
UUID:          	ff088328-138a-4ca7-aa0a-5cbdd2064ce8

Key Slot 0: ENABLED
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
&lt;/pre&gt;

&lt;p&gt;Finally the new encrypted device is opened with &lt;em&gt;backup&lt;/em&gt; name (the password is requested at this point).&lt;/p&gt;

&lt;pre&gt;
# cryptsetup luksOpen /dev/sdb1 backup
Enter passphrase for /dev/sdb1: 
&lt;/pre&gt;

&lt;p&gt;After the luksOpen a &lt;em&gt;/dev/mapper/backup&lt;/em&gt; device is ready to be initialized and used.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Step 4.&lt;/span&gt; I have decided to use the new &lt;a href=&quot;https://btrfs.wiki.kernel.org/index.php/Main_Page&quot;&gt;btrfs&lt;/a&gt; file system. The reason is that this next generation file system manages some nice features like on the fly compression and &lt;a href=&quot;http://en.wikipedia.org/wiki/Snapshot_(computer_storage)&quot;&gt;snapshots&lt;/a&gt;, encryption and some synchronization integration are also planned (see &lt;a href=&quot;https://btrfs.wiki.kernel.org/index.php/Project_ideas&quot;&gt;the project ideas&lt;/a&gt;). Obviously compression will save some space in the disk and snapshots let us create some backup copies with a minimal cost in terms of time and space (my idea is backing up data and maintaining some snapshots of the backups).&lt;/p&gt;

&lt;p&gt;The btrfs module is currently marked as experimental in my 3.0.0 Debian kernel but its web page claims that since 2.6.31 only forward compatible disk format changes are planned. In order to create the FS the tools package has to be installed before.&lt;/p&gt;

&lt;pre&gt;
# apt-get install btrfs-tools
&lt;/pre&gt;

&lt;p&gt;Now the FS is made with BACKUP name.&lt;/p&gt;

&lt;pre&gt;
# mkfs.btrfs -L BACKUP /dev/mapper/backup

WARNING! - Btrfs Btrfs v0.19 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using

fs created label BACKUP on /dev/mapper/backup
	nodesize 4096 leafsize 4096 sectorsize 4096 size 1024.00GB
Btrfs Btrfs v0.19
&lt;/pre&gt;

&lt;p&gt;The new FS is mounted for testing and its owner changed to my common user.&lt;/p&gt;

&lt;pre&gt;
# mount /dev/mapper/backup /mnt
# df -h /mnt
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/backup   1008G  200M  957G   1% /mnt
# chown ricky:ricky /mnt
&lt;/pre&gt;

&lt;p&gt;At this point the FS can be unmounted and closed. I will never mount the partition again manually, the idea is that gnome mounts it automatically (password is requested as soon as LUKS FS is detected).&lt;/p&gt;

&lt;pre&gt;
# umount /mnt
# cryptsetup luksClose /dev/mapper/backup
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;span&gt;Step 5.&lt;/span&gt; Now it is time to think about the backup. The easiest way to backup some directories in Linux is using the &lt;a href=&quot;http://rsync.samba.org/&quot;&gt;rsync&lt;/a&gt; utility. This application is a powerful, fast and versatile file copying tool which supports local and remote (ssh for example) copies. The idea for the backup is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the external USB disk is plugged gnome mounts them (both partitions) automatically. For the encrypted file system the password is requested. Inside the root mount point a backup script is located, just clicking on it and running it the backup is started. Gnome automounter mounts the FS with default options. That is the reason I finally decided not to use the compression option of btrfs (&lt;a href=&quot;https://wiki.archlinux.org/index.php/Udev&quot;&gt;UDEV&lt;/a&gt; is used for the automatic mount, and perhaps a new UDEV rule can be used to change the default behavior but I preferred not to complicate the solution).&lt;/li&gt;
&lt;li&gt;This script called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/BackingUpDataIntoaEncryptedExternalDisk/backup-system-gksudo.sh&quot;&gt;backup-system-gksudo.sh&lt;/a&gt; is a simple script that just opens a new gnome-terminal executing &lt;a href=&quot;http://live.gnome.org/gksu&quot;&gt;gksudo&lt;/a&gt; (gnome graphical sudo) over the real backup script &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/BackingUpDataIntoaEncryptedExternalDisk/backup-system.sh&quot;&gt;backup-system.sh&lt;/a&gt; (btrfs command needs root access).&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;backup-system.sh &lt;/em&gt; script reads a local and hidden configuration file called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/BackingUpDataIntoaEncryptedExternalDisk/backup-config.conf&quot;&gt;.backup-config&lt;/a&gt;. This file has some general variables like the directory to maintain in sync (usually it would be / directory but, in my case, &lt;em&gt;/home&lt;/em&gt; is where all my data are placed), number of snapshots to maintain, directory for host backups, file for excluded dirs,...&lt;/li&gt;
&lt;li&gt;First the script creates a new btrfs sub-volume for the specified box (this way the same disk can hold backups for several boxes). The volume is placed in &lt;em&gt;host-backup/$(hostname)&lt;/em&gt; directory (the first directory name is customizable via the configuration file). If the volume already exists this step is just skipped.&lt;/li&gt;
&lt;li&gt;After that the script continues executing the rsync command. The command is called with the following options:

&lt;pre&gt;
rsync -a --delete -v --stats --progress \
  --exclude-from=&quot;${dirName}/${EXCLUDED_DIRS_FILE}&quot; \
  &quot;${SOURCE_BACKUP_DIR}&quot; &quot;${hostDirName}&quot;
&lt;/pre&gt;

With this execution the SOURCE_BACKUP_DIR is in sync against the external and encrypted btrfs volume. The &lt;em&gt;-a&lt;/em&gt; options is for archive mode, &lt;em&gt;--delete&lt;/em&gt; option removes files deleted in the source directory, and &lt;em&gt;-v&lt;/em&gt;, &lt;em&gt;--stats&lt;/em&gt; and &lt;em&gt;--progress&lt;/em&gt; options are for showing some information while copying. The &lt;em&gt;--exclude-from&lt;/em&gt; option let us exclude some directories from the copy, the pattern file is defined inside the configuration (in my case this var points to a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/BackingUpDataIntoaEncryptedExternalDisk/exclude-dirs.conf&quot;&gt;.exclude-dirs&lt;/a&gt; file that contains entries like videos or comics which are huge directories I do not like to backup). This step can take hours the first time but it is quite fast when only changes are sent.
&lt;li&gt;When the rsync command finishes a btrfs snapshot is taken. This snapshot is located at the same level of the host sub-volume but labeled with the current date (the snapshot name is like this &lt;em&gt;$(hostname)-YYYYMMDDHHMMSS)&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Finally old snapshots are deleted (in the configuration file there is a MAX_SNAPSHOTS variable, if the snapshots are more than this number the old ones are removed).&lt;/li&gt;
&lt;li&gt;At the end of the script a message is shown to the user. &lt;a href=&quot;http://freshmeat.net/projects/zenity&quot;&gt;Zenity&lt;/a&gt; command is used to tell the user that the backup has been successfully done or the script has terminated with errors.&lt;/li&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;

&lt;p&gt;Here a video is presented to show the backup execution. It is at accelerated speed, the real backup took around two minutes. First the disk is inserted and gnome requests the password for the encrypted partition. When the device is automatically mounted the graphical script is executed (first I show that only one snapshot is in the hosts directory). This script launches a new gnome-terminal, after the root password is also requested the backup (rsync) and snapshot are performed. Once the script finishes a successful message is shown. Finally I enter in the host directory and show the just created snapshot directory.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/BackingUpDataIntoaEncryptedExternalDisk/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;In summary this entry comments how to implement a backup utility over an encrypted external disk in Linux (Debian). I have written it just to remember what I did (I had never worked with this utilities, cryptsetup, dm-crypt, btrfs or rsync). As you have seen my idea is keeping it as simple as possible. Only the chosen File System (btrfs) is a bit strange, but thinking about current and announced features it seems to be the proper one (maybe in the near future btrfs alone can do all the stuff explained here, sync and encryption included, avoiding the use of any other program). Please reuse and adapt it if you think it is useful for you.&lt;/p&gt;

&lt;p&gt;Remember to backup your ideas too!&lt;/p&gt;</description>
	<pubDate>mar, 16 ago 2011 17:09:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Changing Again the Way I Listen to Music</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/39-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/39-Changing-Again-the-Way-I-Listen-to-Music.html</link>
	<description>&lt;p&gt;I have just requested my &lt;a href=&quot;http://www.spotify.com/&quot;&gt;Spotify&lt;/a&gt; free account to be deleted (&lt;a href=&quot;http://www.accountkiller.com/en/delete-spotify-account&quot;&gt;it is done via email&lt;/a&gt;). I had this account since nearly the beginning cos I was moved from &lt;a href=&quot;http://www.last.fm/&quot;&gt;LastFM&lt;/a&gt;. It seems the story repeats again and, much to my sorrow, it will not be my last time. I was a loyal user of LastFM for years (besides there was a plugin for &lt;a href=&quot;http://projects.gnome.org/rhythmbox/&quot;&gt;rhythmbox&lt;/a&gt; which I loved) but in 2009 &lt;a href=&quot;http://blog.last.fm/2009/03/24/lastfm-radio-announcement&quot;&gt;they decided I needed a subscription&lt;/a&gt;. I changed to Spotify which impressed me. It was not a radio, it was your personal music device but with almost all the songs of the world. Of course the snag was that there was no native Linux application, but &lt;a href=&quot;http://www.winehq.org/&quot;&gt;wine&lt;/a&gt; worked well enough for me. Sadly &lt;a href=&quot;http://www.spotify.com/blog/archives/2011/04/14/upcoming-changes-to-spotify-free-open/&quot;&gt;Spotify changed free account access some months ago&lt;/a&gt;, since then I could only listen to music ten hours per month, and they are very few! So I needed to change again. I decided to use &lt;a href=&quot;http://grooveshark.com/&quot;&gt;Grooveshark&lt;/a&gt;. It is just a web page where you can also select the songs you like to listen. When I discovered you can drag some songs, turn on the radio and it keeps playing forever choosing similar songs, I decided it would be my first choice. Here the problems are that the page uses &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/35-Sound-Issue-in-Linux-Adobe-Flash.html&quot;&gt;the annoying flash player&lt;/a&gt; and there are no songs of &lt;a href=&quot;http://www.thechemicalbrothers.com/&quot;&gt;The Chemical Brothers&lt;/a&gt; (not even &lt;a href=&quot;http://www.youtube.com/watch?v=QDe6MZQjpho&quot;&gt;The Test&lt;/a&gt;, a glaring error as my brother says &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;). But, again, it is good enough for me (dammit! I just want to listen to music!). I am going to use the &lt;a href=&quot;http://www.google.com/support/chrome/bin/answer.py?answer=95710&quot;&gt;chromium application shortcut feature&lt;/a&gt;, I prefer it in a separate and clear window.&lt;/p&gt;

&lt;p&gt;This week I found that &lt;a href=&quot;http://triggercell.posterous.com/you-know-what-really-grinds-my-gears&quot;&gt;Grooveshark sometimes stops playing and asks if you are still there&lt;/a&gt; (obviously it happens when you let it playing for a long time). It is really a pain in the ass, you have to stop what you are doing and click that yes, I am fucking here. Please take this into account. I am not sure what I hate more, this or Spotify ads (they were annoying but the music was never stopped).&lt;/p&gt;

&lt;p&gt;Well, Grooveshark is my new way to listen to music... How long will it last this time?&lt;/p&gt;</description>
	<pubDate>sáb, 16 jul 2011 21:11:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Pon un sol en tu vida: Sometimes, swap space still matters</title>
	<guid>http://blogs.nologin.es/slopez/archives/28-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/28-Sometimes,-swap-space-still-matters.html</link>
	<description>Most modern, general purpose Operating Systems (OS), come with a full-fledged Virtual Memory (VM) system that generates the illusion of having more memory than the real amount installed in the machine. Whether this &lt;i&gt;virtual&lt;/i&gt; memory is backed by real RAM, disk swap or it just isn't backed by any physical device, is something up to the OS.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://blogs.nologin.es/slopez/archives/28-Sometimes,-swap-space-still-matters.html#extended&quot;&gt;Continue reading &quot;Sometimes, swap space still matters&quot;&lt;/a&gt;</description>
	<pubDate>vie, 15 jul 2011 17:19:07 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Nolife at Nologin: Grandes frases</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/135-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/135-Grandes-frases.html</link>
	<description>&lt;p&gt;Empiezo una secciĂłn de grandes frases dichas en el trabajo, en esta nolife.&lt;/p&gt;&lt;p&gt;&amp;quot;El hombre invisible no es un voyeur&amp;quot;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;Gersius&lt;/p&gt;</description>
	<pubDate>vie, 15 jul 2011 12:40:40 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Testing the IcedTea-Web Java Plugin</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/38-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/38-Testing-the-IcedTea-Web-Java-Plugin.html</link>
	<description>&lt;p&gt;Some days ago I realized that debian packages related to java plugin in OpenJDK/IcedTea had been upgraded in testing to the new &lt;a href=&quot;http://icedtea.classpath.org/wiki/IcedTea-Web&quot;&gt;IcedTea-Web&lt;/a&gt; infrastructure. The IcedTea-Web is a redesign of the old gcjwebplugin and Netx JavaWS implementations. This entry talks a bit about the complex story of java web-plugin in OpenJDK and then a little testing of the new plugin is presented.&lt;/p&gt;

&lt;p&gt;If you have been interested in the process of open-sourcing the Sun Java Virtual Machine (called &lt;a href=&quot;http://openjdk.org&quot;&gt;OpenJDK&lt;/a&gt;) you already know that the Java web-plugin and Java Web Start (JavaWS) were never incorporated. The first component is the browser plugin that let HTML pages to integrate &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_applet&quot;&gt;Java Applets&lt;/a&gt; inside them. If you remember I have talked about applets two times in this blog, first in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/12-Signature-Applet.html&quot;&gt;signature applet series&lt;/a&gt; and second in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html&quot;&gt;scatter plot trilogy&lt;/a&gt;. &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Web_Start&quot;&gt;JavaWS&lt;/a&gt; is a similar technology to Applets but not as tightly coupled with the browser, here Java applications run outside it but interaction is also possible. JavaWS is also known as Java Network Launching Protocol (JNLP) because of the definition files and the protocol used to launch the applications.&lt;/p&gt;

&lt;p&gt;When Sun announced the possibility of open-sourcing the JDK in the JavaOne conference of 2006 there were some parts of the code which were covered by third party licenses (some GUI classes, the java audio system, some cryptography components and many more). For that reason the first versions of OpenJDK, released under GPLv2 license, were not complete and they had encumbrances. These parts had to be downloaded apart, as a binary blob, in order to get a full Java Virtual Machine. The plan was to gradually replace these proprietary components with alternative implementations. Nowadays OpenJDK has no more encumbered code or components and the sources for versions 6 and 7 can be downloaded from its web page (initially only JDK7 was to be open-sourced but finally &lt;a href=&quot;http://blogs.oracle.com/darcy/entry/openjdk_6_genealogy&quot;&gt;JDK6 was included in a complex merge process&lt;/a&gt;). Nevertheless the web plugin and the JavaWS were not included in the free code neither in the encumbered parts (both technologies, although related to J2SE, are not part of it).&lt;/p&gt;

&lt;p&gt;Update 10 of the non-free Sun JDK6 (not OpenJDK) replaced the Java plugin with a new and bright implementation. In the mids of 2009 Joe Darcy, at that moment the release manager of OpenJDK6, announced &lt;a href=&quot;http://blogs.oracle.com/darcy/entry/openjdk_and_the_new_plugin&quot;&gt;this new implementation was to be included in the OpenJDK tree&lt;/a&gt;. But some updates after and with no signs of the new plugin &lt;a href=&quot;http://mail.openjdk.java.net/pipermail/jdk6-dev/2009-June/000604.html&quot;&gt;Joe himself confirmed that circumstances had changed&lt;/a&gt;. For one reason or another both technologies (Applets and JavaWS) were never moved from non-free implementation to OpenJDK.&lt;/p&gt;

&lt;p&gt;Separately (but very close to OpenJDK) the &lt;a href=&quot;http://icedtea.classpath.org/wiki/Main_Page&quot;&gt;IcedTea project&lt;/a&gt; is the effort of RedHat of making the OpenJDK usable without any encumbered bits as soon as possible. This project quickly added to OpenJDK the &lt;a href=&quot;http://www.nongnu.org/gcjwebplugin/&quot;&gt;gcjwebplugin&lt;/a&gt;, a plugin implementation started as a &lt;a href=&quot;http://savannah.gnu.org/&quot;&gt;Savannah&lt;/a&gt; project but later moved to the &lt;a href=&quot;http://www.gnu.org/software/classpath/&quot;&gt;GNU classpath&lt;/a&gt;, and &lt;a href=&quot;http://jnlp.sourceforge.net/netx/&quot;&gt;Netx&lt;/a&gt;, an alternative implementation of the JNLP protocol. The problem with these two projects was that both were old implementations and quite buggy. If you remember one of my reasons to start the HTML5 scatter graph study was the gcjwebplugin, default plugin for all linux distros.&lt;/p&gt;

&lt;p&gt;I do not know the real reasons (maybe Sun announcement of plugin integration, maybe both technologies are not commonly used,...) but the real thing is that the plugin progress has been slow. IcedTea was born in 2007 using old implementations, in 2009 &lt;a href=&quot;https://dbhole.wordpress.com/2009/05/15/introducing-the-icedteanpplugin/&quot;&gt;Deepak Hole announced the new IcedTea plugin&lt;/a&gt; in an enormous step forward, in 2010 &lt;a href=&quot;https://dbhole.wordpress.com/2010/04/14/icedtea-1-8-released-with-new-np-plugin/&quot;&gt;it was integrated in IcedTea&lt;/a&gt; for the first time and, finally, in 2011 &lt;a href=&quot;https://dbhole.wordpress.com/2011/02/02/first-release-of-icedtea-web/&quot;&gt;IcedTea-Web was released as a separated sub-project&lt;/a&gt; of the general IcedTea project.&lt;/p&gt;

&lt;p&gt;Current version of IcedTea-Web is 1.1 and it is the version which has recently arrived to testing. Some days ago these packages were upgraded in my desktop box (I have installed OpenJDK there to see the progress of this implementation and not the non-free packages I usually use in my working laptop) and I decided to test how good the status of this new plugin is. I have to mention my previous experiences were very disappointing (when plugins were a little complex they never work). In order to do that I have checked the two most complex applets I have access to.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The scatter plot Applet &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html&quot;&gt;I commented in the canvas entries&lt;/a&gt;. This &lt;a href=&quot;http://www.puertos.es/en/oceanografia_y_meteorologia/redes_de_medida/index.html&quot;&gt;applet is used in &lt;em&gt;Puertos del Estado&lt;/em&gt; web page&lt;/a&gt; (a governmental organization that studies sea and harbor issues in Spain). This application uses &lt;a href=&quot;http://code.google.com/webtoolkit/&quot;&gt;Google Web Toolkit (GWT)&lt;/a&gt; and the applet is presented always a magnitude is plotted (several applets in the same page, lots of sample points,...). When I was working there one of my mates used an ubuntu box with OpenJDK and the applet crashes sometimes (usually when you were displaying several graphs, adding or removing them).&lt;/li&gt;

&lt;li&gt;The Signature Applet I presented in the security series. Of course I am going to test &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/21-DNIe-and-the-Signature-Applet.html&quot;&gt;the crytocard version using my Spanish eID&lt;/a&gt; (the most complex version, signed jar, JNI to the opensc-pkcs11 library and so on).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The conclusions are not very promising. It seems the new IcedTea-Web is evolving but it is not ready yet. With the scatter plot Applet I added and removed several graphs and two issues were found. When the plots are added to the page (a new div element is added) they are not properly re-painted, it is like the plot was not there (maybe this issue happens because the plots are added dynamically -javascript- to the page). Then I discovered the Sea Level plot hung the plugin. This magnitude plot (as I commented in its own entry) displays a lot of samples (more than 10,000) and it seemed IcedTea-Web could not manage this high number of samples. Using &lt;em&gt;&lt;a href=&quot;http://download.oracle.com/javase/6/docs/technotes/guides/management/jconsole.html&quot;&gt;jconsole&lt;/a&gt;&lt;/em&gt; and looking at the code I found a loop that leaves much to be desired. Keeping my habits I developed a patch and &lt;a href=&quot;http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=749&quot;&gt;reported a bug&lt;/a&gt;. I did not do anything with the first issue, it is quite related to the way applets are displayed and I do not have the source code of the applet.&lt;/p&gt;

&lt;p&gt;In the Signature application more problems came out. First the PKCS11 provider did not load the certificates from the card. The &lt;em&gt;KeyStore.getInstance(keyStoreType)&lt;/em&gt; method call does not work in OpenJDK/IcedTea-Web. I changed the call to &lt;em&gt;KeyStore.getInstance(keyStoreType, provider)&lt;/em&gt; and it magically started to work. The second problem, when the signature was computed mail/activation libraries gave the following error &lt;em&gt;javax.activation.UnsupportedDataTypeException: no object DCH for MIME type application/pkcs7-mime&lt;/em&gt;. It only worked when I copied &lt;a href=&quot;http://www.bouncycastle.org/java.html&quot;&gt;Bouncy Castle&lt;/a&gt; libraries to the &lt;em&gt;ext/lib&lt;/em&gt; OpenJDK directory. I do not really know what this issues are about but they seem related to security concerns, although this applet is self-signed (none of them happened in a simple java execution using OpenJDK -out of the applet- or in the non-free JDK plugin). Obviously the second Applet does not work (cos you cannot trust in a user copying files to &lt;em&gt;lib/etx&lt;/em&gt; directory) but, as I commented in the signature entry, this Applet is just a PoC (Proof of Concept) and it does some strange things. I consider a real signature Applet (a one that just signs and/or encrypts) maybe would work.&lt;/p&gt;

&lt;p&gt;It is important to comment that these two applets, although complex, work smoothly in the closed-source plugin. Finally I want to add that now the IcedTea-Web has a &lt;em&gt;itweb-settings&lt;/em&gt; configuration command which emulates typical &lt;em&gt;ControlPanel&lt;/em&gt; of non-free JDK (here there is also room for improvement but, you know, it is more than nothing).&lt;/p&gt;

&lt;p&gt;I present a video where, using IcedTea-Web plugin inside iceweasel, I connect to the internet Plotter Applet and add three different graphs. As you see, applets are not re-painted (they need a click to force the rendering). But at least with my patch Sea Level plots are working. Then the Signature Applet is accessed (local application), once the libraries are in the &lt;em&gt;lib/ext&lt;/em&gt; folder the mail is signed and sent without a problem.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/TestingIcedTea-WebJavaPlugin/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;It seems the IcedTea-Web is finally improving but nowadays it is still not the Java plugin that OpenJDK deserves. I did not test any JavaWS example (I have no one and it would be great if any of you could test some custom application) but I ran two applets which I know were problematic in OpenJDK before. Now both of them work better but some issues were still discovered. I know two tests are not many but they are meaningful to me. The best point is the plugin is now an independent project in IcedTea which I think guarantees better maintenance and improvement. Despite all this I am sure that if I have to develop a new applet or JavaWS application I will take this plugin implementation into account.&lt;/p&gt;

&lt;p&gt;Keep on pushing IcedTea guys!&lt;/p&gt;</description>
	<pubDate>sáb, 09 jul 2011 17:44:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Usign OpenMQ with Tomcat</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/37-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/37-Usign-OpenMQ-with-Tomcat.html</link>
	<description>&lt;p&gt;Some weeks ago a company mate asked me some questions about a JavaEE application that needs a JMS queue for a special process. The customer wanted to install the software inside Tomcat and I warned her that Tomcat is just a Servlet container and not a fully JavaEE application server, therefore she needed another JMS server software. Although I have never worked with open source JMS servers I advised to use &lt;a href=&quot;http://activemq.apache.org/&quot;&gt;ActiveMQ&lt;/a&gt; but the problem was the customer already used OpenMQ. I tried to find some examples about this configuration but it was impossible, so I finally could not help very much. But yesterday I had some free time and I tried it by myself.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mq.java.net/&quot;&gt;OpenMQ&lt;/a&gt; is the Oracle (formerly Sun) open source &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Message_Service&quot;&gt;JMS&lt;/a&gt; server used in &lt;a href=&quot;http://glassfish.java.net/&quot;&gt;Glassfish&lt;/a&gt;. It used to be tightly coupled with the application server but the last versions are trying to split the two platforms. Nevertheless I was unable to find any example of how to integrate OpenMQ inside Tomcat, so this shows the division is just underway. I decided to follow a very &lt;a href=&quot;http://javaguru.fi/blog/-/blogs/configuring-activemq-5-jms-topic-in-tomcat-6&quot;&gt;good guide for setting ActiveMQ in Tomcat&lt;/a&gt; and then perform the needed changes.&lt;/p&gt;

&lt;p&gt;OpenMQ can be downloaded from its web page and there is a simple ZIP distribution file. Just uncompressing the file a &lt;em&gt;MessageQueue4_5&lt;/em&gt; directory is popped out with all the necessary bits. From here this directory will be called &lt;em&gt;{OPENMQ_DIR}&lt;/em&gt;.&lt;/p&gt;

&lt;pre&gt;
$ unzip openmq4_5-binary-Linux_X86.zip
&lt;/pre&gt;

&lt;p&gt;After installation the broker (the JMS java daemon) can be just started.&lt;/p&gt;

&lt;pre&gt;
{OPENMQ_DIR}/mq/bin$ ./imqbrokerd &amp;amp;
[17/Jun/2011:17:14:46 CEST] 
==============================================
Open Message Queue 4.5
Oracle
Version:  4.5  (Build 29-b)
Compile:  Wed Feb  9 22:53:30 PST 2011

Copyright (c) 2010, Oracle and/or its affiliates.  All rights reserved.
===============================================
Java Runtime: 1.6.0_26 Sun Microsystems Inc. /usr/lib/jvm/java-6-sun-1.6.0.26/jre
[17/Jun/2011:17:14:46 CEST]    IMQ_HOME=/home/blog/MessageQueue4_5/mq
[17/Jun/2011:17:14:46 CEST] IMQ_VARHOME=/home/blog/MessageQueue4_5/var/mq
[17/Jun/2011:17:14:46 CEST] Linux 2.6.38-2-amd64 amd64 magneto (4 cpu) ricky
[17/Jun/2011:17:14:46 CEST] Java Heap Size: max=188416k, current=188416k
[17/Jun/2011:17:14:46 CEST] Arguments: 
[17/Jun/2011:17:14:46 CEST] [B1060]: Loading persistent data...
[17/Jun/2011:17:14:46 CEST] Using built-in file-based persistent store: 
/home/blog/MessageQueue4_5/var/mq/instances/imqbroker/
[17/Jun/2011:17:14:46 CEST] WARNING [B3168]: Invalid broker address for this broker 
to run in cluster: Loopback IP address is not allowed in broker address 
mq://127.0.1.1:7676/?instName=imqbroker&amp;amp;brokerSessionUID=6784163344567163648
for cluster
[17/Jun/2011:17:14:46 CEST] WARNING [B1137]: Cluster initialization failed. 
Disabling the cluster service.
[17/Jun/2011:17:14:46 CEST] [B1270]: Processing messages from transaction log file...
[17/Jun/2011:17:14:46 CEST] [B1039]: Broker &quot;imqbroker@magneto:7676&quot; ready.
&lt;/pre&gt;

&lt;p&gt;Of course the software can be configured in more detail (OpenMQ supports high availability, different backends to store messages and so on) but it was not the goal of this entry. With this nonexistent configuration the broker uses the directory &lt;em&gt;{OPENMQ_DIR}/instances/imqbroker&lt;/em&gt;, inside it there are several things: the configuration properties file, the directory where messages are stored by default,...&lt;/p&gt;

&lt;p&gt;Once the broker is up and ready a queue called &lt;em&gt;sampleQueue&lt;/em&gt; is created.&lt;/p&gt;

&lt;pre&gt;
{OPENMQ_DIR}/mq/bin$ ./imqcmd create dst -n sampleQueue -t q -u admin
Password: 
Creating a destination with the following attributes:

Destination Name    sampleQueue
Destination Type    Queue

On the broker specified by:

-------------------------
Host         Primary Port
-------------------------
localhost    7676

Successfully created the destination.
&lt;/pre&gt;

&lt;p&gt;OpenMQ admin user also has &lt;em&gt;admin&lt;/em&gt; as the default password (although it can be easily changed using &lt;em&gt;imqusermgr update -u admin -p newpassword&lt;/em&gt;). With an OpenMQ queue ready to be used the next step is configuring Tomcat resources. But, obviously, we need first to include client libraries in Tomcat classpath. I just copied the jars in the lib directory. At this point I am assuming a Tomcat 6 server is installed in &lt;em&gt;{TOMCAT_DIR}&lt;/em&gt; directory.&lt;/p&gt;

&lt;pre&gt;
$ cp {OPENMQ_DIR}/mq/lib/imq.jar {TOMCAT_DIR}/lib
$ cp {OPENMQ_DIR}/mq/lib/jms.jar {TOMCAT_DIR}/lib
&lt;/pre&gt;

&lt;p&gt;And now the hard part comes, cos now I need to define the resources in Tomcat to be populated in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface&quot;&gt;JNDI&lt;/a&gt; tree, and this was the part I could not find documentation anywhere. Looking OpenMQ source code (that's the way I wanna Open Source) I discover that OpenMQ has some JNDI ObjectFactory classes (an &lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/javax/naming/spi/ObjectFactory.html&quot;&gt;ObjectFactory&lt;/a&gt; is the way Tomcat creates and loads any kind of object in the JNDI tree). All of them are placed in the &lt;em&gt;com.sun.messaging.naming&lt;/em&gt; package. After some tries (I will never admit how many) I discovered the factory and the queue have to be defined in the &lt;em&gt;GlobalNamingResources&lt;/em&gt; of the &lt;em&gt;server.xml&lt;/em&gt; file this way.&lt;/p&gt;

&lt;pre&gt;
  &amp;lt;GlobalNamingResources&amp;gt;
    ...
    &amp;lt;Resource name=&quot;jms/sampleFactory&quot; 
              auth=&quot;Container&quot; 
              type=&quot;com.sun.messaging.QueueConnectionFactory&quot; 
              description=&quot;OpenMQ Queue Connection Factory&quot;
              factory=&quot;com.sun.messaging.naming.QCFObjectFactory&quot; 
              securityPort=&quot;7676&quot;
              parm=&quot;--&quot;
              subnet=&quot;0&quot;
              host=&quot;-s localhost&quot;
              ackTimeout=&quot;-t 30000&quot;
              version=&quot;1.1&quot; /&amp;gt;
    &amp;lt;Resource name=&quot;jms/sampleQueue&quot; 
              auth=&quot;Container&quot; 
              type=&quot;com.sun.messaging.Queue&quot; 
              description=&quot;OpenMQ Queue&quot;
              factory=&quot;com.sun.messaging.naming.QObjectFactory&quot; 
              destName=&quot;sampleQueue&quot;
              version=&quot;1.1&quot; /&amp;gt;
  &amp;lt;/GlobalNamingResources&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I really do not know why the references are so exotic but, as I said before, it seems the reason is the high coupling with former Sun application server (if you see some values are like arguments to start the broker daemon). With this part solved the rest of the configuration is just like ActiveMQ or any other JMS software. We need to add the references in the default context (&lt;em&gt;context.xml&lt;/em&gt; file).&lt;/p&gt;

&lt;pre&gt;
&amp;lt;Context&amp;gt;
    ...
    &amp;lt;ResourceLink global=&quot;jms/sampleFactory&quot; name=&quot;jms/sampleFactory&quot; 
        type=&quot;javax.jms.ConnectionFactory&quot;/&amp;gt;
    &amp;lt;ResourceLink global=&quot;jms/sampleQueue&quot; name=&quot;jms/sampleQueue&quot; 
        type=&quot;javax.jms.Queue&quot;/&amp;gt;
&amp;lt;/Context&amp;gt;
&lt;/pre&gt;

&lt;p&gt;And finally a little web application is necessary to test the setup. I quickly developed a servlet with a send and receive (consume) method, the complete Netbeans project can be downloaded &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsignOpenMQwithTomcat/sampleJms.zip&quot;&gt;here&lt;/a&gt;. In short the &lt;em&gt;web.xml&lt;/em&gt; file has to define again the references.&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;resource-ref&amp;gt;
        &amp;lt;res-ref-name&amp;gt;jms/sampleFactory&amp;lt;/res-ref-name&amp;gt;
        &amp;lt;res-type&amp;gt;javax.jms.ConnectionFactory&amp;lt;/res-type&amp;gt;
        &amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;
        &amp;lt;res-sharing-scope&amp;gt;Shareable&amp;lt;/res-sharing-scope&amp;gt;
    &amp;lt;/resource-ref&amp;gt;	
    &amp;lt;resource-ref&amp;gt;
        &amp;lt;res-ref-name&amp;gt;jms/sampleQueue&amp;lt;/res-ref-name&amp;gt;
        &amp;lt;res-type&amp;gt;javax.jms.Queue&amp;lt;/res-type&amp;gt;
        &amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;
        &amp;lt;res-sharing-scope&amp;gt;Shareable&amp;lt;/res-sharing-scope&amp;gt;
    &amp;lt;/resource-ref&amp;gt;
&lt;/pre&gt;

&lt;p&gt;And here it is the doSend method (nothing special was done).&lt;/p&gt;

&lt;pre&gt;
    private void doSend(String txt) throws ServletException {
        QueueConnection connection = null;
        QueueSession queueSession = null;
        try {
            System.out.println(&quot;Getting connection factory from JNDI...&quot;);
            QueueConnectionFactory connFactoryObj = (QueueConnectionFactory) 
                initialContext.lookup(&quot;java:/comp/env/jms/sampleFactory&quot;);
            System.out.println(&quot;Creating connection...&quot;);
            connection = connFactoryObj.createQueueConnection(&quot;admin&quot;, &quot;admin&quot;);
            queueSession = connection.createQueueSession(true, 
                Session.SESSION_TRANSACTED);
            System.out.println(&quot;Getting queue from JNDI...&quot;);
            Queue queue = (Queue) initialContext.lookup(&quot;java:/comp/env/jms/sampleQueue&quot;);
            System.out.println(&quot;Creating the session&quot;);
            QueueSender queueSender = queueSession.createSender(queue);
            TextMessage message = queueSession.createTextMessage();
            message.setText(txt);
            System.out.println(&quot;Sending the message: &quot; + message);
            queueSender.send(message);
            queueSession.commit();
        } catch (Exception e) {
            if (queueSession != null) {
                try {queueSession.rollback();} catch(Exception ex) {}
            }
            e.printStackTrace();
            throw new ServletException(e);
        } finally {
            if (queueSession != null) {
                try {queueSession.close();} catch(Exception e) {}
            }
            if (connection != null) {
                try {connection.close();} catch(Exception e) {}
            }
        }
    }
&lt;/pre&gt;

&lt;p&gt;Finally I decided to extend or improve this solution. In the resource configuration only host and port are specified, this means a lot of the JMS software features are wasted. OpenMQ right now does not recommend the use of &lt;em&gt;imqBrokerHostName&lt;/em&gt; or &lt;em&gt;imqBrokerHostPort&lt;/em&gt; properties, now it uses a new &lt;em&gt;imqAddressList&lt;/em&gt; which defines one or more broker instances (HA setup). So I created a new ObjectFactory called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsignOpenMQwithTomcat/CFReflectionObjectFactory.java&quot;&gt;CFReflectionObjectFactory.java&lt;/a&gt; which simply lists all the connection configuration properties of OpenMQ (using reflection over the class &lt;a href=&quot;http://mq.java.net/nonav/javadoc/4.5/javadoc/com/sun/messaging/ConnectionConfiguration.html&quot;&gt;ConnectionConfiguration&lt;/a&gt;) and set the property if it is defined in the Tomcat resource definition. This way any property can be passed to OpenMQ connection. Using this little improvement (I also copied the one class jar library inside the Tomcat lib directory) the Resource for the factory was as follows.&lt;/p&gt;

&lt;pre&gt;
    &amp;lt;Resource name=&quot;jms/sampleFactory&quot; 
              auth=&quot;Container&quot; 
              type=&quot;com.sun.messaging.QueueConnectionFactory&quot; 
              description=&quot;OpenMQ Queue Connection Factory&quot;
              factory=&quot;com.sun.messaging.naming.CFReflectionObjectFactory&quot; 
              imqAddressList=&quot;mq://localhost:7676/jms&quot;
              imqReconnectEnabled=&quot;true&quot;
              imqReconnectInterval=&quot;60000&quot;
              imqReconnectAttempts=&quot;5&quot; /&amp;gt;
&lt;/pre&gt;

&lt;p&gt;If you see I have set the host using recommended &lt;em&gt;imqAddressList&lt;/em&gt; property and some other reconnection properties just as example (because of reflection any property can be set, any property which exists in the &lt;em&gt;ConnectionConfiguration&lt;/em&gt; OpenMQ class of course). With this final setup I present a video where the demo servlet is used to send three text messages to the queue and then they are retrieved.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/UsignOpenMQwithTomcat/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;I hope that I am helping my mate and maybe someone else (possibly it is a bit late, I am sorry). It is incredible there was no information about a Tomcat/OpenMQ setup. In summary there are some ObjectFactories ready to be used in the OpenMQ distribution but I fear that they are a bit old and obsolete, and that is the reason I created a new one which can define any configuration property.&lt;/p&gt;

&lt;p&gt;Be smart!&lt;/p&gt;</description>
	<pubDate>sáb, 18 jun 2011 11:41:41 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Sound Issue in Linux Adobe Flash (Better Solution)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/36-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/36-Sound-Issue-in-Linux-Adobe-Flash-Better-Solution.html</link>
	<description>&lt;p&gt;Yesterday I spent some time reading the &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=638477&quot;&gt;fedora bug&lt;/a&gt; about the flash issue commented in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/35-Sound-Issue-in-Linux-Adobe-Flash.html&quot;&gt;the previous entry&lt;/a&gt;. There are very interesting comments in it, but more important, there are two attachments to replace by yourself the &lt;em&gt;memcpy&lt;/em&gt; calls with &lt;em&gt;memmove&lt;/em&gt; (one is a &lt;a href=&quot;https://bugzilla.redhat.com/attachment.cgi?id=460254&quot;&gt;bash script&lt;/a&gt; and the other is a &lt;a href=&quot;https://bugzilla.redhat.com/attachment.cgi?id=487982&quot;&gt;C++ program&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I tried the C++ source code program and it seems to work quite well:&lt;/p&gt;

&lt;pre&gt;
# wget -O replace.c https://bugzilla.redhat.com/attachment.cgi?id=487982
# g++ -o replace replace.c
# cd /usr/lib64/flashplugin-nonfree/
# cp libflashplayer.so libflashplayer.so.ORIG
# ~/replace libflashplayer.so
Found memmove at symbol table index 516
Found and fixed 1 reloc entries
&lt;/pre&gt;

&lt;p&gt;Of course this solution is a much better approach, because it depends directly on you, you can understand what you are doing and it will work for future plugin releases (if they are still broken). But remember I was desperate at those times. Another thing I did not comment before is that this bug only applies to amd64 linux platforms (not i386, 32 bit installations). And paying more attention to glib package upgrade (I also upgraded my desktop debian box yesterday), I realized there is a warning screen about this &lt;em&gt;memcpy&lt;/em&gt; issue you need to accept. I really do not know if I just accepted it without reading in the laptop upgrade or it is new now... I bet for the first option. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Cheerio!&lt;/p&gt;</description>
	<pubDate>vie, 03 jun 2011 06:21:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>9â‚¬Â®$!Âµ$: Por quĂ© me gusta tanto el VGA Planets</title>
	<guid>http://blogs.nologin.es/gersius/archives/56-guid.html</guid>
	<link>http://blogs.nologin.es/gersius/archives/56-Por-que-me-gusta-tanto-el-VGA-Planets.html</link>
	<description>Realmente no es tanto el juego como los jugadores. Llevo algunos aĂ±os jugando con una panda de espaĂ±oles y argentinos, y las partidas son divertidĂ­simas. Para muestra, el siguiente mensaje en la lista de correo de la partida:&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;Manga de cagones trolos chupatrozos, en el turno 10, cunpliendo la consigna, yo ataque a Peron, de acuerdo a lo que todos decian. Le tome la unica puta nave que vi en el horizonte 2D de nuestro universo... y el resto? nada... manga de travestidos disfrazados de moyano... ya no les creo nada... ahora en el turno 20, Peron puede transitar libremente entre mis planetas (no en ellos) y fuera de mis campos minados, joder!&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
Y las hostilidades aĂşn no han comenzado... pronto empezarĂˇn las explosiones &lt;img src=&quot;http://blogs.nologin.es/gersius/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; class=&quot;emoticon&quot; /&gt;</description>
	<pubDate>jue, 26 may 2011 13:45:23 +0000</pubDate>
	<author>nospam@example.com (gersius)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Sound Issue in Linux Adobe Flash</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/35-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/35-Sound-Issue-in-Linux-Adobe-Flash.html</link>
	<description>&lt;p&gt;Another quick entry this time. Some months ago I started to watch &lt;a href=&quot;http://en.wikipedia.org/wiki/Dexter_%28TV_series%29&quot;&gt;dexter&lt;/a&gt; via streaming, but the past week I noticed the sound was very garbled and strange. My streaming site uses (in my linux user opinion) the annoying &lt;a href=&quot;http://www.adobe.com/products/flashplayer/&quot;&gt;adobe flash plugin&lt;/a&gt;. Being very busy these days I just found the &lt;a href=&quot;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=620901&quot;&gt;debian associated bug&lt;/a&gt; but, at that moment, it solved nothing. Today I have rechecked it and a user comment links to &lt;a href=&quot;https://bugs.adobe.com/jira/browse/FP-5739&quot;&gt;another adobe bug&lt;/a&gt;. It explains that the plugin is using &lt;em&gt;memcpy&lt;/em&gt; instead of &lt;em&gt;memmove&lt;/em&gt;. And if man pages are consulted it is clear what is going on:&lt;/p&gt;

&lt;blockquote&gt;
The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas should not overlap. Use memmove(3) if the memory areas do overlap.
&lt;/blockquote&gt;

&lt;p&gt;Last glibc upgrade has got this sound issue out (you know I have a thing about upgrading my debian box). If you follow the previous adobe link there is a solution from a &lt;a href=&quot;http://www.linux.org.ru/forum/talks/5663681&quot;&gt;Russian page&lt;/a&gt;. It seems the &lt;em&gt;memcpy&lt;/em&gt; function has been binary replaced by &lt;em&gt;memmove&lt;/em&gt; (I did not know it was even possible). In my debian box the solution is very similar to the explained by the Russian mate. Please be aware of the fact that you are trusting in a binary change done by this guy (you know, desperate times call for desperate measures).&lt;/p&gt;

&lt;pre&gt;
# wget http://catap.ru/patches/flash64/memcpy-10.3.162.29.bsdiff
# cp /usr/lib64/flashplugin-nonfree/libflashplayer.so \
  /usr/lib64/flashplugin-nonfree/libflashplayer.so.old
# bspatch /usr/lib64/flashplugin-nonfree/libflashplayer.so.old \
  /usr/lib64/flashplugin-nonfree/libflashplayer.so \
  memcpy-10.3.162.29.bsdiff
&lt;/pre&gt;
 
&lt;p&gt;Adobe flash plugin is a pain in the ass of any linux user. So please I encourage everybody to change to new &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/categories/16-HTML5&quot;&gt;HTML5 features&lt;/a&gt;, especially pages like grooveshark, megavideo or youtube (google is already doing that) which are part of my life.&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;</description>
	<pubDate>mar, 24 may 2011 20:31:45 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: JAX-WS and Multiple Endpoints</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/30-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/30-JAX-WS-and-Multiple-Endpoints.html</link>
	<description>&lt;p&gt;These last weeks I have been working in an identity project that deals with Web Services. The customer wants the Identity Solution to integrate several applications via Web Services. Therefore the agreement of a WSDL between all parts was the first issue to work with. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Services_Description_Language&quot;&gt;WSDL (Web Services Description Language)&lt;/a&gt; is an XML language to describe and model Web Services, using simpler words, it is a way to define what methods to implement and what the data model exchanged is (without any doubt). Finishing the introduction &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_API_for_XML_Web_Services&quot;&gt;JAX-WS (Java Api for XML Web Services)&lt;/a&gt; is the API  that deals with Web Services as part of the &lt;a href=&quot;http://www.oracle.com/technetwork/java/javaee/overview/index.html&quot;&gt;Java EE&lt;/a&gt; platform specification (it gives annotations, WSDL parsing and many other features to simplify the development of Web Services in the Java platform).&lt;/p&gt;

&lt;p&gt;It is important to explain that in this case my part (the identity side) would be the client whilst the different applications would be the Web Services server side. This way the Identity Software would invoke the methods of the agreement in order to provision a new account, to change some attributes or to delete a user in the integrated application. If a WSDL is defined previously no compatibility problems are expected, no matter the server software or the implementation language. Besides, as all methods and exchange objects had been deliberately defined generic, only one client would have been needed in the identity side for all applications. In fact the agreement document version 1.0 (with the first version of the WSDL inside too) was sent to customer and to the different application teams some months ago.&lt;/p&gt;

&lt;p&gt;But people sometimes do not understand what a WSDL is and, even worse, developers think some methods with similar functionality are more than sufficient (which is basically true but it converts all the previous work in a waste of time and the scheduled timetable in a real bullshit). Of course these &lt;em&gt;little modifications&lt;/em&gt; are considered not important enough to even advise the other parts involved. To sum the first application to integrate had developed their way Web Services. Besides the application team used a custom and abominable Web Services framework which did not generate the artifacts, so the XML data had to be manually parsed (oh my gosh!). Another of its features was every operation was bound to a different endpoint (a different URL). Needless to say the WSDL was not automatically generated and it had also to be written manually. So you can image the situation. After some crisis times I decided to tune their WSDL and implement the same file in a modern application server, mainly my idea was testing with a confident implementation and reporting errors to them as fast as I can.&lt;/p&gt;

&lt;p&gt;But developing a multi-endpoint web service with JAX-WS was not as easy as I expected and this is the reason for this entry. I decided to use &lt;a href=&quot;http://jax-ws.java.net/&quot;&gt;Metro implementation&lt;/a&gt; which is the JAX-WS reference and open-source implementation done by Oracle (formerly Sun). Actually metro is the complete Web Services stack for glassfish (and other application servers) and covers many other components like &lt;a href=&quot;http://en.wikipedia.org/wiki/JAX-RS&quot;&gt;JAX-RS&lt;/a&gt; (see my &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/27-Improving-RGraph-Plot-with-Real-Data-via-Web-Services.html&quot;&gt;ScatterPlot entry for more information for RESTful Web Services&lt;/a&gt;), &lt;a href=&quot;http://en.wikipedia.org/wiki/JAXB&quot;&gt;JAXB&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/WSIT&quot;&gt;WSIT&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/SAAJ&quot;&gt;SAAJ&lt;/a&gt; inside the Java EE. There are more implementations like &lt;a href=&quot;http://axis.apache.org/axis2/java/core/&quot;&gt;Apache Axis 2&lt;/a&gt;, &lt;a href=&quot;http://cxf.apache.org/&quot;&gt;Apache CXF&lt;/a&gt; or &lt;a href=&quot;http://xfire.codehaus.org/&quot;&gt;Codehouse XFire&lt;/a&gt; but I have more experience with this one and I suppose basics are the same for all of them. I spent some time to create the Web Service and I want to save this information here.&lt;/p&gt;

&lt;p&gt;For obvious reasons I cannot present the real WSDL file so I created a very simple user &lt;a href=&quot;http://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt; service for a supposed application, here it is the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/basic-crud.wsdl&quot;&gt;basic-crud.wsdl&lt;/a&gt; file. This WSDL is not generic but it is easier and better for learning purposes. The definition has four endpoints with one operation inside each (Create, Read, Update and Delete). If you download the JAX-WS Metro bundle there are some sample applications inside, and one of them explicitly shows how to create a jax-ws service from a given WSDL file (&lt;em&gt;fromwsdl&lt;/em&gt; inside &lt;em&gt;samples&lt;/em&gt; directory). Following the instructions the wsdl must be imported in order to create the interfaces and exchange objects:&lt;/p&gt;

&lt;pre&gt;
$ wsimport -keep -Xnocompile -verbose -d ../../../src/java/ basic-crud.wsdl 
parsing WSDL...

generating code...

sample/user/crud/basic/CreatePort.java
sample/user/crud/basic/CreateRequest.java
sample/user/crud/basic/CreateResponse.java
sample/user/crud/basic/DeletePort.java
sample/user/crud/basic/DeleteRequest.java
sample/user/crud/basic/DeleteResponse.java
sample/user/crud/basic/ObjectFactory.java
sample/user/crud/basic/ReadPort.java
sample/user/crud/basic/ReadRequest.java
sample/user/crud/basic/ReadResponse.java
sample/user/crud/basic/SampleUser.java
sample/user/crud/basic/Status.java
sample/user/crud/basic/StatusCode.java
sample/user/crud/basic/UpdatePort.java
sample/user/crud/basic/UpdateRequest.java
sample/user/crud/basic/UpdateResponse.java
sample/user/crud/basic/WsCRUDUserService.java
sample/user/crud/basic/package-info.java
&lt;/pre&gt;

&lt;p&gt;The wsimport command parses the WSDL file and generates the Java portable artifacts (keep option does not delete the Java files and they are saved inside src directory). With this command all Java classes and the Web Service Interfaces are generated for all the ports. After that the different ports need to be coded and, following the &lt;em&gt;fromwsdl&lt;/em&gt; example, the &lt;em&gt;@WebService&lt;/em&gt; annotation must only have the &lt;em&gt;endpointInterface&lt;/em&gt; property set in each. In my example all the ports just manage the users into memory (a memory example repository). The code for read operation is presented below.&lt;/p&gt;

&lt;pre&gt;
package sample.user.crud.basic.implementation;

import javax.jws.WebService;
import sample.user.crud.basic.ReadRequest;
import sample.user.crud.basic.ReadResponse;
import sample.user.crud.basic.SampleUser;
import sample.user.crud.basic.Status;
import sample.user.crud.basic.StatusCode;

@WebService(endpointInterface = &quot;sample.user.crud.basic.ReadPort&quot;)
public class ReadPort {

    private UserMapSingleton map = UserMapSingleton.getSingleton();

    public ReadResponse read(ReadRequest request) {
        ReadResponse response = new ReadResponse();
        Status status = new Status();
        response.setStatus(status);
        try {
            if (request.getId() == null) {
                status.setStatus(StatusCode.ERROR);
                status.setMessage(&quot;No ID passed!&quot;);
            } else {
                SampleUser user = map.getMap().get(request.getId());
                response.setUser(user);
                status.setStatus(StatusCode.OK);
                if (user == null) {
                    status.setMessage(&quot;User '&quot; + request.getId() + &quot;' not found!&quot;);
                }
            }
            return response;
        } catch (Throwable t) {
            status.setStatus(StatusCode.ERROR);
            status.setMessage(t.getMessage());
            return response;
        }
    }
}
&lt;/pre&gt;

&lt;p&gt;When the Web Services are created from a defined WSDL all the ports have to be added to the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/sun-jaxws.xml&quot;&gt;sun-jaxws.xml&lt;/a&gt; file manually (as I said previously only the &lt;em&gt;endpointInterface&lt;/em&gt; attribute annotation is present in the Java class and all the configuration is defined via the &lt;em&gt;sun-jaxws&lt;/em&gt; file). This file contains all the endpoints with the implementation and interface part. You have to think this is exactly the opposite of what is done when the WSDL is not previously defined (everything is annotated and nothing is set in the &lt;em&gt;sun-jaxws.xml&lt;/em&gt;). Here it is the file for the four CRUD endpoints.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;endpoints 
    xmlns=&quot;http://java.sun.com/xml/ns/jax-ws/ri/runtime&quot;
    version=&quot;2.0&quot;&amp;gt;

    &amp;lt;endpoint
        name=&quot;wsCRUDUserServicePortTypeBindingCreate&quot;
        implementation=&quot;sample.user.crud.basic.implementation.CreatePort&quot;
        interface=&quot;sample.user.crud.basic.CreatePort&quot;
        wsdl=&quot;WEB-INF/wsdl/basic-crud.wsdl&quot;
        service=&quot;{http://basic.crud.user.sample}wsCRUDUserService&quot;
        port=&quot;{http://basic.crud.user.sample}wsCRUDUserServicePortTypeBindingCreate&quot;
        url-pattern=&quot;/wsCRUDUserServicePortTypeBindingCreate&quot; /&amp;gt;

    &amp;lt;endpoint
        name=&quot;wsCRUDUserServicePortTypeBindingRead&quot;
        implementation=&quot;sample.user.crud.basic.implementation.ReadPort&quot;
        interface=&quot;sample.user.crud.basic.ReadPort&quot;
        wsdl=&quot;WEB-INF/wsdl/basic-crud.wsdl&quot;
        service=&quot;{http://basic.crud.user.sample}wsCRUDUserService&quot;
        port=&quot;{http://basic.crud.user.sample}wsCRUDUserServicePortTypeBindingRead&quot;
        url-pattern=&quot;/wsCRUDUserServicePortTypeBindingRead&quot; /&amp;gt;

    &amp;lt;endpoint 
        name=&quot;wsCRUDUserServicePortTypeBindingUpdate&quot;
        implementation=&quot;sample.user.crud.basic.implementation.UpdatePort&quot;
        interface=&quot;sample.user.crud.basic.UpdatePort&quot;
        wsdl=&quot;WEB-INF/wsdl/basic-crud.wsdl&quot;
        service=&quot;{http://basic.crud.user.sample}wsCRUDUserService&quot;
        port=&quot;{http://basic.crud.user.sample}wsCRUDUserServicePortTypeBindingUpdate&quot;
        url-pattern=&quot;/wsCRUDUserServicePortTypeBindingUpdate&quot; /&amp;gt;

    &amp;lt;endpoint 
        name=&quot;wsCRUDUserServicePortTypeBindingDelete&quot;
        implementation=&quot;sample.user.crud.basic.implementation.DeletePort&quot;
        interface=&quot;sample.user.crud.basic.DeletePort&quot;
        wsdl=&quot;WEB-INF/wsdl/basic-crud.wsdl&quot;
        service=&quot;{http://basic.crud.user.sample}wsCRUDUserService&quot;
        port=&quot;{http://basic.crud.user.sample}wsCRUDUserServicePortTypeBindingDelete&quot;
        url-pattern=&quot;/wsCRUDUserServicePortTypeBindingDelete&quot; /&amp;gt;

&amp;lt;/endpoints&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Finally the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/web.xml&quot;&gt;web.xml&lt;/a&gt; is modified to add JAX-WS listener and servlet and the servlet is mapped against all the URLs specified in the previous file.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;web-app version=&quot;2.5&quot; xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; 
  xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; 
  xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;&amp;gt;
    &amp;lt;listener&amp;gt;
        &amp;lt;listener-class&amp;gt;
            com.sun.xml.ws.transport.http.servlet.WSServletContextListener
        &amp;lt;/listener-class&amp;gt;
    &amp;lt;/listener&amp;gt;
    &amp;lt;servlet&amp;gt;
        &amp;lt;display-name&amp;gt;wsCRUDUserService&amp;lt;/display-name&amp;gt;
        &amp;lt;servlet-name&amp;gt;wsCRUDUserService&amp;lt;/servlet-name&amp;gt;
        &amp;lt;servlet-class&amp;gt;com.sun.xml.ws.transport.http.servlet.WSServlet&amp;lt;/servlet-class&amp;gt;
        &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
    &amp;lt;/servlet&amp;gt;
    &amp;lt;servlet-mapping&amp;gt;
        &amp;lt;servlet-name&amp;gt;wsCRUDUserService&amp;lt;/servlet-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/wsCRUDUserServicePortTypeBindingCreate&amp;lt;/url-pattern&amp;gt;
        &amp;lt;url-pattern&amp;gt;/wsCRUDUserServicePortTypeBindingRead&amp;lt;/url-pattern&amp;gt;
        &amp;lt;url-pattern&amp;gt;/wsCRUDUserServicePortTypeBindingUpdate&amp;lt;/url-pattern&amp;gt;
        &amp;lt;url-pattern&amp;gt;/wsCRUDUserServicePortTypeBindingDelete&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/servlet-mapping&amp;gt;
    &amp;lt;session-config&amp;gt;
        &amp;lt;session-timeout&amp;gt;30&amp;lt;/session-timeoutv
    &amp;lt;/session-config&amp;gt;
    &amp;lt;welcome-file-list&amp;gt;
        &amp;lt;welcome-file&amp;gt;index.jsp&amp;lt;/welcome-file&amp;gt;
    &amp;lt;/welcome-file-list&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;

&lt;p&gt;In theory at this point everything is set and the project is ready to be used. I deployed the war file inside a standard glassfish 2.1.1 application server. If you access to any of the four mapped endpoints Metro lists all the endpoints defined in the application (see screenshot below). If the WSDL is requested to any of the four endpoints the same XML file is returned (cos four endpoints are coded from the same WSDL file).&lt;/p&gt;

&lt;div&gt;
  &lt;img class=&quot;serendipity_image_center&quot; src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/webservice-endpoints.png&quot; alt=&quot;webservice endpoints&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Finally I implemented a quick &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/WsCRUDUserServiceTest.java&quot;&gt;JUnit test case class&lt;/a&gt; which checks the four endpoints work as expected (it creates, updates and deletes a user doing some reads between modify operations to test the functionality).&lt;/p&gt;

&lt;p&gt;Today's entry explains how to create a JAX-WS Web Service with several endpoints from a pre-defined WSDL definition file using reference Metro implementation. As you have stated it is not very difficult and you can directly follow fromwsdl sample instructions. But I wanted to summarize the process here to have a quick guide for the next time (I do not usually work with Web Services this way and I spent some time to achieve it). In my defense, it seems incredibly simpler once you have written the full instructions, these things always make me think I am really stupid &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;. The complete NetBeans project can be download from &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/JAX-WSandMultipleEndpoints/WsCRUDUserService.zip&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;God is in the detail. Cheerio!&lt;/p&gt;</description>
	<pubDate>sáb, 30 abr 2011 10:49:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Glassfish Enterprise Profile on Linux amd64</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/34-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/34-Glassfish-Enterprise-Profile-on-Linux-amd64.html</link>
	<description>&lt;p&gt;The previous week an ex co-worker, and a good friend, asked me if I had tested &lt;a href=&quot;http://glassfish.java.net/&quot;&gt;Glassfish&lt;/a&gt; 2.1.1 on a x64 linux box. The question surprised me cos my new laptop is an amd64 Linux installation, all my glassfish tests are done in it and I had not noticed any problem. He clarified me that he could not setup an enterprise profile. I remember that Glassfish 2.1.1 has no difference between open source and supported edition (it was based on the same source code), so this entry is about how to setup a Glassfish enterprise profile in Linux x64 using its community version.&lt;/p&gt;

&lt;p&gt;Glassfish v2 can be installed using &lt;a href=&quot;http://download.oracle.com/docs/cd/E19879-01/821-0185/gelvk/index.html&quot;&gt;three different profiles&lt;/a&gt;: developer, cluster or enterprise. Developer profile is a single application server instance. Cluster is a multi-instance setup with central management for all servers and cluster/Load Balancing features enabled. Enterprise profile is exactly like cluster but using &lt;a href=&quot;http://www.mozilla.org/projects/security/pki/nss/&quot;&gt;NSS (Netscape Security Services)&lt;/a&gt; instead of JKS (Java KeyStore) for the certificate store and the possibility of using HADB for session management (a kind of multinode database that Sun used to integrate with Glassfish to get the third type of session-aware cluster I talked about in a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/32-High-Availability-in-Application-Servers.html&quot;&gt;previous post&lt;/a&gt;). My friend explained to me that the problem was with NSS libraries (supported Glassfish edition includes them), the libraries provided by the Linux distribution were ELF 32-bit and, obviously, they do not work with a 64 bit JVM and system.&lt;/p&gt;

&lt;p&gt;I am going to explain the steps I followed testing this issue. This is usually how I like to show my entries, because I think this way is more useful and it is also better for me to remember.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;As the Glassfish documentation comments, in open source edition NSS and NSPR libraries have to be installed independently from glassfish. In my debian box this step was easily done.&lt;/p&gt;

&lt;pre&gt;
$ apt-get install libnss3-1d libnss3-tools libnspr4-0d libnspr4-dev libnss3-dev
&lt;/pre&gt;

&lt;p&gt;Developer packages were not needed at this time but following points are going to use them.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Glassfish installer for open source edition was downloaded from glassfish site. For linux only one package is available. Cluster setup was installed using &lt;a href=&quot;http://glassfish.java.net/downloads/v2.1.1-final.html&quot;&gt;glassfish instructions&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
$ java -Xmx256m -jar glassfish-installer-v2.1.1-b31g-linux.jar
$ cd glassfish
$ lib/ant/bin/ant -f setup-cluster.xml
&lt;/pre&gt;

&lt;p&gt;Glassfish community edition is installed in the directory where the installer is launched, inside a new &lt;em&gt;glassfish&lt;/em&gt; folder (this installation directory will be denoted ${GLASSFISH_DIR} since now). By default the previous process creates a domain (domain1) using cluster profile (not enterprise). So this domain was deleted.&lt;/p&gt;

&lt;pre&gt;
$ cd ${GLASSFISH_DIR}/bin
$ ./asadmin delete-domain domain1
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The configuration file &lt;em&gt;${GLASSFISH_DIR}/config/asenv.conf&lt;/em&gt; was modified to include where NSS are installed (debian installs main NSS and NSPR libs in &lt;em&gt;/usr/lib&lt;/em&gt;). So the following properties were modified:&lt;/p&gt;

&lt;pre&gt;
AS_NSS=&quot;/usr/lib&quot;
AS_NSS_BIN=&quot;/usr/bin&quot;
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;If you try to create an enterprise profile domain just like this the issue explained by my colleague happens. It seems a internal &lt;em&gt;libasnss.so&lt;/em&gt; is also used and glassfish only provides it in 32 bit mode (as you see in the download page there is no Linux x64 installer). But this is open source so, not wasting any time, I took a look to &lt;a href=&quot;http://java.net/projects/glassfish/sources/v2/show&quot;&gt;glassfish 2.1.1 subversion&lt;/a&gt; and I found a &lt;a href=&quot;http://java.net/projects/glassfish/sources/v2/content/trunk/appserv-native-ee/src/cpp/nssutil/nssstore.c&quot;&gt;nssstore.c&lt;/a&gt; file. This is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Native_Interface&quot;&gt;Java Native Interface (JNI)&lt;/a&gt; wrapper above NSS library (Java can call native libraries using JNI and this file is a wrapper to make the interaction easier). Although there are some links for completely building glassfish (&lt;a href=&quot;http://wikis.sun.com/display/GlassFish/V3FullBuildInstructions&quot;&gt;one for glassfish v3&lt;/a&gt; and &lt;a href=&quot;http://glassfish.java.net/public/BuildGlassFish.html&quot;&gt;another outdated one for v2&lt;/a&gt;), I quickly gave up because the process seems to be huge. So I decided to only compile the problematic file.&lt;/p&gt;

&lt;p&gt;First the directory that contains this file was checked out:&lt;/p&gt;

&lt;pre&gt;
$ cd /tmp
$ svn checkout https://svn.java.net/svn/glassfish~v2/trunk/appserv-native-ee
$ cd appserv-native-ee/src/cpp/nssutil/
&lt;/pre&gt;

&lt;p&gt;After that the header file has to be made. In JNI this is done reading the class and executing &lt;em&gt;javah&lt;/em&gt; command on it (the problematic class, source of the exception, was &lt;em&gt;com.sun.enterprise.ee.security.NssStore&lt;/em&gt;).&lt;/p&gt;

&lt;pre&gt;
$ javah -classpath ${GLASSFISH_DIR}/lib/appserv-se.jar \
  -o com_sun_enterprise_ee_security_NssStore.h com.sun.enterprise.ee.security.NssStore
&lt;/pre&gt;

&lt;p&gt;With this header the C file can be compiled against NSS/NSPR debian 64 bits libraries:&lt;/p&gt;

&lt;pre&gt;
$ gcc -fpic -I/usr/lib/jvm/java-6-sun-1.6.0.24/include/ \
  -I/usr/lib/jvm/java-6-sun-1.6.0.24/include/linux/ \
  -I/usr/include/nss/ -I/usr/include/nspr/ nssstore.c -c
$ gcc -shared -Wl,-rpath,${GLASSFISH_DIR}/lib -o libasnss.so nssstore.o -lc \
  -L/usr/lib -lnss3 -lnspr4 -lnssutil3 -lsmime3
&lt;/pre&gt;

&lt;p&gt;The new &lt;em&gt;libasnss.so&lt;/em&gt; library is copied to glassfish lib directory (a backup is previously done).&lt;/p&gt;

&lt;pre&gt;
$ cp ${GLASSFISH_DIR}/lib/libasnss.so ${GLASSFISH_DIR}/lib/libasnss.so.ORIG
$ cp libasnss.so ${GLASSFISH_DIR}/lib/libasnss.so
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;After the previous step the domain is successfully created but it fails to start. It complains about library &lt;em&gt;/usr/lib/amd64/libsoftokn3.so&lt;/em&gt; does not exist. Looking again the code of the class &lt;a href=&quot;http://java.net/projects/glassfish/sources/v2/content/trunk/appserv-core-ee/appserv-core/src/java/com/sun/enterprise/ee/security/EESecuritySupportImpl.java&quot;&gt;EESecuritySupportImpl.java&lt;/a&gt; (thrower of the new exception) it tries to initialize the PKCS11 provider (method initNSS) with the &lt;em&gt;libsoftokn3&lt;/em&gt; NSS library compounding its path as follows: the &lt;em&gt;AS_NSS&lt;/em&gt; path from &lt;em&gt;asenv.conf&lt;/em&gt; (in our case &lt;em&gt;/usr/lib&lt;/em&gt;), the architecture if system is 64 bits (&lt;em&gt;amd64&lt;/em&gt; in our case) and finally &lt;em&gt;libsoftokn3.so&lt;/em&gt; if system is not windows. So the result is &lt;em&gt;/usr/lib/amd64/libsoftokn3.so&lt;/em&gt; but, in case of debian, this library is located in &lt;em&gt;/usr/lib/nss&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I did not think too much and, after becoming root, I created a link.&lt;/p&gt;

&lt;pre&gt;
# cd /usr/lib
# ln -s nss amd64
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Finally the enterprise domain was created and started successfully. &lt;/p&gt;

&lt;pre&gt;
$ cd ${GLASSFISH_DIR}/bin
$ ./asadmin create-domain --profile enterprise --user admin --adminport 9898 \
  --savelogin=true --savemasterpassword=true domain1
$ ./asadmin start-domain
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here it is a video where the new domain is created and started (as you see my architecture is amd64, the certificate store is NSS and glassfish works perfect).&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/GlassfishEnterpriseProfileonLinuxamd64/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;As a conclusion the glassfish installer for Linux is only provided in 32 bits. It works in x64 Linux system using developer and cluster profile cos a complete Java stack is used (no JNI library is needed) but it fails in enterprise. The enterprise profile uses NSS as the certificate store and a little &lt;em&gt;libasnss.so&lt;/em&gt; (JNI library) is provided for easier integration, but it is only in 32 bit. In this entry the library was re-compiled in my amd64 box. Of course another problems could come out cos I did not test all the features and maybe more libraries are used (there are more native libraries in the &lt;em&gt;lib&lt;/em&gt; glassfish directory and all of them are 32 bit).&lt;/p&gt;

&lt;p&gt;That's the Way I Wanna Rock 'n' Roll!&lt;/p&gt;</description>
	<pubDate>dom, 10 abr 2011 14:01:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: High Availability in Application Servers (sequel)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/33-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/33-High-Availability-in-Application-Servers-sequel.html</link>
	<description>&lt;p&gt;In the previous entry a study about &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/32-High-Availability-in-Application-Servers.html&quot;&gt;High Availability (HA) in Application Server&lt;/a&gt; was done. The main reason for this study was checking how proper an in-memory repository (like &lt;a href=&quot;http://www.membase.org/&quot;&gt;membase&lt;/a&gt;) is for session management. I found &lt;a href=&quot;http://code.google.com/p/memcached-session-manager/&quot;&gt;memcached-session-manager (MSM)&lt;/a&gt;, a session manager for tomcat and memcached, and, for that, I performed a benchmark of the three typical HA solutions using tomcat. In the comments section Martin Grotzke (the main developer of MSM) pointed out that, if mod_jk had been configured sticky, the proper behavior of MSM was also to be sticky. I want to explain that my understanding of the third scenario (a external repository is used to save sessions) consists in that the new backend (JDBC, in-memory or whatever) has to be a complete replacement for session management. This way it should be accesseded twice in every request (first to get the session and then, if session is modified, to save changes). This is the reason I configured MSM non-sticky, but obviously this is the most demanding configuration and quite weird (sticky mod_jk but non-sticky MSM is something clearly useless in a real deployment). Finally I have included the complete sticky benchmark to compare all results fairly.&lt;/p&gt;

&lt;p&gt;The MSM project page explains the differences between sticky and non-sticky configuration. When tomcat servers are accessed in a sticky way MSM can assume that, if it has an active session, the session is up to date (cos no other server can modify it). Therefore sticky MSM configuration saves all gets (except in the first request, when there is no active session it has to check if it was previously created in a failed server). Besides MSM seems to use only one object in sticky configuration and two in non-sticky (session itself is obviously always managed but a kind of validity object is also managed in non-sticky implementation), so this fact saves some gets and sets too. In summary, there is a lot less work to do in sticky than in non-sticky configuration. Do not forget a get/set also represents a serialization/de-serialization process.&lt;/p&gt;

&lt;p&gt;The MSM/membase sticky solution presents &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/Statistics-MEM-STICKY.csv&quot;&gt;the following numbers&lt;/a&gt;. I also show the same charts and graphs of the previous entry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average and 90% Line time (four configurations).&lt;/li&gt;
&lt;li&gt;New graphic results from JMeter for sticky scenario.&lt;/li&gt;
&lt;li&gt;Membase statistics page for this new benchmark.&lt;/li&gt;
&lt;li&gt;CPU utilization in both virtual boxes (all scenarios).&lt;/li&gt;
&lt;/ul&gt;

 
 

 
&lt;div class=&quot;highslide-gallery&quot;&gt; 

&lt;a id=&quot;pfc_thumb1&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/times-new.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/times-new-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Average response time and 90% Line time
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb2&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/graph-mem-sticky.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/graph-mem-sticky-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        JMeter graph results for sticky membase scenario
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb5&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/membase-statistics-new.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/membase-statistics-new-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Membase statistics for default bucket
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb6&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/cpu-debian1-new.jpg&quot; class=&quot;highslide&quot;&gt;
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/cpu-debian1-new-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt;
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        CPU used in debian box 1
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb7&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/cpu-debian2-new.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServerssequel/cpu-debian2-new-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt;
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        CPU used in debian box 2
&lt;/div&gt;

&lt;/div&gt;

&lt;p&gt;If you see the numbers of sticky configuration (8ms average request time and 14ms for 90% line time) are very similar to the replication cluster, and half a way between simple load balancing and SMS non-sticky. It is quite logical, more or less, half of the work is not necessary. Looking at CPU percentage the new sticky architecture is around 16% (tomcat process consumes a bit less than in replication scenario but membase adds another 4%). So, again, everything is as expected and it is clear that when this solution was mature enough it would be very very competitive with replication cluster but more scalable. All the options have been benchmarcked and studied, as I said before, now it is fairer.&lt;/p&gt;

&lt;p&gt;Cheerio!&lt;/p&gt;</description>
	<pubDate>mar, 05 abr 2011 06:40:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: High Availability in Application Servers</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/32-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/32-High-Availability-in-Application-Servers.html</link>
	<description>&lt;p&gt;Today entry, despite it is not a typical topic for me, is about an architectural decision: &lt;strong&gt;High Availability (HA) in Application Servers&lt;/strong&gt;. Actually this entry comes out because I have been seeing these days several solutions which involve a in-memory repository in order to get a clustered session-aware Application Server infrastructure (for example &lt;a href=&quot;http://blogs.sun.com/theaquarium/entry/glassfish_3_1_sotd_8&quot;&gt;this glassfish + coherence presentation&lt;/a&gt;). So I decided to study this new solution more deeply. The entry is divided in three different sections: presentation of some HA theory in Application Server world, preparation of a demo and some benchmark results.&lt;p&gt;



&lt;h3&gt;CONCEPTS&lt;/h3&gt;

&lt;p&gt;As always some concepts are needed before the entry goes into the substance. Mainly Application Servers have three different clustered solutions.&lt;/p&gt;

&lt;h4&gt;Load Balancing + Stickyness&lt;/h4&gt;

&lt;p&gt;The first and more easy clustered solution is just a setup with two or more applications servers which receive clients in a sticky way. When I say stickyness I refer to the fact that when a user request has first sent towards a specified server (and the java session has been created in this server) the load balancing element always sends his future requests to the same server. This way the session is maintained in only one server but everything works as expected.&lt;/p&gt;

&lt;p&gt;In this scenario there is no special session treatment and, therefore, if one application server dies all its sessions (clients) are lost. The balancer will detect the server has fallen and all new requests will be redirected against another server but, as sessions are stored individually, the user will have to re-login and previous work (in a shopping cart application for instance) could be lost.&lt;/p&gt;

&lt;p&gt;As you see this solution is very very simple. There are lots of load balancers solutions (software or hardware) and almost all of them support stickyness (using jsessionid tracking cookie) and server status checks. Stickyness can also be used in the other two solutions and, in fact, it is usually recommended.&lt;/p&gt;

&lt;h4&gt;Load Balancing + Session Replication&lt;/h4&gt;

&lt;p&gt;The second solution tries to solve the session lost problem of the previous scenario. Many application servers (all famous ones at least) implement a in-memory session replication. This way when a request modifies any attribute in the session these changes are sent to the rest of servers and, consequently, session is always up to date in all of them.&lt;/p&gt;

&lt;p&gt;This solution solves the main problem but it is not absolutely safe. Some problems are the following: all sessions are in all serves (this is the main one, think about a ten server cluster with thousands and thousands of sessions), replication is not immediately done, performance drops when a lot of sessions are involved or they are very big and, if all servers die unexpectedly, they are also lost.&lt;/p&gt;

&lt;h4&gt;Load Balancing + HA Storage&lt;/h4&gt;

&lt;p&gt;The final solution is to use another persistent element to store sessions (Application Server can save sessions only in the repository or in both sites, its own heap and in the new repository). This solution has two main problems, the High Availability feature is moved from Application Servers to the external repository and the performance penalty of storing and retrieving any session may be major.&lt;/p&gt;



&lt;h3&gt;DEMO&lt;/h3&gt;

&lt;p&gt;The third solution presented before used to be not very common, mainly because the repository for storing sessions traditionally was a database, which represents a severe performance impact and a clustered database was also needed (you know, the box was worth more than its contents). So usually AppServer HA solutions were reduced to the first (when session lost was not a decisive penalty) or the second scenario (when a session-aware cluster was really needed). Nevertheless, after &lt;a href=&quot;http://memcached.org/&quot;&gt;memcached&lt;/a&gt;, the in-memory backends are getting more and more popular and this kind of external repositories can solve, in theory, all the typical problems of JDBC stores. When I heard about this idea (as I commented in the beginning of the entry some commercial Application Servers are starting to offer this solution) I checked if there was any open source implementation for doing the same and I found the &lt;a href=&quot;http://code.google.com/p/memcached-session-manager&quot;&gt;memcached-session-manager or MSM&lt;/a&gt; project. MSM honors its name and it is exactly that, a session manager for &lt;a href=&quot;http://tomcat.apache.org&quot;&gt;tomcat&lt;/a&gt; (6 and 7) and memcached. So the rest of this chapter I am going to explain how to setup the previous three scenarios using tomcat. &lt;/p&gt;

&lt;p&gt;Obviously a distributable application is also needed for testing. For that I am going to merge two Web Modules (WAR files). On the one hand, the typical glassfish example &lt;a href=&quot;http://glassfish.java.net/javaee5/build/GlassFish_LB_Cluster.html#deploy&quot;&gt;clusterjsp&lt;/a&gt; application, some JSPs which are very useful to check if Load Balancing and Clustering is working. On the other, the &lt;a href=&quot;http://www.webperformance.com/library/reports/ServletReport/&quot;&gt;ServletBenchmarck&lt;/a&gt;, a quite well thought application to bechmark Servlet engines. I have added the JSPs of clusterjsp inside ServletBenchmark war file so I can test individually and benchmark at the same time (here it is &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/ServletBenchmark.war&quot;&gt;the war file I deployed&lt;/a&gt; inside tomcats).&lt;/p&gt;

&lt;h4&gt;Tomcat + Apache2/mod_jk&lt;/h4&gt;

&lt;p&gt;For the first scenario typical &lt;a href=&quot;http://tomcat.apache.org/connectors-doc-archive/jk2/&quot;&gt;mod_jk&lt;/a&gt; balancing is going to be used. The mod_jk is a module for Apache2 that interacts with tomcat servers using AJP 1.3 protocol. It supports load balancing, server checks and stickyness. I installed two debian Squeeze boxes using KVM virtualization. Then I setup two apaches and two tomcats with stickyness enabled, debian packages have been used for everything (there are a lot of installation guides over the internet, for example &lt;a href=&quot;http://blog.jerrevds.be/article/apache2-tomcat6-debian&quot;&gt;this one&lt;/a&gt;). Here it is my &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/workers.properties&quot;&gt;workers.properties&lt;/a&gt; if you want to check it out.&lt;/p&gt;

&lt;p&gt;With this configuration the following video is presented. When I access apache the mod_jk module redirects my request against one of the tomcats. Using clusterjsp page some attributes are added to the session, as configuration is sticky, same tomcat is always accessed. To test Load Balancing I kill the server which is being used. As you see the other tomcat takes the control but session is empty as expected.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/HighAvailabilityinApplicationServers/out-lb.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;h4&gt;Tomcat + Apache2/mod_jk + Session Replication&lt;/h4&gt;

&lt;p&gt;The second scenario can be easily implemented because of &lt;a href=&quot;http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html&quot;&gt;cluster tomcat feature&lt;/a&gt;. This configuration makes each tomcat Server to broadcasts topology and session changes to other servers in the cluster (it seems tomcat uses multicast for spreading changes). In order to configure tomcat inside a cluster only some minor changes in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/server-cluster.xml&quot;&gt;server.xml&lt;/a&gt; are needed.&lt;/p&gt;

&lt;p&gt;With this setup now the video is better. After I kill the first accessed tomcat and mod_jk redirects my request to the other one, my session is still alive and all the attributes are still displayed. Replication is doing the job!&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/HighAvailabilityinApplicationServers/out-cluster.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;h4&gt;Tomcat + Apache2/mod_jk + memcached-session-manager&lt;/h4&gt;

&lt;p&gt;This is a more interesting and newer scenario. For this configuration I decided not to use memcached (like MSM expects) but &lt;a href=&quot;http://www.membase.org&quot;&gt;membase&lt;/a&gt;. Membase is a next generation memcached with several improvements (mainly because it is not a cache, it is a real NoSQL database which stores data in disk, has replication features and manages topology changes) but keeps all goodness (simplicity, elasticity, very fast,...). &lt;/p&gt;

&lt;p&gt;The main reason for this change is how I understand this solution. For me the external repository must handle HA independently and memcached is just a cache system, it does not cover replication or even a server fault (for this reason MSM stores a second backup session when more than one memcached is configured). But membase uses the idea of &lt;a href=&quot;http://techzone.couchbase.com/wiki/display/membase/Membase+Data+Buckets&quot;&gt;buckets&lt;/a&gt;, which are isolated virtual containers for data and they are currently of two types: memcached (same old characteristics) or membase type (new features of persistence, replication and rebalancing). Actually &lt;a href=&quot;http://techzone.couchbase.com/wiki/display/membase/Failover+with+Membase&quot;&gt;membase does not perform an automatic rebalancing&lt;/a&gt;, if a server fails an administrator must rebalance the cluster manually via the web console or via script (semi-automatic rebalancing). In my opinion for session storage the persistence part (saving data in disk) is not necessary, although sessions can survive through membase reboots I think the cost is greater than the benefits. So if membase had a bucket with only replication and rebalancing I think it would be the best configuration for this goal. Think about that, a membase without disk storage is the perfect extension of the second scenario, session is replicated only the configured times (in a membase cluster you can set how many copies are saved) and space is not wasted in all tomcats. Of course there are some disadvantages like tomcat accesses to membase every request (but membase is supposed to be very fast) and partial replication is not possible (membase is a general purpose repository so it does not know anything about sessions or attributes). But, in general, I think a in-memory replicated repository could be the best solution for an architecture with a lot of servers, a lot of sessions or very big ones.&lt;/p&gt;

&lt;p&gt;As I said MSM is thought to be configured against, at least, two memcached servers (one for main session storage and the second as a backup if the first one fails) but I will only configure one (membase replicates information instead of MSM). Clients for membase can be of two types (see &lt;a href=&quot;http://techzone.couchbase.com/wiki/display/membase/Client+Libraries#ClientLibraries-TypesofMembaseClients&quot;&gt;membase types of clients&lt;/a&gt;) and MSM uses the &lt;a href=&quot;http://code.google.com/p/spymemcached/&quot;&gt;spymemcached&lt;/a&gt; library which is of type 1 (typical memcached client which is not aware of cluster topology). For this situations membase deploys a gateway process (called moxi) which is the responsible of redirect the requests to the correct membase server (for more information about &lt;a href=&quot;http://techzone.couchbase.com/wiki/display/membase/Moxi&quot;&gt;moxi gateway see membase documentation&lt;/a&gt;). So finally I setup a two node membase cluster (one in each debian box), with default membase type bucket (one extra copy configured) and each tomcat instance accesses the server-side moxi. The membase software was installed using community 64bit debian package downloaded from &lt;a href=&quot;http://www.couchbase.com/downloads&quot;&gt;couchbase site&lt;/a&gt;. MSM was configured following its beautiful and simple &lt;a href=&quot;http://code.google.com/p/memcached-session-manager/wiki/SetupAndConfiguration&quot;&gt;guide&lt;/a&gt;, I used non-sticky configuration (although I use sticky mod_jk workers I wanted that sessions were always retrieved and stored) and &lt;a href=&quot;http://code.google.com/p/kryo/&quot;&gt;kryo&lt;/a&gt; recommended serialization.&lt;/p&gt;

&lt;p&gt;As usual my setup fell into a MSM bug, a lot of objects remained in membase when sessions were invalidated (they are not removed). The problem seemed to be that the code always tried to delete the backup session object although it had not been created previously (cos only one memcached is configured), it thrown an exception and other object was not removed (MSM stores two objects per session). I fixed the problem and, as usual, I try to be a friendly neighbor and I sent an email to MSM main developer explaining my case (Martin Grotzke kindly opened an &lt;a href=&quot;http://code.google.com/p/memcached-session-manager/issues/detail?id=95&quot;&gt;issue&lt;/a&gt; for me).&lt;/p&gt;

&lt;p&gt;After the bug was fixed a membase session storage system was correctly working. Now the sessions are always retrieved and then saved from/to membase on every client request to tomcat. So now in the video when the server is killed the other one successfully retrieves the session from membase and the attributes are still there. But even better, if I kill both Tomcats and I start the first one killed my session is still active (cos membase stores it outside tomcat). In the membase statistics page for default bucket the new session objects has been created.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://rickyepoderi/uploads/HighAvailabilityinApplicationServers/out-membase.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;I also wanted to test a JDBC solution (in order to have a comparison with previous SQL backends) and I tried to configure &lt;a href=&quot;http://tomcat.apache.org/tomcat-6.0-doc/config/manager.html&quot;&gt;tomcat JDBC Store and the Persistence Manager&lt;/a&gt; with MySQL (I tried to follow &lt;a href=&quot;http://www.intelligrape.com/blog/2010/07/21/tomcat-6-session-persistence-through-jdbcstore/&quot;&gt;this guide&lt;/a&gt;). But it did not work for me. Although sessions survived through tomcat restarts they were almost never persisted when tomcat was killed. It seemed like sessions were not always stored inside the table and they were just inserted based on a time scheduling. In short I was not able to make sessions to be inserted immediately in the database (if someone is smarter than me please comments will be appreciated). And I have to admit this point is a real pity for the next point.&lt;/p&gt;



&lt;h3&gt;BENCHMARK&lt;/h3&gt;

&lt;p&gt;Finally I set up a benchmark to test the three scenarios. As I commented the ServletBenchmark is a smart application that simulates a common web navigation (check the application link previously presented for details). In this case it was specially interesting cos this benchmark manages session with three different types of users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short size (10 bytes) and short lived session (one request).&lt;/li&gt;
&lt;li&gt;Medium size (up to 150 bytes) and medium lived session (five requests).&lt;/li&gt;
&lt;li&gt;Long size (up to 2100 bytes) and long lived session (20 requests).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I prepared &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/ServletBenchmark.jmx&quot;&gt;this JMeter test plan&lt;/a&gt; which launches 60 concurrent threads looping over the three ServletBenchmark cases for half an hour. In each loop the thread has 20% of probabilities to execute the short scenario, 30% the medium and 50% the long one. When the scenario is completed the thread sleeps for 1 second and then invalidates the session. Architecture is also very important for understanding any benchmark. And, as I explained before, my demo site is a crap: all inside my laptop; two KVM virtualized Debian Squeeze linux (apache2, tomcat and membase installed in each); the JMeter benchmark tool in my real Debian laptop pointing to the first apache. So it is clear numbers are not very important, just the difference between them.&lt;/p&gt;

&lt;p&gt;You can download the complete results for the three scenarios (&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/Statistics-LB.csv&quot;&gt;Load balancing&lt;/a&gt;, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/Statistics-CLUSTER.csv&quot;&gt;replication cluster&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/Statistics-MEM.csv&quot;&gt;membase solution&lt;/a&gt;). And here they are the numbers via charts and graphics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average response time and 90% Line time (response time in which the 90% of requests were completed) for the three solutions.&lt;/li&gt;
&lt;li&gt;JMeter graph results for the three scenarios.&lt;/li&gt;
&lt;li&gt;Membase statistics (screenshot of the default bucket statistics).&lt;/li&gt;
&lt;li&gt;CPU consumed (top used) by involved processes (in the third scenario tomcat and membase percents have been added). Two graphs, one for each debian box.&lt;/li&gt;
&lt;/ul&gt;

 
 

 
&lt;div class=&quot;highslide-gallery&quot;&gt; 

&lt;a id=&quot;pfc_thumb1&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/times.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/times-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Average response time and 90% Line time
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb2&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-lb.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-lb-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        JMeter graph results for Load Balancing scenario
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb3&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-cluster.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-cluster-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        JMeter graph results for Replication Cluster scenario
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb4&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-membase.jpg&quot; class=&quot;highslide&quot;&gt; 
	&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/graph-membase-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt; 
&lt;div class=&quot;highslide-heading&quot;&gt; 
	JMeter graph results for Membase scenario
&lt;/div&gt; 

&lt;a id=&quot;pfc_thumb5&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/membase-statistics.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/membase-statistics-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Membase statistics for default bucket
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb6&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/cpu-debian1.jpg&quot; class=&quot;highslide&quot;&gt;
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/cpu-debian1-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt;
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        CPU used in debian box 1
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb7&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/cpu-debian2.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/HighAvailabilityinApplicationServers/cpu-debian2-preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        CPU used in debian box 2
&lt;/div&gt;

&lt;/div&gt;

&lt;p&gt;For me the results are exactly what I had in mind before the benchmark. First and important, there is no error in any of the tests, so the three solutions are very reliable. A thing that surprise me is that numbers are quite low (6, 7 and 11 ms for average response time respectively). This means KVM works really well and, maybe, as everything is deployed in the same physical box, communication latencies are nearly zero. If we look at the response times things work as expected. Each solution gives more availability than the previous one with a cost in performance. But this cost seems reasonable, only 1 ms in replication over simple load balancing and 4 ms in membase solution over replication cluster. And in the 90% line, distances remain the same (which means three solutions work quickly most of the times). When checking the CPU used, load balancing uses around 5-7% of the CPU time, replication over 12-14% and membase (tomcat + membase daemons) over 20-23%. They are also expected except that membase is a little more of what I thought, tomcat process itself is a bit more CPU hungry than in replicated scenario (cost of serialize the whole session) and membase processes (moxi, memcached and beam) add around 6-7% more.&lt;/p&gt;

&lt;p&gt;Final comments, the benchmark has not stressed the system enough (I think I would have needed more threads, lower sleeping times or a more intense application but I also think that this is more than enough for what I wanted to show). The membase scenario is a really good competitor, cos a 4-5ms penalty is almost nothing in my opinion (think in a real scenario where requests do some real processing and can last for 100ms or more). And remember these numbers can be even lower if membase do not save sessions in disk. It was a real pity that the numbers of a real JDBC solution cannot be compared (seeing what is the real distance between new membase NoSQL solution and a traditional MySQL/PostgreSQL one would have been great). Of course this membase solution is not in a production ready state (there are some snags, mainly with membase HA) but the goal of this entry was testing if this kind of in-memory softwares are convenient as session stores (numbers have been presented) and, at the same time, checking some real open-source scenario.&lt;/p&gt;

&lt;p&gt;I have invest some time in this benchmark but it was a thing I really wanted to do. I hope it was worthy for someone else. See you next time! &lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>sáb, 02 abr 2011 10:33:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Friday Night Fever (or How a Computer Guy Spends the Friday Night)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/31-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/31-Friday-Night-Fever-or-How-a-Computer-Guy-Spends-the-Friday-Night.html</link>
	<description>&lt;p&gt;For some strange reasons this week I needed to use my &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/21-DNIe-and-the-Signature-Applet.html&quot;&gt;Spanish eID (DNIe) again&lt;/a&gt; and, sometimes these things happen, firefox hanged like crazy. Finally I had to reboot my system to use the platform pre-installed windows to complete the formality. Yesterday night I decided to find out what the hell was going on here.&lt;/p&gt;

&lt;p&gt;As always I put opensc in debug mode (setting debug to 10 in &lt;em&gt;/etc/opensc/opensc.conf&lt;/em&gt;) and what I saw was really amazing. Starting firefox (iceweasel) inside a terminal the debug dumped like crazy but it sometimes hanged for exactly 60 seconds. So it was not totally frozen, it worked quite well but sometimes it was waiting for something one minute. The problem is opensc calls a lot to the card and firefox hangs at least two or three times every startup (which means more than two or three minutes waiting firefox to come up).&lt;/p&gt;

&lt;p&gt;First thing to always check in these situations is what has been changed (I have a thing about upgrading my Debian laptop). Since the time I wrote the DNIe entry the &lt;a href=&quot;http://www.opensc-project.org/opensc&quot;&gt;opensc&lt;/a&gt; packages (the project that deals with PKCS#11 and PKCS#15) remain the same, &lt;a href=&quot;http://pcsclite.alioth.debian.org/&quot;&gt;PC/SC lite&lt;/a&gt; (the project for communicating with smartcards and readers) has been upgraded from 1.5.5 to 1.6.6 and &lt;a href=&quot;http://pcsclite.alioth.debian.org/ccid.html&quot;&gt;libccid&lt;/a&gt; (the handler library for my reader) from 1.3.11 to 1.4.2. I decided to come back to original packages (uninstalling and installing the old ones) to see what happened and, voilĂ , it started to work as before, no watings.&lt;/p&gt;

&lt;p&gt;At that moment I was not totally happy cos I do not feel comfortable when I do not know what really happens and, even less, holding packages. So I started compiling by myself the complete software stack, first PC/SC lite 1.7.0, then libccid 1.4.2 and then opensc 0.12.1. But with opensc I changed my mind and I compiled it twice. First the old source from  DNIe official page (opensc-dnie), the external library I talked about in the old entry, and opendnie (see &lt;a href=&quot;http://www.opensc-project.org/pipermail/opensc-devel/2011-February/015952.html&quot;&gt;this mail&lt;/a&gt; and &lt;a href=&quot;http://www.kriptopolis.org/opendnie-listo&quot;&gt;this spanish blog&lt;/a&gt;), the effort of a Spanish guy to re-implement all the stuff to include Spanish eID into opensc without legal issues (maybe this work deserves a new entry). I had been thinking about opendnie for some time but I had never had the the time to test it. The old source code for opensc-dnie now does not compile, the problem is &lt;a href=&quot;http://www.mirrorservice.org/sites/www.gnupg.org/related_software/libassuan/index.html.en&quot;&gt;libassuan&lt;/a&gt; (the little window the library shows when you are about to sign something) has changed its api. But checking &lt;a href=&quot;http://www.opensc-project.org/opensc/attachment/ticket/217/opensc-libassuan-2.patch&quot;&gt;opensc patch&lt;/a&gt; the modification of dialog.c was easy (here it is the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/FridayNightFever/dialog.c.patch&quot;&gt;patch&lt;/a&gt; if you want to use it). Opendnie compiled with no issues.&lt;/p&gt;

&lt;p&gt;Testing and debugging I realized the problem was not in any of these packages but in &lt;a href=&quot;http://www.libusb.org/&quot;&gt;libusb&lt;/a&gt; (the spurious hang also happened in my compiled versions and it did not matter you use opendnie or opensc-dnie). Now libccid 1.4.x is linked against libusb-1.0 (thing that did not happen with 1.3.x) and this is the reason the bug came out after the upgrade. So I also compiled libusb 1.0.8 and I saw the problem was inside &lt;em&gt;libusb_control_transfer&lt;/em&gt; function. This function sends the transfer to the usb device and then waits for the response with a 60 seconds timeout. Finally I changed the fixed 60 seconds and tried again. And it worked, both solutions (opendnie and opensc-dnie) hanged no more. My patch was very crappy and straight forward but I opened a &lt;a href=&quot;http://www.libusb.org/ticket/103&quot;&gt;bug&lt;/a&gt; against libusb. At that time it was around 2 am at night and I had not even dinner. You know... &lt;strong&gt;it was a computering Friday night fever!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today in the morning Ludovic Rousseau (the PC/SC and CCID guy) answered me saying this bug was known. He opened &lt;a href=&quot;http://www.libusb.org/ticket/56&quot;&gt;a ticket six months ago&lt;/a&gt; with a resolution patch inside but it is not closed yet (and Ludovic seems not very happy with that). I sent another post saying my issue can therefore be closed and then I tested Ludovic's patch. The patched libusb also worked correctly so I sent a final comment to Ludovic's ticket saying his patch fixed my issue (at this moment both posts are not displayed cos libusb moderates the comments). And that is all. I do not know how other jobs are but we are masochists and (worst of all) we enjoy it. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;</description>
	<pubDate>sáb, 19 mar 2011 14:59:57 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: RGraph Scatter Plot using WebSockets</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/29-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/29-RGraph-Scatter-Plot-using-WebSockets.html</link>
	<description>&lt;p&gt;Today entry is the last one (at east for the moment) about the Scatter Graph problem. If you remember this series started as a HTML5 migration study of an old applet scatter graph application, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html&quot;&gt;the first post tried to implement a XY client-side graph using Canvas element&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/27-Improving-RGraph-Plot-with-Real-Data-via-Web-Services.html&quot;&gt;the second one added Web Services real samples&lt;/a&gt; (prototypejs + JSON + JAX-RS). Now I am going to replace the Web Services for a new HTML5 feature: &lt;a href=&quot;http://en.wikipedia.org/wiki/Websockets&quot;&gt;WebSockets&lt;/a&gt;. I had no experience at all with them and I think this is a good example where this new technique fits smoothly.&lt;/p&gt;

&lt;p&gt;WebSockets are a new protocol coordinated by the &lt;a href=&quot;http://www.ietf.org&quot;&gt;IETC (The Internet Engineering Task Force)&lt;/a&gt; that tries to complement our old friend HTTP which falls short in some aspects of the Web 2.0. A WebSocket is a bidirectional (communication can be started by server or client), full-duplex (both ends can send information at the same time), minimal overhead (only two bytes are used in each frame), long lived (it remains opened until an end explicitly closes it) communication channel over a single TCP socket. Standardized by the W3C &lt;a href=&quot;http://dev.w3.org/html5/websockets/&quot;&gt;the JavaScript WebSockets API&lt;/a&gt; is completely asynchronous and very easy to use. The protocol also defines new &lt;em&gt;ws://&lt;/em&gt; and &lt;em&gt;wss://&lt;/em&gt; prefixes which indicate a WebSocket and a WebSocket Secure connection respectively. This technique is clearly defined for avoiding all the pain associated with AJAX/Web2.0 frameworks (overcoming HTTP limitations, more simplicity, better performance,...).&lt;/p&gt;

&lt;p&gt;The technology has been hardly pushed by Google since the beginning, obviously this company is very interested in simplifying and improving web 2.0 applications. Therefore Chrome supports WebSockets since its version 4.0 and Apple joined later with Safari 5. Until some months ago the adoption was going smoothly with firefox 4 and Opera 11 announcing WebSockets as one of their new features. Nevertheless they turned out wrong when a protocol security flaw was discovered (&lt;a href=&quot;http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76&quot;&gt;standard is still in draft version 76&lt;/a&gt;). Adam Barth showed how a malicious code can be injected in the browser using a technique called cache poisoning (exploiting a problem in the initial handshake between client and server when a web proxy is involved). Some days after the bug was reported firefox announced the new feature would be disabled by default in its new beta and same did Opera. Microsoft was always more reluctant to WebSockets, even before the security flaw was pointed out they had not said a word about this protocol and IE9. In my opinion WebSockets is a perfect example of the current anxiety about the web (all browsers trying to support any new feature before competitors, no matter if the technique is mature or not, at the same time they put any stumbling block in another's path) but the technology behind them is clearly a good idea that just needs more time. Here it is &lt;a href=&quot;http://news.cnet.com/8301-30685_3-20025272-264.html&quot;&gt;a good and more detailed report of these events&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So now my scatter graph application is going to obtain the samples using a WebSocket instead of the prototype/JAX-RS web service. In order to use the new protocol both sides need to support it, for the client part default debian Chromium 6 will be used and Glassfish 3.1 (RC2 - b41) will be our Application Server (Glassfish uses &lt;a href=&quot;http://grizzly.java.net&quot;&gt;Grizzly&lt;/a&gt; as its Web Server component which is the piece of software that &lt;a href=&quot;http://blogs.sun.com/oleksiys/entry/grizzly_1_9_19_beta2&quot;&gt;really supports WebSockets&lt;/a&gt;). In the implementation side almost all remain the same but the following changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The JAX-RS resource class is replaced by a &lt;a href=&quot;http://grizzly.java.net/nonav/docs/1.9/apidocs/com/sun/grizzly/websockets/WebSocketApplication.html&quot;&gt;WebSocketApplication (Grizzly WebSocket 1.9 API)&lt;/a&gt;. &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/PlotApplication.java&quot;&gt;PlotApplication.java&lt;/a&gt; is the real class and JAXB is still being used for marshalling and unmarshalling stuff (the same PlotData object is used but JAXB is now directly called). Other difference is that JSON is now used in both ways (communication from Server/Java to browser/JavaScript and vice-versa).&lt;/li&gt;
&lt;li&gt;The WebSockets technology in Grizzly needs a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/WebSocketsServlet.java&quot;&gt;WebSocketsServlet.java&lt;/a&gt; to integrate the previous application into the WAR module. &lt;a href=&quot;http://antwerkz.com/glassfish-web-sockets-sample/&quot;&gt;GlassFish Web Sockets Sample&lt;/a&gt; and &lt;a href=&quot;http://weblogs.java.net/blog/spericas/archive/2010/09/29/web-sockets-and-html5-glassfish&quot;&gt;Web Sockets and HTML5 in Glassfish&lt;/a&gt; are two good entries about how to implement a WebSocket Application using Glassfish/Grizzly.&lt;/li&gt;
&lt;li&gt;The WebSocket application uses the same JPA entities to access the database but now a simple EJB &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/PlotQueryEjb.java&quot;&gt;PlotQueryEjb.java&lt;/a&gt; has been implemented (adding @Stateless annotation to the WebSocket application threw  an exception). CDI is used for injection as usual.&lt;/li&gt;
&lt;li&gt;The JavaScript in the server side also needs to be changed, basically prototype.js is replaced by the WebSocket API. So now the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/TestRGraphChart.js&quot;&gt;TestRGraphChart.js&lt;/a&gt; (JavaScript object) and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/TestRGraphChart.xhtml&quot;&gt;TestRGraphChart.xhtml&lt;/a&gt; (Facelets page) are slightly modified in the sending/receiving part. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For all these reasons the video this time is similar and less interesting. I first execute a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/test.html&quot;&gt;test.html&lt;/a&gt; page that shows the JSON data exchanged, only WAVE type is requested so the last 24 hours of wave highs are returned, the WebSocket is then closed. After that the same actions of the previous scatter graph video are performed (first showing sea level magnitude, one sample per minute, and then waves, one per hour). The WebSocket scatter graph has been tested with Chromium 6 and firefox4 b11 obtaining a good and smooth usability (&lt;a href=&quot;http://techdows.com/2010/12/turn-on-websockets-in-firefox-4.html&quot;&gt;FF4 needs to override the security block for WebSockets&lt;/a&gt;).&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;In short this entry is a presentation of the WebSockets, another HTML5 improvement. WebSockets are not just a new feature they are really a new protocol definition standardized to make an easier and better Web 2.0. Its adoption is being full of obstacles and many browsers do not support them by default (only Chrome and Safari right now). So current entry has to be intended as a training application and not a production ready example. You can download &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/RGraphScatterPlotusingWebSockets/ScatterPlot-WebSockets.zip&quot;&gt;the complete NetBeans project used for the video from here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stay tuned for more about the Web Wars!&lt;/p&gt;</description>
	<pubDate>sáb, 19 feb 2011 11:54:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Pon un sol en tu vida: How device size affects disk performance in Linux (II)</title>
	<guid>http://blogs.nologin.es/slopez/archives/27-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/27-How-device-size-affects-disk-performance-in-Linux-II.html</link>
	<description>I've just noticed that in a virtualized environment, where roundtrips are more expensive, read speed differences between a page-aligned partition and a non page-aligned one are even more noticeable:&lt;br /&gt;
&lt;br /&gt;
Non-aligned partition (size in sectors: (41929649-63)+1=&lt;i&gt;41929587&lt;/i&gt;):&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;none:~# fdisk -l -u /dev/sdb&lt;br /&gt;
&lt;br /&gt;
Disk /dev/sdb: 21.4 GB, 21474836480 bytes&lt;br /&gt;
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors&lt;br /&gt;
Units = sectors of 1 x 512 = 512 bytes&lt;br /&gt;
Disk identifier: 0x93dbf2be&lt;br /&gt;
&lt;br /&gt;
   Device Boot      Start         End      Blocks   Id  System&lt;br /&gt;
/dev/sdb1              63    41929649    20964793+  83  Linux&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=0&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 3.80593 s, &lt;i&gt;27.6 MB/s&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=100&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 3.82304 s, &lt;i&gt;27.4 MB/s&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=200&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 3.83713 s, &lt;i&gt;27.3 MB/s&lt;/i&gt;&lt;/code&gt;&lt;br /&gt;
Page-aligned partition (size in sectors: (41929654-63)+1=&lt;i&gt;41929592&lt;/i&gt;) :&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;none:~# fdisk -l -u /dev/sdb&lt;br /&gt;
&lt;br /&gt;
Disk /dev/sdb: 21.4 GB, 21474836480 bytes&lt;br /&gt;
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors&lt;br /&gt;
Units = sectors of 1 x 512 = 512 bytes&lt;br /&gt;
Disk identifier: 0x93dbf2be&lt;br /&gt;
&lt;br /&gt;
   Device Boot      Start         End      Blocks   Id  System&lt;br /&gt;
/dev/sdb1              63    41929654    20964796   83  Linux&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=0&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 0.618494 s, &lt;i&gt;170 MB/s&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=100&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 0.582423 s, &lt;i&gt;180 MB/s&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=200&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
104857600 bytes (105 MB) copied, 0.589081 s, &lt;i&gt;178 MB/s&lt;/i&gt;&lt;/code&gt;&lt;br /&gt;
&lt;b&gt;NOTE:&lt;/b&gt; In both tests, the data is cached in the host (so there is no real I/O to disks but traffic through virtualization pipes), but clean in the guest.&lt;br /&gt;</description>
	<pubDate>mié, 16 feb 2011 09:10:44 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Pon un sol en tu vida: How device size affects disk performance in Linux</title>
	<guid>http://blogs.nologin.es/slopez/archives/26-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/26-How-device-size-affects-disk-performance-in-Linux.html</link>
	<description>While running some tests in a client's environment, we've noticed reading from a partition of a multipath device was considerably slower than reading from its parent node:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;[root@none]# dd if=mpath4 of=/dev/null bs=1M count=1024&lt;br /&gt;
1024+0 records in&lt;br /&gt;
1024+0 records out&lt;br /&gt;
1073741824 bytes (1.1 GB) copied, 8.92711 seconds, &lt;b&gt;120 MB/s&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
[root@none]# dd if=mpath4p1 of=/dev/null bs=1M count=1024 skip=1024&lt;br /&gt;
1024+0 records in&lt;br /&gt;
1024+0 records out&lt;br /&gt;
1073741824 bytes (1.1 GB) copied, 17.5965 seconds, &lt;b&gt;61.0 MB/s&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
We asked to client support of a well-known GNU+Linux vendor, and they indicated that this behavior was &quot;expected&quot;, since this kind of partitions were created by stacking a &lt;i&gt;dm-linear&lt;/i&gt; device over  the original multipath node. I wasn't satisfied by this answer, since AFAIK dm-linear only did a simple transposition of the original request over an specified offset (the beginning of the partition), so I decided to investigate a bit further on my own.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://blogs.nologin.es/slopez/archives/26-How-device-size-affects-disk-performance-in-Linux.html#extended&quot;&gt;Continue reading &quot;How device size affects disk performance in Linux&quot;&lt;/a&gt;</description>
	<pubDate>mié, 09 feb 2011 08:04:48 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Debian 6.0 released!</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/28-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/28-Debian-6.0-released!.html</link>
	<description>&lt;p&gt;This time a quick entry. As everybody who usually reads this blog knows I use debian testing as my common linux distribution (working laptop and general use desktop). Today I want to present one of the reasons why I love debian. The next version of this operating system is released when it is ready, and when is it ready? When critical bugs are counted down to zero. And &lt;a href=&quot;http://www.debian.org/News/2011/20110205a&quot;&gt;squeeze was ready this morning&lt;/a&gt;:&lt;/p&gt;

&lt;div&gt;
&lt;a href=&quot;http://bugs.debian.org/release-critical/&quot;&gt;
&lt;img class=&quot;serendipity_image_center&quot; src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/Debian6.0released/debian-bugs.png&quot; alt=&quot;debian bugs at 6th of February 2011&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;It is incredible how an open community, where anybody opens, follows and patches bugs, can work in such an efficient  way.&lt;/p&gt;

&lt;p&gt;Congratulations to everyone involved! I admire you guys! And welcome wheezy!&lt;/p&gt;</description>
	<pubDate>dom, 06 feb 2011 09:53:58 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: El Libro sobre el Origen de Nologin</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/133-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/133-El-Libro-sobre-el-Origen-de-Nologin.html</link>
	<description>Nuevo libro publicado por Nologin Publishing:&lt;p align=&quot;center&quot;&gt;&lt;div align=&quot;center&quot; class=&quot;serendipity_imageComment_center&quot;&gt;&lt;!-- s9ymdb:40 --&gt;&lt;img height=&quot;610&quot; width=&quot;508&quot; src=&quot;http://blogs.nologin.es/lfabiani/uploads/nologin/NologinsOrigins.png&quot; class=&quot;serendipity_image_center&quot; /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div align=&quot;left&quot;&gt;Porque, a pesar de lo que dicen en &lt;a href=&quot;http://blogs.nologin.es/lfabiani/archives/128-No-Lata.html&quot;&gt;algunos sitios&lt;/a&gt;, Nologin tiene mĂˇs de 10 aĂ±os.&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;ÂżQuieres un adelanto del contenido? Este es el Ă­ndice:&lt;/div&gt;



 &lt;br /&gt;&lt;a href=&quot;http://blogs.nologin.es/lfabiani/archives/133-El-Libro-sobre-el-Origen-de-Nologin.html#extended&quot;&gt;Continua leyendo &quot;El Libro sobre el Origen de Nologin&quot;&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>mar, 25 ene 2011 14:49:00 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Improving RGraph Plot with Real Data via Web Services</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/27-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/27-Improving-RGraph-Plot-with-Real-Data-via-Web-Services.html</link>
	<description>&lt;p&gt;In a previous entry I talked about &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html&quot;&gt;how to implement a scatter graph using javascript and the new HTML5 canvas element&lt;/a&gt;. This post was just the first step towards a more robust solution. If you remember my intention was studying the feasibility of a migration from an old applet application to a new HTML5 one. Today I will try to continue the PoC plotting real data inside the graph instead of the fixed sine wave (javascript generated) RGraph drew before.&lt;/p&gt;

&lt;p&gt;First of all the real samples must be retrieved from somewhere and, obviously, a relational database is the easiest solution (besides the current application uses a database too). It is important to remember that the scatter plot represents a physical magnitude (wind strength, sea level, high of waves,...) in time. For the PoC some &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Persistence_API&quot;&gt;JPA (Java Persistence API)&lt;/a&gt; entities were created, these classes are very simple. Every sample only contains the timestamp and the measured value. It is clear that in a real scenario tables would usually have more columns (current devices measure several magnitudes at the same time) but I think this is enough for this example. Three classes are presented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/PlotType.java&quot;&gt;PlotType.java&lt;/a&gt;: Enumeration that handles all the plots the application can draw (my idea is simple, if a new plot is needed it has to be added here). SEA_LEVEL and WAVE are the current plot types (Sea Level is measured one sample per minute and the High of Waves one per hour).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/PlotSample.java&quot;&gt;PlotSample.java&lt;/a&gt;: Abstract entity class that represents any sample (as I said, a timestamp and the measured value).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/SeaLevel.java&quot;&gt;SeaLevel.java&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/Wave.java&quot;&gt;Wave.java&lt;/a&gt;: Two examples of real plots, both extend PlotSample and define a &lt;em&gt;&amp;lt;PLOT_TYPE_NAME&amp;gt;-findSamplesBetweenDates&lt;/em&gt; query which is always used to query for the samples between two specified dates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the data is organized a web service is needed. It is quite clear this technique is perfect to retrieve the data for plotting. Nowadays there are a lot of JavaScript libraries to easily call a server-side Web Service (&lt;a href=&quot;http://www.prototypejs.org&quot;&gt;prototypejs&lt;/a&gt;, &lt;a href=&quot;http://jquery.com/&quot;&gt;jquery&lt;/a&gt;,...) and managing &lt;a href=&quot;http://en.wikipedia.org/wiki/JSON&quot;&gt;JSON (JavaScript Object Notation)&lt;/a&gt;. For this part I decided to use &lt;a href=&quot;http://en.wikipedia.org/wiki/JAX-RS&quot;&gt;JAX-RS (Java API for RESTful Web Services)&lt;/a&gt; to implement the service and &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding&quot;&gt;JAXB (Java Architecture for XML Binding)&lt;/a&gt; for generating the JSON data. JAX-RS (which I had rarely used) is incredible easy and very good services are implemented in a little time. Besides JSON can be specified as the result to be produced and this, using JAXB at the same time, lets you return a Java object avoiding all JSON generating stuff. Only two classes are presented here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/PlotData.java&quot;&gt;PlotData.java&lt;/a&gt;: This is the JAXB element that represents the data to be plotted by the browser. The data returned when a scatter plot is going to be drawn is just a simple class with some properties (start and end timestamps, plot type name, description,...) and a map with the samples (value keyed by the timestamp).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/PlotResource.java&quot;&gt;PlotResource.java&lt;/a&gt;: The JAX-RS resource which receives the name of the plot type to graph, start and end timestamp. With this information it queries the database and creates the PlotData to be returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two important tips here. First, JavaScript (in my opinion) handles the timezone in dates not very good. The date object is created using the timezone of the browser/system (GMT+1 in my case) but it is quite difficult to convert from one timezone to another. The date object has a getTimezoneOffset method that returns the offset in minutes between your zone and GMT, but your code needs to add and subtract offsets all the time. For this reason I decided to manage timestamps (milliseconds since standard epoch of 1/1/1970) instead of string dates. A timestamp will be represented in JSON with a String containing the big number of milliseconds prefixed by a character &lt;em&gt;&quot;T&quot;&lt;/em&gt; (for example the epoch 1/1/1970 would be the string &lt;em&gt;&quot;T0&quot;&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Second, I wanted the JSON response was (more or less) the following: &lt;/p&gt;

&lt;pre&gt;
{
  &quot;type&quot;:&quot;WAVE&quot;,
  &quot;start&quot;:&quot;T1295095138172&quot;,
  &quot;end&quot;:&quot;T1295181538172&quot;,
  &quot;description&quot;:&quot;High of the waves&quot;,
  &quot;legend&quot;:&quot;Meters (m)&quot;,
  ...
  &quot;data&quot;:
  {
    &quot;T1295096400000&quot;:&quot;3.4&quot;,
    &quot;T1295100000000&quot;:&quot;3.16&quot;,
    &quot;T1295103600000&quot;:&quot;3.52&quot;,
    ...
  }
}
&lt;/pre&gt;

&lt;p&gt;The JSON data part (the list/map of samples) should be the pair timestamp and value, which is the natural way to represent a map in JSON. Nevertheless JAXB has some problems with maps and they are not represented in this natural way (see RFE &lt;a href=&quot;http://java.net/jira/browse/JERSEY-551&quot;&gt;JERSEY-551&lt;/a&gt; for more info). So I added the JsonMapAdapter.java class this enhancement manages in order to obtain the JSON representation I showed before.&lt;/p&gt;

&lt;p&gt;So now the browser can query via the restful web service in order to obtain the data to plot. The final part is performing some little changes in the JavaScript developed for the previous post, now the  array of samples has to be retrieved calling the Web Service. The presentation part are the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/PlotTypeBean.java&quot;&gt;PlotTypeBean.java&lt;/a&gt;: A extremely simple request scoped JSF bean only used to list the plot types defined in the application (the combo box at the right) and select one of them.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/TestRGraphChart.xhtml&quot;&gt;TestRGraphChart.xhtml&lt;/a&gt;: XHTML page very similar to the one used in the first entry but using facelets/JSF in order to call the previous bean and so on.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/TestRGraphChart.js&quot;&gt;TestRGraphChart.js&lt;/a&gt;: The JavaScript file that uses &lt;a href=&quot;http://www.prototypejs.org/download&quot;&gt;prototype.js&lt;/a&gt; and &lt;a href=&quot;http://www.javascripttoolbox.com/lib/date/&quot;&gt;JavascriptToolbox data.js&lt;/a&gt; to call the web service and parse/manage JSON and timestamps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the PoC is ready, RGraph plots a scatter XY graph of which data is retrieved via Web Service. The application was deployed in a Java EE 6 compatible application server (Glassfish v3) using its default database engine (derby/javadb). I personally think this is an elegant solution for my problem, all the plotting part is done by the browser and the server only sends the samples to draw. The solution works quite well in browsers with decent canvas performance (which are all the current browsers except IE8, check the previous post). In the video I first call restful web service with WAVE plot type (high of waves), I use no parameters so it returns 24 hours of data (WAVE plot type has one sample per hour). I change to the graph page in order to display the whole day of the sea level plot (one sample per minute). I also move the graph forward and reverse in time. Then I increase the range of time to display a whole week of data (less than 10,000 points cos I did not insert in my database the whole week of samples). And then I choose the time range to plot selecting directly over the canvas element. Finally I select the other plot type, high of waves again. As you can see it works very well in my chromium 6 browser. The application is also very smooth in iceweasel 3.5 and epiphany 2.30 (the other two browsers I have installed in my debian box).&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;At the moment the JavaScript always requests all the samples to plot. It is clear that some data can be reused (for example when the plot is moved forward or reverse) and the JavaScript could be improved to only request the missing samples and after join all of them. You can improve that part if you need and want it.&lt;/p&gt;

&lt;p&gt;As a summary this entry goes one step further in the scatter graph problem. Now the solution plots real data. Data which is read from a database and requested by the browser using a RESTful Web Service and JSON. Here I present &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/ImprovingRGraphPlotwithRealDataviaWebServices/ScatterPlot.zip&quot;&gt;the complete NetBeans project&lt;/a&gt; (without any jar file as usual). As I said in the first entry of this series the PoC is currently unusable (or at least without a second plan for IE8), but the time for triggering HTML5 features is getting closer day by day...&lt;/p&gt;

&lt;p&gt;Please plot a smile in your face! &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;</description>
	<pubDate>vie, 21 ene 2011 22:29:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Decision Taken</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/25-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/25-Decision-Taken.html</link>
	<description>&lt;p&gt;Finally I decided to leave &lt;a href=&quot;http://www.nologin.es&quot;&gt;nologin&lt;/a&gt;. It has been a fabulous nine years here but I feel now it is time for a change. Our paths have been diverging for some time and now I think it is the correct time to walk separately. I will really miss you all but we will surely keep in touch.&lt;/p&gt;

&lt;p&gt;Now I have to realize I am not here and I am working at other place. I am putting my new helmet on...&lt;/p&gt;

&lt;div&gt;
&lt;img class=&quot;serendipity_image_center&quot; src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/DecisionTaken/ricky-magneto.png&quot; alt=&quot;putting the helmet on!&quot; /&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;span&gt;&amp;ldquo;&lt;strong&gt;&lt;em&gt;Maybe you can finally understand that it is possible to be true to your goal and still pursue your own personal happiness. The two are not mutually exclusive.&lt;/em&gt;&lt;/strong&gt;&amp;rdquo;&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&amp;#160;&amp;#160;- Magneto to Professor Charles Xavier in Uncanny X-Men Vol 1 #309 (Scott Lobdell - John Romita Jr)&lt;/span&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think nologin let me continue this blog right here. But stay calm if entries are less frequent, my life is changing in these moments and maybe I need some time to get used to it.&lt;/p&gt;</description>
	<pubDate>mar, 04 ene 2011 07:45:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: CalDAV and the Whitepages Portlet</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/26-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/26-CalDAV-and-the-Whitepages-Portlet.html</link>
	<description>&lt;p&gt;In the past weeks the blog received some comments about the old caldav introduction series. If you remember this series consists of two entries, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html&quot;&gt;the first one introduces caldav and presents some http/webdav methods&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/15-Introducing-CalDAV-Part-II.html&quot;&gt;the second post shows some real caldav requests&lt;/a&gt;. At that time I decided to not attach the complete project but linking every java file when it goes into stage. I thought this way would result in a better understanding but, obviously, I was wrong. For this reason I finally changed my mind and I am going to present the whole project and a real PoC example.&lt;/p&gt;

&lt;p&gt;For some months I have been thinking in improving my little whitepages portlet (shown in both VoIP entries, &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/6-Integrating-Skype-into-a-Portal.html&quot;&gt;Skype internet solution&lt;/a&gt; and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/7-Integrating-VoIP-into-a-Portal.html&quot;&gt;Pidgin/OpenFire custom intranet project&lt;/a&gt;). It would be great if the whitepages, besides VoIP presence and interaction capabilities, could show the events or free/busy information for a specified company mate. This way any colleague can see what events has any other mate arranged for today and act accordingly.&lt;/p&gt;

&lt;p&gt;It is quite clear that CalDAV is perfect for accessing the company calendar solution. In this case I have not installed any Calendar software (like I did with open sourced &lt;a href=&quot;http://trac.calendarserver.org&quot;&gt;Calendar Server&lt;/a&gt; in the CalDAV entries) and the whitepages portlet will work against internet google and Yahoo! calendars. Finally I configured Yahoo! as the default calendar cos google does not support &lt;em&gt;free-busy-query&lt;/em&gt; in its CalDAV implementation.&lt;/p&gt;

&lt;p&gt;Before implementing the whitepages extension I worked with the old CalDAV project. Some jackrabbit libraries have been upgraded to new 2.2.0 version and another report has been implemented: &lt;strong&gt;free-busy-query&lt;/strong&gt;. This report queries for the free/busy information of a user in a specified time. Its response only shows when the user has some events arranged, is busy, and when is free, but not specifying any detail of any event. If you check the libraries, jackrabbit-webdav depends on the old &lt;a href=&quot;http://hc.apache.org/httpclient-3.x/&quot;&gt;Commons HttpClient 3.1&lt;/a&gt; which was superseded long time ago by a new &lt;a href=&quot;http://hc.apache.org/httpcomponents-client-ga/&quot;&gt;HttpClient in the HttpComponents&lt;/a&gt; project (actual GA version 4.0.3). But its API has been deeply changed and jackrabbit needs some time to upgrade (see bug &lt;a href=&quot;https://issues.apache.org/jira/browse/JCR-2406&quot;&gt;JCR-2406&lt;/a&gt; for more details). This is an important issue to consider before choosing jackrabbit-webdav and I did not comment it before. As I promised here it is &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CalDAVandtheWhitepagesPortlet/caldav.zip&quot;&gt;the complete CalDAV NetBeans project&lt;/a&gt; (libraries are missing because of space).&lt;/p&gt;

&lt;p&gt;As I commented in previous VoIP entries the whitepages is a JSF 2.0 portlet application which uses &lt;a href=&quot;http://www.openldap.org/&quot;&gt;OpenLDAP&lt;/a&gt; as the user repository. Every user entry has several attributes, and some of them are simply displayed (name, telephone,...) and others are treated specially. For example the jpegPhoto attribute is fetched and transformed into an image tag, the mail one is converted into a common email href link and skype/pidgin attribute is interpreted to show the presence and interaction links (start chat, add to my contacts,...).&lt;/p&gt;

&lt;p&gt;For calendar integration a new attribute is used. This attribute is going to have the complete URI for the CalDAV Event collection of the user, in case of Yahoo! the attribute will be &lt;em&gt;https://caldav.calendar.yahoo.com/dav/&amp;lt;yahoo-email&amp;gt;/Calendar/&amp;lt;calendar-name&amp;gt;/&lt;/em&gt;. But like the other special attributes, the calendar one will not be just presented, the URI will be used to access and query for the today user events. These events will be retrieved and presented to the end user. In order to fetch the events of a user calendar it must be shared with whitepages internal user or be totally public (i.e. any other google or Yahoo! user can see our events). In Yahoo! the calendar accessibility is set in &lt;em&gt;Options â†’ Share Calendar â†’ Other Ways to Share â†’ Public Link&lt;/em&gt; and in google in &lt;em&gt;Settings â†’ Calendar settings â†’ Calendars â†’ Click the calendar you want to share â†’ Share this Calendar â†’ Make this calendar public&lt;/em&gt;. In both sites there is an option to only share free/busy information and not make the calendar absolutely public (details are hidden and only availability is shown) but, also in both, this option does not work. Google does not support free-busy-query (CalDAV cannot access free/busy information) and in Yahoo! this option is disabled (with a beautiful &lt;em&gt;coming soon&lt;/em&gt; message). In a custom calendar solution the whitepages could also be configured to use a superuser with special grants to access any other user calendar. But, as I commented, finally I set Yahoo! URI in the LDAP attribute of my entry and therefore my calendar must be public. The portlet tries first to obtain all the events arranged for today using &lt;em&gt;calendar-query&lt;/em&gt; report (this needs all events to be public) and, if this first option does not work, it tries a second &lt;em&gt;free-busy-query&lt;/em&gt; report to only show when the person is occupied (only free/busy access is needed).&lt;/p&gt;

&lt;p&gt;Here it is a new video. My hypothetic boss wants to see the whitepages improvements before the department meeting at the afternoon and he searches for me in the intranet portal. After checking I have one hour free in the morning and I am online in Skype he decides to chat with me and arrange a meeting. I accept the offer and update my Yahoo! calendar. The update is immediately shown in the portlet.&lt;/p&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/CalDAVandtheWhitepagesPortlet/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;p&gt;I hope CalDAV entries were clearer now. This entry has attached the complete caldav project (see above for the link) and shows whitepages as a real example (very simple but a real one). I like the way my little whitepages application is being improved. &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; class=&quot;emoticon&quot; /&gt; &lt;/p&gt;

&lt;p&gt;Happy new year!&lt;/p&gt;</description>
	<pubDate>jue, 30 dic 2010 08:02:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: Conspiraciones</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/130-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/130-Conspiraciones.html</link>
	<description>&lt;p&gt;No soy dado a escribir sobre temas serios para evitar repercusiones, pero hoy voy a romper esta norma no escrita. Primero de todo, dejar claro lo siguiente:&lt;/p&gt;&lt;p&gt;Si creyera que el mundo es perfecto, no creerĂ­a en las conspiraciones ni en las cortinas de humo.&lt;br /&gt;
Si no creyera en las conspiraciones, creerĂ­a que todo el mundo es bueno.&lt;br /&gt;
Si creyera que todo el mundo es bueno, ninguna coincidencia me parecerĂ­a sospechosa.&lt;/p&gt;Y, tras el salto, una serie de extraĂ±as coincidencias. &lt;br /&gt;&lt;a href=&quot;http://blogs.nologin.es/lfabiani/archives/130-Conspiraciones.html#extended&quot;&gt;Continua leyendo &quot;Conspiraciones&quot;&lt;/a&gt;</description>
	<pubDate>jue, 09 dic 2010 22:52:00 +0000</pubDate>
	<author>nospam@example.com (lfabiani)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Canvas Scatter Plot</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/24-Canvas-Scatter-Plot.html</link>
	<description>.canvas-table { 
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}
.canvas-table td { 
  padding-left:4px; 
}


&lt;p&gt;These weeks I have been working in an application that shows some sea physical data (sea level, waves altitude, water temperature, wind strength,...) using &lt;a href=&quot;http://en.wikipedia.org/wiki/Scatter_plot&quot;&gt;scatter plots&lt;/a&gt;. Now the application uses an applet to display the XY graphs which, I must say, is incredibly fast. But, as I commented before in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/12-Signature-Applet.html&quot;&gt;digital signature entries&lt;/a&gt;, applets are now a quite obsoleted solution and sometimes are not very good in terms of compatibility (users need to have a Java Virtual Machine installed, problems with different versions, many linux distributions use by default openjdk/icedtea/gcjwebplugin which crashes sometimes and many other issues which usually generate a lot of complaints). I decided to study a direct browser solution using new HTML5 and javascript features.&lt;/p&gt;

&lt;p&gt;Spending some time searching over the web I saw there are a lot of libraries to directly &lt;a href=&quot;http://javascript.open-libraries.com/utilities/chart/20-best-javascript-charting-and-plotting-libraries/&quot;&gt;draw charts in javascript&lt;/a&gt;. But looking deeper I discovered the majority of them use the new &lt;a href=&quot;http://en.wikipedia.org/wiki/Canvas_element&quot;&gt;HTML5 canvas tag&lt;/a&gt;. The canvas is a new component to render inside its area 2D shapes and images using javascript.&lt;/p&gt;

&lt;p&gt;The first library I used was &lt;a href=&quot;http://www.jscharts.com&quot;&gt;JSCharts&lt;/a&gt; (I did not think too much, it was at the first position in the previous link). It is very powerful but does not fit completely for my problem. The plots of the application were usually a magnitude (meters, degrees, velocity,... in the Y axis) throughout the time (X axis). In the applet version some magnitudes show a very large number of points (around ten thousand). JSCharts cannot handle such a number of points, the resulting graphs are very beautiful but too much complex for this large amount of data. There are some features that explains this fact: points are circles, a specific scatter plot does not exist and a line chart (with invisible line) must be used, time labels must be assigned separately,... All of them make JSCharts not fast enough to draw the 10,000 points in a reasonable time.&lt;/p&gt;

&lt;p&gt;After this first disappointment I decided to just test with a direct canvas implementation (i.e. developing my own javascript that plots a very simple XY graph). But searching information about canvas I discovered a very straight forward graph library which also uses the canvas tag, &lt;a href=&quot;http://www.rgraph.net&quot;&gt;RGraph&lt;/a&gt;. This implementation is much simpler than JSCharts and it has a direct scatter plot graph type. Developing a initial time/magnitude plot the times became very very competitive (for example RGraph scatter plot draws 10,000 points in less than a second in many browsers).&lt;/p&gt;

&lt;p&gt;Finally a study about browser compatibility must be done. And one more time, same thing happened in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/10-Videos-were-About-to-Change.html&quot;&gt;HTML5 video announcement&lt;/a&gt;, all Internet Explorers (included current IE8) do not support the canvas tag. Right now there is a &lt;a href=&quot;http://code.google.com/p/explorercanvas/&quot;&gt;ExCanvas&lt;/a&gt; project that emulates the canvas tag using &lt;a href=&quot;http://en.wikipedia.org/wiki/Vector_Markup_Language&quot;&gt;VML&lt;/a&gt;. The solution (as you can see later) is incredibly slow and there are initiatives for doing the same using &lt;a href=&quot;http://www.azarask.in/blog/post/flash-canvas/&quot;&gt;flash&lt;/a&gt; , &lt;a href=&quot;http://blogs.msdn.com/b/delay/archive/2009/08/24/using-one-platform-to-build-another-html-5-s-canvas-tag-implemented-using-silverlight.aspx&quot;&gt;silverlight&lt;/a&gt; or a &lt;a href=&quot;http://cristianadam.blogspot.com/2010/02/iecanvas-build.html&quot;&gt;ActiveX component&lt;/a&gt;. IE9, which is in beta state, is going to support canvas with many other HTML5 features. For this reason I prepared a little example of a XY plot to test usability with different numbers of points. The sample code draws a sine wave (javascript generated) in a period of time and let us change the number of points, showing finally the drawing time in a box (the part for generating the wave is not taken into account). At the end of the entry I present the little example inside an iframe (I know it is not very beautiful but this could be easily improved).&lt;/p&gt;

&lt;p&gt;When I played with the resulting graph using different browsers numbers were the following (I took them not very precisely):&lt;/p&gt;

&lt;table class=&quot;canvas-table&quot;&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;100 points&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;1,000 points&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;10,000 points&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;iceweasel 3.5.15 (linux)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;26ms&lt;/td&gt;&lt;td&gt;80ms&lt;/td&gt;&lt;td&gt;712ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;chromium 6.0.472.63 (linux)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;10ms&lt;/td&gt;&lt;td&gt;18ms&lt;/td&gt;&lt;td&gt;98ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;firefox 3.6.12 (Windows)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;32ms&lt;/td&gt;&lt;td&gt;130ms&lt;/td&gt;&lt;td&gt;1,018ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;firefox 4.0 Beta 7 (Windows)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;32ms&lt;/td&gt;&lt;td&gt;120ms&lt;/td&gt;&lt;td&gt;970ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;chrome 7.0.517.44 (Windows)&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;11ms&lt;/td&gt;&lt;td&gt;32ms&lt;/td&gt;&lt;td&gt;240ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IE8+ExCanvas (Windows)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;800ms&lt;/td&gt;&lt;td&gt;3,850ms&lt;/td&gt;&lt;td&gt;70,000ms+&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IE9 Preview 7 (Windows)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;17ms&lt;/td&gt;&lt;td&gt;65ms&lt;/td&gt;&lt;td&gt;500ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Opera 10.63 (Windows)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;25ms&lt;/td&gt;&lt;td&gt;49ms&lt;/td&gt;&lt;td&gt;305ms&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;My conclusion is a HTML5 plot solution results usable in any browser that supports canvas, but IE8 kills us again. Any canvas graph is fateful for many windows users. I decided some time ago to trigger all HTML5 new features when debian testing will distribute iceweasel 3.6 (squeeze must be released before) and chromium 6.0 (it is already) and IE9 will be released. As you can see in the numbers, times are very good in the last versions of the browsers and even better in the future ones. You already know but it is absolutely necessary to keep our browsers in their last versions. Now there are a lot of options (free, open source, distributed with the OS,...), so there is no excuse. Make web developers life easier...&lt;/p&gt;

&lt;p&gt;Please, upgrade your browser!!!&lt;/p&gt;</description>
	<pubDate>lun, 22 nov 2010 23:37:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Pon un sol en tu vida: DRM y Software Privativo van de la mano</title>
	<guid>http://blogs.nologin.es/slopez/archives/25-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/25-DRM-y-Software-Privativo-van-de-la-mano.html</link>
	<description>Navegando por &lt;a href=&quot;http://reddit.com&quot; title=&quot;reddit&quot;&gt;reddit&lt;/a&gt;, me he encontrado con &lt;a href=&quot;http://www.reddit.com/r/pics/comments/e37ba/this_is_why_we_pirate/&quot;&gt;esta entrada&lt;/a&gt; en la que un usuario se queja de que no puede reproducir un Blue-Ray legĂ­timamente adquirido, ya que estĂˇ utilizando como salida de vĂ­deo una TV conectada al puerto HDMI de su portĂˇtil (un Macbook Pro).&lt;br /&gt;
&lt;br /&gt;
En dicha entrada se comenta cĂłmo los fabricantes se perjudican a sĂ­ mismos con este tipo de prĂˇcticas. Ciertamente es un aspecto a destacar, pero tambiĂ©n es importante tener en cuenta que dichas prĂˇcticas no serĂ­an posibles sin que existiese cierto Software Privativo que haga efectivas las limitaciones artificiales impuestas por los fabricantes. Y donde hoy es impedir que se reproduzca un contenido si se visualiza en una TV sin &lt;a href=&quot;http://es.wikipedia.org/wiki/High-Bandwidth_Digital_Content_Protection&quot;&gt;HDCP&lt;/a&gt;, maĂ±ana podrĂ­a ser cualquier otra prohibiciĂłn igualmente ridĂ­cula y arbitraria.&lt;br /&gt;
&lt;br /&gt;
Y es que este es uno de los principales motivos por los que Richard M. Stallman iniciĂł el proyecto &lt;a href=&quot;http://gnu.org&quot;&gt;GNU&lt;/a&gt; hace 25 aĂ±os: impedir que los fabricantes tuvieran la capacidad de decidir sobre lo que el usuario puede o no hacer con su computadora. El Software Libre, como su propio nombre indica (al menos en su denominaciĂłn castellana, mĂˇs precisa que la anglosajona), trata sobre la libertad, y no sobre la gratuitidad, matizaciĂłn que con frecuencia se suele pasar por alto.&lt;br /&gt;
&lt;br /&gt;
Si en atenciĂłn a nuestra comodidad entramos en el &lt;a href=&quot;http://en.wikipedia.org/wiki/Walled_garden_(technology)&quot;&gt;jardĂ­n vallado&lt;/a&gt; que nos presentan y damos por buenas este tipo de prĂˇcticas (y entre ellas podemos incluir tambiĂ©n modelos de distribuciĂłn de software como el AppStore), le estamos dando vĂ­a libre a los fabricantes para que tomen el control de nuestros dipositivos y decidan por nosotros lo que podemos hacer con ellos. Y los peligros que esto entraĂ±a en una sociedad donde las TI estĂˇn presentes a todos los niveles (y cada dĂ­as mĂˇs), son impredecibles.&lt;br /&gt;
&lt;br /&gt;</description>
	<pubDate>mar, 09 nov 2010 21:24:30 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Nolife at Nologin: El final de la familia Zapatero</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/129-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/129-El-final-de-la-familia-Zapatero.html</link>
	<description>Hoy llego al trabajo indignado. El congreso ha aprobado la nueva &lt;a href=&quot;http://www.abc.es/20101104/espana/claves-reforma-registro-civil-201011040648.html&quot;&gt;Ley del Registro Civil&lt;/a&gt;.Â  Entre otras cosas, establece que cuando no haya acuerdo entre los padres, los apellidos se pondrĂˇn en orden alfabĂ©tico. Hasta ahora, primaba el apellido del padre por motivos tradicionales. Vamos, el final de la familia Zapatero.&lt;p&gt;Es cuestiĂłn matemĂˇtica: Zapatero es uno de los Ăşltimos apellidos alfabĂ©ticamente, luego cualquier Zapatero que se case (hombre o mujer) tiene mĂˇs de un 90% de posibilidades de que su pareja tenga un apellido prevaleciente. Luego quedarĂˇ en segundo lugar, no siendo heredable (salvo, lo dicho, acuerdo entre los padres). La siguiente generaciĂłn se repetirĂ­a el proceso. En 2 o 3 generaciones no quedarĂˇn Zapateros.&lt;/p&gt;&lt;p&gt;Hay que tener en cuenta que el acuerdo entre los padres para modificar la norma general, pese a ser una posibilidad, no es lo mĂˇs extendido, ni con esta ni con ninguna norma, y que de facto la tradiciĂłn se fundamenta en normas que se han convertido en hĂˇbito. AsĂ­ que esta ley nos pinta un mundo con apellidos que empiecen sĂłlo por las primeras letras del abecedario. Como indican en &lt;a href=&quot;http://www.elpais.com/articulo/sociedad/reforma/legal/termina/prevalencia/apellido/padre/elpepisoc/20101104elpepisoc_4/Tes&quot;&gt;El PaĂ­s&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;Patricia LĂłpez PelĂˇez, profesora titular de Derecho Civil de la Uned, 
explica que ese sistema alfabĂ©tico puede provocar que, en unos aĂ±os, 
terminen prevaleciendo los apellidos de la primera parte del alfabeto. 
&amp;quot;Pero es cierto que se ha buscado un criterio objetivo para no 
discriminar ni favorecer a ninguno de los miembros de la pareja&amp;quot;, 
explica.&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Se me ocurren muchos otros titulares maravillosos:&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;b&gt;Zapatero legisla para que Aznar perdure pero Ă©l se extinga.&lt;/b&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;b&gt;Los Villaarriba y los Villabajo se unen para manifestarse contra el fin de sus linajes.&lt;/b&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;b&gt;En el futuro, en EspaĂ±a todos nos apellidaremos Abel.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Personalmente, me parece una barbaridad lingĂĽistica. En aras de la igualdad, se comete una estupidez cuya consecuencia serĂˇ que en unos aĂ±os nuestro sistema de apellidos perderĂˇ en riqueza. Los Zapata, Zaragoza, Zurueta, ZurbarĂˇn, ZafĂłn, ZumĂˇrraga y demĂˇs serĂˇn historia y quedarĂˇn relegados a las pĂˇginas, expulsados de la realidad.&lt;/p&gt;&lt;p&gt;La clave estĂˇ en que se ha perdido el componente de aleatoriedad en la elecciĂłn del nombre de los apellidos. Hasta ahora el orden en EspaĂ±a dependĂ­a de una variable aleatoria como era el sexo de los progenitores (quizĂˇ en el futuro deje de ser aleatorio, pero ahora no lo es). Los legisladores dicen en el mismo artĂ­culo del PaĂ­s:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;(...) se ha estudiado la legislaciĂłn de otros paĂ­ses en los que se puede 
elegir el orden de los apellidos. En Alemania, por ejemplo, se lanza una
 moneda al aire para tomar la decisiĂłn, en caso de que los padres no se 
pongan de acuerdo.&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Se ha estudiado pero NO se ha comprendido. En Alemania garantizan que todos los apellidos tengan posibilidades de continuar existiendo. AquĂ­ no. Prefiero mil veces una discriminaciĂłn positiva que cambie la tortilla radicalmente, poniendo delante el nombre de la madre (despuĂ©s de todo, las madres legan mĂˇs componente genĂ©tico que los padres gracias a las mitocondrias) que esta estupidez que va a terminar con parte de nuestro legado cultural.&lt;/p&gt;&lt;hr width=&quot;100%&quot; size=&quot;2&quot; /&gt;PD: Busco un logo para una campaĂ±a: &amp;quot;Los estupidos legislan: Zapatero mata su apellido&amp;quot;. ÂżAlguna sugerencia? Vamos a darle visibilidad a esta estupidez.</description>
	<pubDate>jue, 04 nov 2010 07:56:00 +0000</pubDate>
	<author>nospam@example.com (lfabiani)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Using Cassandra with EJB Technology</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/23-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/23-Using-Cassandra-with-EJB-Technology.html</link>
	<description>&lt;p&gt;The past week Eric, a french reader of the blog, contacted me because of my old &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/9-Getting-Started-With-Cassandra.html&quot;&gt;Cassandra entry&lt;/a&gt;. He was trying to get some help in how to implement an &lt;a href=&quot;http://www.oracle.com/technetwork/java/index-jsp-140203.html&quot;&gt;Enterprise Java Bean&lt;/a&gt; for the NoSQL database. As I explained in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/17-Integrating-Terminal-Services-into-a-Portal.html&quot;&gt;Terminal Services posts&lt;/a&gt; the portlet used Thrift and Cassandra to store the application tree which was shown in the series. I am going to present the same solution but replacing the portlet with an EJB 3.1 / JSF 2.0 web application. The idea of this post is explaining the whole process.&lt;/p&gt;

&lt;p&gt;First of all the Cassandra data model was designed. If you remember, the Terminal Services portlet is a tree very similar to a file system. Any item can be a folder or an application. Folders can contain any number of other folders or applications, and applications are leafs which contain the RDP definition file (the file which is downloaded to launch the Terminal Services client program). Following the ideas presented in the old Cassandra post only two simple columns were needed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Applications&lt;/strong&gt;: The applications column family will contain all the applications and folders. The key will be the complete and uppercased path of the application (for example &lt;em&gt;/APPLICATIONS/SKYPE&lt;/em&gt;) and the values will represent different data. More precisely the columns will be the following:&lt;/li&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;name&lt;/strong&gt;: application name to show (&lt;em&gt;Skype&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;description&lt;/strong&gt;: application description.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;icon&lt;/strong&gt;: 16x16 PNG icon.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;type&lt;/strong&gt;: &lt;em&gt;app&lt;/em&gt; or &lt;em&gt;folder&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;rdp&lt;/strong&gt;: rdp file to startup this application (only for apps).&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;

&lt;pre&gt;
Applications: { // ColumnFamily
  /INTERNET: { // key
    name: Internet
    description: Internet applications
    icon: 0x19EA14...
    type: folder
  },
  /INTERNET/SKYPE: { // key
    name: Skype
    description: VoIP client application (www.skype.com)
    icon: 0x56FA12...
    type: app
    rdp: 0xA4326A...
  }
  ...
}
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ApplicationStructure&lt;/strong&gt;: This other column family just cover the folder structure which is missing in the other one. This column is quite simple, the key continues to be the path of the folder in uppercase and the values are its children (path and name of every child). This column family gives an easy way to access all the children of a specified folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;
ApplicationStructure: { // ColumnFamily
  /APPLICATIONS: { // key
    /APPLICATIONS/INTERNET: Internet
    /APPLICATIONS/PAINT: Paint
  },
  /APPLICATIONS/INTERNET: { // key
    /APPLICATIONS/INTERNET/PIDGIN: Pidgin
    /APPLICATIONS/INTERNET/SKYPE: Skype
  }
  ...
}
&lt;/pre&gt;

&lt;p&gt;In order to create the EJB which manages applications (and folders) the idea is just creating a bean which handles basic &lt;a href=&quot;http://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt; operations for applications. This class is called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/CassandraManagerEJB.java&quot;&gt;CassandraManagerEJB&lt;/a&gt;. In the previous posts this class was a &lt;a href=&quot;http://en.wikipedia.org/wiki/Plain_Old_Java_Object&quot;&gt;POJO&lt;/a&gt; (liferay was deployed inside a tomcat and EJB technology was unavailable) that has been now converted into a Singleton Enterprise Bean. Another class called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/Application.java&quot;&gt;Application&lt;/a&gt; represents any application or folder with typical getters and setters. Obviously the CassandraManagerEJB receives objects of this class and transforms them into thrift mutations and columns for writing and vice-versa for reading. There is a special folder keyed by &quot;/&quot; for the root path. The EJB uses &lt;a href=&quot;http://commons.apache.org/pool/&quot;&gt;commons-pool&lt;/a&gt; to treat Thrift connections inside a pool. The three main methods in the EJB are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;readApplication&lt;/strong&gt;: Reads any application from the Cassandra repository. The application or folder path is passed to the method. The attributes to read can be also specified in order to not read all of them. But it also receives a parameter to specify how the children is retrieved:&lt;/li&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;NONE&lt;/strong&gt;: No children are returned, the column family Applications is the only one read.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ONLY_NAMES&lt;/strong&gt;: The application is also read from the ApplicationStructure column family and only its data is filled in the children list (path and name).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;FULL&lt;/strong&gt;: After reading the children from ApplicationStructure all of them are also got from the Applications column family. So now all the specified attributes are filled in the children list.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RECURSIVE&lt;/strong&gt;: The method is called recursively to retrieve all hierarchy with all attributes specified, from the path passed to the bottom.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;createApplication&lt;/strong&gt;: Creates or updates an application or folder. This method do not let create folders with children (for folders is just like &lt;em&gt;mkdir&lt;/em&gt; command), application names cannot contain '/' character (only root can do that) and the specified parent must exists previously in Cassandra repository. If the application object passed does not follow these rules an Exception is thrown.&lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;deleteApplication&lt;/strong&gt;: Deletes an application or folder. If the application does not exist or it is a folder with children the method throws an exception (again it can be considered like a &lt;em&gt;rmdir&lt;/em&gt; command in case of a folder).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tested the web module deploying it inside a J2EE6 compatible glassfish v3 application server. So the EJB is annotated to be a Singleton and an application scoped named object, this way the EJB can be injected using &lt;a href=&quot;http://www.theserverside.com/news/1373391/Dependency-Injection-in-Java-EE-6-Part-1&quot;&gt;Context Dependency Injection (CDI)&lt;/a&gt;. Remember the &lt;a href=&quot;http://www.andygibson.net/blog/tutorial/getting-started-with-jsf-2-0-and-cdi-in-jee-6-part-1/&quot;&gt;beans.xml file must be created&lt;/a&gt; to make &lt;a href=&quot;http://seamframework.org/Weld&quot;&gt;WELD&lt;/a&gt; (CDI implementation) start to work. I recommend to read &lt;a href=&quot;http://www.germanescobar.net/2010/04/4-areas-of-possible-confusion-in-jee6.html&quot;&gt;this post&lt;/a&gt; to know more about the differences between CDI and EJB injecting techniques.&lt;/p&gt;

&lt;p&gt;The JSF part will use the created enterprise bean to display all the tree. There is only one managed bean which is called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/ApplicationTreeBean.java&quot;&gt;ApplicationTreeBean&lt;/a&gt; but it is accompanied by some helper classes. This JSF bean uses injection to get the Singleton EJB and is also annotated as named to be injected into &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/index.txt&quot;&gt;index.xhtml&lt;/a&gt; facelet like a session scoped bean. The JSF part can be more or less complicated but it just presents the application tree we saw in the Terminal Server entries (see image below).&lt;/p&gt;

&lt;div&gt;
  &lt;img class=&quot;serendipity_image_center&quot; src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/tswebclient.png&quot; alt=&quot;tswebclient sample image&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;As all of you can see this way of integrating Cassandra into EJB 3.1 technology is very very straight forward but, not being an expert in Cassandra, I think it is the most suitable nowadays. Remember all Cassandra stuff presented here uses the inflexible Thrift client (I chose it cos I wanted to learn Cassandra internals), there are some more &lt;a href=&quot;http://wiki.apache.org/cassandra/ClientOptions&quot;&gt;java clients out there&lt;/a&gt; and surely they are friendlier. Here it is the whole &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/UsingCassandrawithEJBTechnology/tswebclient-ejb.zip&quot;&gt;Netbeans project&lt;/a&gt; just in case (libraries have been deleted to save space).&lt;/p&gt;

&lt;p&gt;When I talked all this stuff to Eric, he advised me there is a project called &lt;a href=&quot;http://code.google.com/p/kundera/&quot;&gt;Kundera&lt;/a&gt; (I have just realized it is listed as Cassandra client in the previous link) which is trying to implement a &lt;a href=&quot;http://en.wikipedia.org/wiki/Java_Persistence_API&quot;&gt;JPA&lt;/a&gt; provider for Cassandra (see &lt;a href=&quot;http://anismiles.wordpress.com/2010/07/14/kundera-now-jpa-1-0-compatible/&quot;&gt;the following post&lt;/a&gt;). At first moment I think it makes no sense, the Java Persistence API is tightly coupled with SQL (it can be said it was designed to cover SQL databases) and, therefore, not very suitable for a NoSQL repository like Cassandra. The weekend I spent some time trying to figure out how, for instance, the queries are performed. Kundera mixes Cassandra repository with &lt;a href=&quot;http://lucene.apache.org/java/docs/index.html&quot;&gt;Lucene indexing engine&lt;/a&gt; and, this way, some little queries can be performed against the indexes. Looking into relations (many to many, one to many, one to one,...) I saw some of them are still not implemented, but this point is less problematic cos developers could (more or less) follow the same ideas I commented in my previous entry about Cassandra. So, despite of my initial skepticism, the project has at least some sense. I still believe the idea is a bit farfetched but I have to admit they are implementing the same solution I would have used in a supposed Cassandra project. If you remember I already talked about mixing Cassandra and some indexing engine like &lt;a href=&quot;http://lucene.apache.org/solr/&quot;&gt;solr&lt;/a&gt; (Lucene based) to get a robust result.&lt;/p&gt;

&lt;p&gt;Good job guys! Continue surprising me!&lt;/p&gt;</description>
	<pubDate>lun, 25 oct 2010 18:38:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: PFC</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/22-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/22-PFC.html</link>
	<description>The other day I was helping my mother to tidy my parent's junk room when I found all the documentation of my PFC (a kind of dissertation needed in Spain to get your bachelor degree). The whole stuff was a non-working CD, a VHS tape and the book itself.
&lt;br /&gt;&lt;br /&gt;

At that time I was quite interested in computer graphics and I tried to do my project in the graphics department of my University. This department was (and still is) a group called &lt;a href=&quot;http://giga.cps.unizar.es&quot;&gt;GIGA&lt;/a&gt;, Spanish acronym for Advanced Computing Graphics Group. After some initial doubts I finally decided to continue an unfinished project of the group. The GIGA had collaborated with &lt;a href=&quot;http://www.chebro.es/&quot;&gt;CHE&lt;/a&gt; (a governmental company that deals with water issues in my home region, its name comes from the river that crosses Zaragoza, the &lt;a href=&quot;http://en.wikipedia.org/wiki/Ebro&quot;&gt;Ebro river&lt;/a&gt;) and the group had achieved from them some valuable information: 

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;An altitude map file&lt;/strong&gt;. The file was a 40 megabyte file with the altitudes of the Ebro basin terrain measured every 100 meters (the file was a altitude mesh of squares which sides are lengthened by 100m).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Satellite images of the same basin&lt;/strong&gt; (6 CDs). The quality of the images was more or less a point of color every 5 meters.&lt;/li&gt;
&lt;/ul&gt;

I know that now, in the google era, this information is a real shit but 15 years ago all of this was a data of enormous worth. The GIGA group had developed a quick application to make a video for a CHE presentation in which you virtually cruised throughout some places of the basin. The idea of my tutor (&lt;a href=&quot;http://webdiis.unizar.es/~seron/&quot;&gt;Francisco JosĂ© SerĂłn&lt;/a&gt;) were mainly three points:

&lt;ul&gt;
  &lt;li&gt;Developing, using some interpolation methods, a software that let them to create a more dense mesh.&lt;/li&gt;
  &lt;li&gt;Improving the flying application because it had been done just for the presentation. I suppose my other tutor (&lt;a href=&quot;http://webdiis.unizar.es/~magallon/diis/hom/&quot;&gt;Juan Antonio MagallĂłn&lt;/a&gt;) spent long nights to finish the job.&lt;/li&gt;
  &lt;li&gt;Making some study for finding water (rivers, lakes,..) in the satellite images. Finally this point was not done (only some comments and not a thorough job).&lt;/li&gt;
&lt;/ul&gt;

Of course only the second point was truly interesting to me and the reason why I wanted to work with GIGA but it was an all or nothing. The flying application used GTK for window management (menus, buttons,...) and OpenGL for drawing. The mesh was painted and the satellite images were used as textures. I switched from plain C to a C++ application and I tried to make a more structured code. During developing another collaboration came up, GIGA was in touch with a woman who was making a thesis about fire spreading. Of course the idea of a video or images about a fire spreading over some place of the basin quickly emerged. 
&lt;br /&gt;&lt;br /&gt;

And that is the reason for this entry. I have already lost my project, because all of it (code, altitude mesh, some texture images -the small ones-,...) was in the broken CD (I am trying to bring it back to life but I think it is a waste of time) but I want to preserve the video, some photos I still have and a poster I did. As I have already said in some occasions this blog is the perfect place to put things I do not want to lose.
&lt;br /&gt;&lt;br /&gt;

Here I present some of the photos I still has, only a few cos the majority of them are lost inside the CD. The poster I configured about my project is also here.

&lt;div class=&quot;highslide-gallery&quot;&gt; 

&lt;a id=&quot;pfc_thumb1&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/mal_wire.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/mal_wire.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Wire image with a long step in the mesh
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb2&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/mal_junto.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/mal_junto.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Wire and texturized image with a long step in the mesh
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb3&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/mal_tex.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_tex.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Texturized image with a long step wire mesh
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb4&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_wire.jpg&quot; class=&quot;highslide&quot;&gt; 
	&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_wire.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt; 
&lt;div class=&quot;highslide-heading&quot;&gt; 
	Wire image with a more dense mesh integrated
&lt;/div&gt; 

&lt;a id=&quot;pfc_thumb5&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_junto.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_junto.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Wire and texturized image
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb6&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_tex.jpg&quot; class=&quot;highslide&quot;&gt;
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/bien_tex.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt;
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Texturized image
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb7&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/poster.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/poster.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Poster of my PFC
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb8&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego1.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego1.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Fire spreading photo
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb9&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego2.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego2.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Fire spreading photo 2
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb10&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego3.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego3.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Fire spreading texture for tile 23/77
&lt;/div&gt;

&lt;a id=&quot;pfc_thumb11&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego4.jpg&quot; class=&quot;highslide&quot;&gt; 
        &lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/fuego4.preview.jpg&quot; alt=&quot;Highslide JS&quot; title=&quot;Click to enlarge&quot; /&gt; 
&lt;/a&gt;
&lt;div class=&quot;highslide-heading&quot;&gt;
        Fire spreading texture for tile 23/78
&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;
Finally the video, which was done later in a second collaboration with the fire spreading thesis. My application generated the main scenes but the script and all the making of the film was done by &lt;a href=&quot;http://giga.cps.unizar.es/~diegog/&quot;&gt;Diego Gutierrez&lt;/a&gt;, another guy of the GIGA group. Thanks to Edu for digitizing the VHS tape.
&lt;br /&gt;&lt;br /&gt;



&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/PFC/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;

&lt;br /&gt;
It is amazing how things change in less than 15 years. Enjoy!
&lt;br /&gt;&lt;br /&gt;

&lt;span&gt;&lt;strong&gt;PS:&lt;/strong&gt; I sent an email to one of my tutors cos I do not know for sure if I can publish this information (video and images) or not. I have received no answer so I decided to continue. Please use comments or contact me if I am really not allowed to share these data.&lt;/span&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
	<pubDate>dom, 26 sep 2010 21:22:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: No-Lata</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/128-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/128-No-Lata.html</link>
	<description>&lt;p&gt;En este mes de septiembre se cumple el dĂ©cimo aniversario de Nologin.&lt;/p&gt;&lt;p&gt;SegĂşn la Wikipedia, los 10 aĂ±os de casados son las &amp;quot;Bodas de Lata&amp;quot;.&lt;/p&gt;&lt;p align=&quot;baseline&quot;&gt;Aplicando la lĂłgica ilĂłgica de Nolife:&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br /&gt;&lt;img height=&quot;200&quot; src=&quot;http://2.bp.blogspot.com/_gaiJUGaGOgQ/TA0MShpMCBI/AAAAAAAAAKY/LIrrUAoQVXk/s1600/10aniversario%282%29.jpg&quot; /&gt;&lt;br /&gt;&lt;font size=&quot;6&quot;&gt;&lt;b&gt;ÂˇÂˇFeliz Aniversario de Lata!!&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</description>
	<pubDate>lun, 20 sep 2010 14:34:57 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Nolife at Nologin: El ataque de los caracoles asesinos</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/127-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/127-El-ataque-de-los-caracoles-asesinos.html</link>
	<description>&lt;p&gt;Esta samana pasada perdimos varios compaĂ±eros. En la oficina acabamos de atravesar un incidente realmente traumĂˇtico al que apenas sobrevivĂ­. &lt;/p&gt;&lt;p align=&quot;baseline&quot;&gt;Todo comenzĂł de la manera mĂˇs inocente. Uno de los jefes tuvo la idea de entrenar un ejĂ©rcito de caracoles que nos ayudaran en nuestro propĂłsito de controlar el mundo (que viene a ser el propĂłsito de cualquier empresa mediana o grande con aspiraciones). Las largas jornadas de instrucciĂłn iban bien, hasta que los caracoles se rebelaron.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;300&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/6/69/Grapevinesnail_01.jpg&quot; /&gt;&lt;br /&gt;&lt;font size=&quot;1&quot;&gt;Se me ponen los pelos como sus cuernos sĂłlo de verlo...&lt;/font&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;No dudaron en atacarnos, a pesar de todo lo que les habĂ­amos dado. Nos cortaron la retirada, haciĂ©ndose con la puerta. Se movĂ­an sigilosamente, con paciencia, rodeĂˇndonos. Un cĂ­rculo perfecto, y cerrĂˇndose. AĂşn recuerdo cĂłmo se lanzaron lentamente sobre algunos de mis compaĂ±eros, sus cuerpos recubiertos de esas asquerosas babas. Recuerdo sus gritos.&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;DespuĂ©s se retiraron. Nos dejaron vivir a algunos. Ahora estĂˇn sueltos. ÂżQuĂ© pretenden? Oh, seĂ±or, ÂżquĂ© fuerza hemos liberado en nuestra inconsciencia? ÂżCuĂˇl serĂˇ el precio que tendremos que pagar?&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;Cuando veĂˇis a varios caracoles, arrastrĂˇndose en formaciĂłn hacia vosotros, &lt;b&gt;ÂˇHUID!&lt;/b&gt;&lt;/p&gt;&lt;p align=&quot;left&quot;&gt;NOTA: Como hemos aprendido la lecciĂłn, estamos enseĂ±ando tĂ©cnicas ninja a &lt;a href=&quot;http://es.wikipedia.org/wiki/Rostrhamus_sociabilis&quot;&gt;gavilanes caracoleros&lt;/a&gt; para que persigan y acaben con los caracoles. Aprenden deprisa.&lt;br /&gt;&lt;font size=&quot;1&quot;&gt;&lt;/font&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>mar, 14 sep 2010 15:00:00 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: DNIe and the Signature Applet</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/21-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/21-DNIe-and-the-Signature-Applet.html</link>
	<description>Previously I talked about how to deal with web security and certificates in a two part series of entries. In &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/12-Signature-Applet.html&quot;&gt;the first post&lt;/a&gt; I generally talked about security concerns and I presented a little solution based on Java applets. &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/13-Signature-Applet-Using-Browser-Store.html&quot;&gt;The second one&lt;/a&gt; extended the PoC using the same certificates that some browsers do (IE and firefox). I already said that a real security device (cryptocard, cryptousb,...) was the missing point and I told to all of you the time will come with my Spanish &lt;a href=&quot;http://en.wikipedia.org/wiki/Electronic_identity_card&quot;&gt;electronic identity (eID) card&lt;/a&gt; renewal. The time is here!&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.dnielectronico.es&quot;&gt;DNIe&lt;/a&gt; (this is how the new Spanish eID card is known) has two valid certificates (two years of expiration time), one for digital signature and the other for authentication, two fingerprints (right and left index finger), the written signature and a photo. First of all I want to say the integration of the DNIe in linux is quite a hell. Linux implementation is based on the &lt;a href=&quot;http://www.opensc-project.org&quot;&gt;OpenSC project&lt;/a&gt;. This project is an old friend in the linux world and it implements a PKCS#15 backend (PKCS#15 is the RSA standard that defines how the data is organized in a card) and gives a PKCS#11 library (RSA standard API to interact with crypto-devices) to be used inside firefox and many other applications. DNIe distributes an extra library not included in common opensc bits (the library is called &lt;em&gt;libopensc-dnie.so&lt;/em&gt; and it is inside &lt;em&gt;opensc-dnie&lt;/em&gt; package) which is configured in the opensc configuration file as an external shared library. At first sight I thought these bits are only distributed as a closed blob but then I realized that there is also a source zip file. So I am going to explain both methods of installation (following exactly the same steps I performed).&lt;br /&gt;
&lt;br /&gt;
To make the DNIe blob work in my debian testing box I needed to download the &lt;em&gt;&lt;a href=&quot;http://www.dnielectronico.es/descargas/PKCS11_para_Sistemas_Unix/opensc_1.4.6_arq_deb_len32.html&quot;&gt;Debian_Lenny_opensc-dnie_1.4.6-2_i386.deb.tar&lt;/a&gt;&lt;/em&gt; from DNIe official page. The problem here is the blob only works with the distributed 0.11.7 version of opensc (actual version is 0.11.13) and you must exactly install these packages:&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
# dpkg -i libltdl3_1.5.26-4+lenny1_i386.deb libopensc2_0.11.7-7_i386.deb opensc_0.11.7-7_i386.deb  opensc-dnie_1.4.6-2_i386.deb&lt;/blockquote&gt;&lt;br /&gt;
The first one, &lt;a href=&quot;http://packages.debian.org/lenny/libltdl3&quot;&gt;libltdl3&lt;/a&gt;, is a package of Lenny (Stable) which have disappeared in testing but it is compulsory for opensc/DNIe and not included in the distribution tar file. Of course you also need to hold new versions of debian opensc packages (if not any upgrade will break your DNIe again).&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
# echo &quot;opensc hold&quot; | dpkg --set-selections&lt;br /&gt;
# echo &quot;libopensc2 hold&quot; | dpkg --set-selections&lt;/blockquote&gt;&lt;br /&gt;
This integration is so crappy I had decided to not use DNIe in debian (I would have preferred to use a Windows virtual box or similar and not to dirty my system this way). But then, as I commented, I found a &lt;a href=&quot;http://www.dnielectronico.es/descargas/codigo_fuente.html&quot;&gt;source distribution&lt;/a&gt; in the same download page. The source is not completed (it seems some certificate and key variables has been deleted from the source and one file does not compile) but this &lt;a href=&quot;http://www.kriptopolis.org/disponibles-fuentes-pkcs11&quot;&gt;thread in kriptopolis&lt;/a&gt; (a spanish security web site) explains how to make it work. The thread is quite long but it was worth the time. After some &lt;em&gt;nm&lt;/em&gt; and &lt;em&gt;objdump&lt;/em&gt; commands I finally compiled the sources. Now I have my &lt;em&gt;libopensc-dnie.so&lt;/em&gt; which links perfectly against OpenSC 0.11.13, debian testing version, and it works without a problem using the same &lt;em&gt;opensc.conf&lt;/em&gt; configuration file that blob DNIe packages provide. The new library was tested inside firefox, thunderbird and my Java Signature Applet. I also want to comment that DNIe has a &lt;a href=&quot;https://av-dnie.cert.fnmt.es/compruebacert/compruebacert&quot;&gt;test page&lt;/a&gt; which has been incredibly useful to check out all this stuff.&lt;br /&gt;
&lt;br /&gt;
So finally it can be said that DNIe binary packages only work for the distributed 0.11.7 version but compiling the sources you can make the custom DNIe library work linked against current OpenSC version. This is not a perfect solution (any new change in OpenSC can broke again DNIe) but I have to admit that publishing the sources is an awesome step to open source integration. The source zip from DNIe claims to be GPLv3 licensed and I only hope OpenSC can integrate this code in a future release (avoiding all this pain). OpenSC guys already have a &lt;a href=&quot;http://www.opensc-project.org/opensc/ticket/205&quot;&gt;open ticket about this issue&lt;/a&gt;. I submitted some information on it a few days ago and waiting is the only thing we can do right now.&lt;br /&gt;
&lt;br /&gt;
After DNIe is fully functional in my box we can extend our Signature Java Applet PoC in order to integrate DNIe as a valid device. If you have read the two previous entries you already know that the only thing to do is finding a proper JCE provider for Spanish eID card. It is quite clear that DNIe/OpenSC gives a PKCS#11 library and, obviously, the PKCS#11 provider is the correct bet in linux. If you remember I developed a multi-purpose &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/SignatureApplet-UsingBrowserStore/PKCS11Signer.java&quot;&gt;PKCS11Signer.java&lt;/a&gt; (used in the second entry for NSS) which is perfect for OpenSC. Now the applet is instantiated this way.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;
&amp;lt;applet id=&quot;signApplet&quot; codebase=&quot;resources/applet/&quot; code=&quot;sample.applet.SignApplet&quot; archive=&quot;SSignApplet.jar,Sbcmail-jdk16-145.jar,Sbcprov-jdk16-145.jar,Smail-1.4.3.jar&quot; width=&quot;350&quot; height=&quot;200&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;param name=&quot;clazz&quot; value=&quot;sample.applet.PKCS11Signer&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;param name=&quot;param0&quot; value=&quot;sample.applet.pkcs11Name###DNIe&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;param name=&quot;param1&quot; value=&quot;sample.applet.keyAcessNeeded###false&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;param name=&quot;param2&quot; value=&quot;library###/usr/lib/opensc-pkcs11.so&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;param name=&quot;param3&quot; value=&quot;slot###0&quot;/&gt;&lt;br /&gt;
&amp;lt;/applet&gt;&lt;/blockquote&gt;&lt;br /&gt;
With DNIe (and any common PKCS#11 library but Mozilla NSS) only the shared library (&lt;em&gt;/usr/lib/opensc-pkcs11.so&lt;/em&gt; in debian distribution) and the slot (0 in my configuration) are specified. As in the previous examples DNIe only has a master pin so password prompt for keys is disabled (&lt;em&gt;sample.applet.keyAcessNeeded&lt;/em&gt; is set to false). Any further information about the JCE PKCS#11 provider can be achieved in the &lt;a href=&quot;http://download.oracle.com/javase/1.5.0/docs/guide/security/p11guide.html&quot;&gt;J2SE documentation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Finally I present a video where the mail signer application is used again. Using Chromium the email sheet is filled and the applet is started. There the two certificates inside DNIe are displayed and, using the signature one, the email is signed and sent. Now icedove/thunderbird application is started (the startup is quite slow cos the ID card is plugged and OpenSC initialization is not very fast). In this case when the email arrives to me it shows a question mark, that is a consequence of Spanish id certificates does not have any email specified inside them. At the end the certificates of the DNIe are shown again but using thunderbird itself, so DNIe is successfully working on both, the applet and the email application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/DNIeandtheSignatureApplet/out.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
As a conclusion it can be said that right now the status of DNIe in the open source world is a bit confusing. The distribution of the source code under GPLv3 license can clarify the situation and it would be wonderful if the code will be integrated someway inside OpenSC project. Talking about the applet signature PoC, DNIe is the perfect example of how a new crypto-device is smoothly integrated just using JCE and PKCS#11 standard.&lt;br /&gt;
&lt;br /&gt;
It is really great when you make the things work! Never give up!</description>
	<pubDate>dom, 05 sep 2010 20:51:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: Entrada no-patrocinada: Platos VacĂ­os Sin VergĂĽenza</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/126-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/126-Entrada-no-patrocinada-Platos-Vacios-Sin-Vergueenza.html</link>
	<description>&lt;p align=&quot;baseline&quot;&gt;Suele ser bastante comĂşn que algunos blogs tengan entradas patrocinadas, en las que hacen publicidad descarada de productos a cambio de algĂşn tipo de beneficio. En Nolife llegamos mĂˇs allĂˇ, y tendremos no-patrocinaciĂłn para hablar de no-cosas.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img width=&quot;200&quot; src=&quot;http://www.pisitoenmadrid.com/blog/wp-content/uploads/2008/04/post_patrocinado.jpg&quot; /&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Hoy vamos a hablar sobre la ONG a la que pertenece uno de nuestros no-compaĂ±eros (por no decir fundador), llamada &amp;quot;&lt;b&gt;Platos VacĂ­os Sin VergĂĽenza&lt;/b&gt;&amp;quot;.&lt;/p&gt;&lt;p&gt;&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://blogs.nologin.es/lfabiani/archives/126-Entrada-no-patrocinada-Platos-Vacios-Sin-Vergueenza.html#extended&quot;&gt;Continua leyendo &quot;Entrada no-patrocinada: Platos VacĂ­os Sin VergĂĽenza&quot;&lt;/a&gt;</description>
	<pubDate>jue, 26 ago 2010 10:56:39 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Integrating Terminal Services into a Portal (Linux Version)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/18-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/18-Integrating-Terminal-Services-into-a-Portal-Linux-Version.html</link>
	<description>In &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/17-Integrating-Terminal-Services-into-a-Portal.html&quot;&gt;a previous entry&lt;/a&gt; Remote Desktop Protocol (RDP) was discussed and a custom portlet was presented. The portlet shows some applications (that were previously registered in Microsoft Remote Desktop Services) and it lets the user click any of them to download a RDP connection settings file that silently starts client-side RDP application. The solution was tested on a Windows XP box. Windows and Mac have free Microsoft RDC client application, but Linux is a complete different story.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.rdesktop.org&quot;&gt;Rdesktop&lt;/a&gt; is the traditional, and I think the only one, open source RDP solution. Until the time I faced that pre-sale I was not aware of the poor status of this project. Last rdesktop 1.6.0 version only supports version 5.2 of the remote desktop protocol and its releases are becoming more and more infrequent (1.6.0 was released in May 2008, 1.5.0 in September 2006, 1.4.1 in May 2005 and so on). The &lt;a href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=1773895&amp;amp;group_id=24366&amp;amp;atid=381350&quot;&gt;request to support RDP protocol 6.0&lt;/a&gt; was open in the summer of 2007 (a year after 6.0 version was released with Windows Vista) and it is still not assigned. But, you know, this is open source, do not complain and do not wait others to do your job, fix it yourself! Now talking seriously, if somebody has enough time and skills and wants to participate in the never-ending war against Microsoft this is a good project that needs some love.&lt;br /&gt;
&lt;br /&gt;
Coming back to the RDP portlet, Linux only has rdesktop and the portlet must work with it. The main restriction is that this program cannot use TS gateway, so only typical plain RDP (3389 TCP port) communication is possible (remember gateway can use the more secure, easier to integrate HTTPS protocol). This limitation makes absolutely compulsory the use of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Vpn&quot;&gt;VPN&lt;/a&gt; in order to establish a secure channel between an internet user and the server. And, of course, 5.2 protocol seems to be more bandwidth-hungry than 6.0/7.0 but nothing can be done with this issue.&lt;br /&gt;
&lt;br /&gt;
Nevertheless seamless remote application was introduced in 1.5.0 rdesktop version. I am not really sure if this feature uses RDP 6.0 protocol or it was done ad hoc but, after all, rdesktop has the -A option to run a remote application. SeamlessRDP extension was a &lt;a href=&quot;http://www.cendio.com/seamlessrdp/&quot;&gt;contribution of Cendio to rdesktop&lt;/a&gt; in another example of how open source works. This feature needs to install a server side windows program called seamlessrdpshell which is invoked by rdesktop as the alternate shell with the remote application to execute as an argument. For example:&lt;br /&gt;
&lt;blockquote&gt;$ rdesktop -A -s &quot;seamlessrdpshell.exe c:\Windows\System32\mspaint.exe&quot;&lt;/blockquote&gt;In my windows 2008 server installation this program was installed under &lt;em&gt;c:\Windows\System32\&lt;/em&gt; directory (this way it is always found in the execution path). Besides the executable was published as a valid TS Remote Aplication with command line parameters enabled (TS Server lets it run with arguments).&lt;br /&gt;
&lt;br /&gt;
Other issue is rdesktop does not understand rdp files (it is just a common linux command with several execution options). Some other graphical applications (like &lt;a href=&quot;http://tsclient.sourceforge.net&quot;&gt;tsclient&lt;/a&gt;) can parse rdp files and call rdesktop accordingly but none of them (at least I could not find anyone) understands the seamless rdp integration (-A option). So I had to code a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntegratingTerminalServicesintoaPortalLinuxVersion/mstsc.py.txt&quot;&gt;little python example&lt;/a&gt; that reads the rdp file and transforms the file tags into rdesktop options (plaease do not blame me, I already know there is room for improvement). The script needs two minor changes in the generated rdp file (now the alternate shell is specified with the full path to the application and the username is also supplied) but it still works for Microsoft client. Here it is a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntegratingTerminalServicesintoaPortalLinuxVersion/wordpad.rdp&quot;&gt;wordpad.rdp&lt;/a&gt; example. Finally the password to rdesktop invocation is hardcoded inside the script (I have commented the script is improvable, haven't I?).&lt;br /&gt;
&lt;br /&gt;
With all the commented limitations the portlet solution is ready to be executed in linux. Now when the application link is clicked the downloaded rdp file will be executed by the python script, which will run rdesktop with the seamless application option. The video is very similar to the presented in the previous entry but with Debian as OS and firefox/iceweasel as browser. If you see when rdesktop is launched the usual windows login page is presented, automatically fulfilled, and then it disappears, the reason is rdesktop does not have Network Level Authentication (new feature of 6.1 version of the protocol).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntegratingTerminalServicesintoaPortalLinuxVersion/out-lin.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
In summary, this time linux solution is less practical (internet access needs a VPN, a better RDP file parser would be necessary in a real deployment and some bandwidth improvements are lost) but thinking in a global solition, I mean, a solution for all type of clients, is always a good thing and, this way, nobody will say I did not try it.&lt;br /&gt;
&lt;br /&gt;
Keep the faith!</description>
	<pubDate>sáb, 21 ago 2010 13:56:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: La esencia de la publicidad</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/125-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/125-La-esencia-de-la-publicidad.html</link>
	<description>&lt;p&gt;La publicidad muchas veces intenta convencer de que el cielo es rojo, de que los perfumes dan la felicidad o las galletas caseras arreglan familias rotas. Por suerte, en Nologin no tenemos que recurrir a trucos como el que se ve en este video, tan..., representativo de la realidad.&lt;/p&gt;</description>
	<pubDate>lun, 16 ago 2010 22:00:00 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Personal Entries</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/20-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/20-Personal-Entries.html</link>
	<description>Today another entry about changes in the blog. First I have decided to add &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/19-Ricardo-Martin-Camarero-Ricky.html&quot;&gt;some information about myself&lt;/a&gt; in the left part. The previous weekend I requested my facebook account to be deleted, I did not use it. So I will try to post some personal entries from time to time and maybe make the blog a place where I can contact some distant friends (but of course this does not depend on me). This decision does not affect the usual topics which I want to keep on publishing. Second, this blog installation does not send any email to me (maybe I can discuss this issue with my company mates but I am afraid it is for some security reasons), so I have also added the last comments plugin in the left frame. This way I quickly know when someone has made one.&lt;br /&gt;
&lt;br /&gt;
Cheers!</description>
	<pubDate>vie, 13 ago 2010 11:18:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: La esencia del comercial</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/124-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/124-La-esencia-del-comercial.html</link>
	<description>&lt;p&gt;Hay dos maneras de hacer negocios: resolviendo problemas o necesidades, y creando problemas o necesidades. A veces la separaciĂłn entre resolver y crear es realmente estrecha porque la mayorĂ­a de los usuarios no tienen conciencia del problema al que se han acostumbrado. Los usuarios no saben lo bien que les vendrĂ­a tener dientes nuevos porque se han acostumbrado a los viejos. Y allĂ­ entra un buen comercial, uno mejor que Coco, por supuesto:&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;</description>
	<pubDate>lun, 09 ago 2010 22:00:00 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Integrating Terminal Services into a Portal</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/17-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/17-Integrating-Terminal-Services-into-a-Portal.html</link>
	<description>At the end of 2009 I participated in a pre-sale involving a portal migration in a governmental environment. The portal had some content management, portlets and an uncommon feature: &lt;a href=&quot;http://www.citrix.com&quot;&gt;citrix&lt;/a&gt;. This customer worked in a quite special way, their employees usually were out of their own installations but they needed regular access to some internal applications. The problem was part of these programs were very old dos/windows desktop applications which could not be easily moved to the web (customer had upgraded some to new web technologies but a lot of them still worked following this old-fashioned way). The portal used an old version of &lt;a href=&quot;http://www.citrix.es/Productos_y_Soluciones/Productos/XenApp/&quot;&gt;Citrix XenApp&lt;/a&gt; to place these old windows applications the customer really needed inside the portal. Besides that, typical requirements in a portal developing were demanded (sso, cms, eye-candy,...). An one more thing, customer wanted to change citrix for other solution and themselves also talked about the new features of windows Terminal Services.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Remote_Desktop_Protocol&quot;&gt;Remote Desktop Protocol or RDP&lt;/a&gt; is a proprietary protocol developed by Microsoft to provide graphical interface access from one computer to another remote one.  This technology is also known as Terminal Services because of the former name of Microsoft RDP server software (now called &lt;a href=&quot;https://www.microsoft.com/windowsserver2008/en/us/rds-product-home.aspx&quot;&gt;Remote Desktop Services or RDS&lt;/a&gt;). Windows 2008R2 introduced the new 7.0 version of the protocol at the end of the last year but the main improvements were done in the jump between 5.2 and 6.0/6.1 versions. Let's summarize the changes:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://support.microsoft.com/kb/925876&quot;&gt;Version 6.0&lt;/a&gt;&lt;/strong&gt; (November 2006 - Windows Vista):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Terminal Services Remote Applications&lt;/strong&gt;. Remote Programs are a feature of Windows Server Terminal Services that lets client computers connect to a remote computer and execute programs that are installed on it instead of the complete windows desktop. The experience is the same as running a program that is installed on the local computer. An administrator must first publish the programs for end-users to access them.&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;Terminal Services Gateway servers&lt;/strong&gt;. TS Gateway server is a type of gateway that enables authorized users to connect to remote computers on a corporate network. TS Gateway uses RDP together with HTTPS protocol to help create a more secure, encrypted connection. A TS Gateway server uses port 443 and transmits data through a Secure Sockets Layer (SSL) tunnel. TS Gateway opens usual RDP intranet solution up to the world wide web.&lt;br /&gt;
&lt;li&gt;Improved bandwidth tuning for RDP clients.&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://support.microsoft.com/kb/951616&quot;&gt;Version 6.1&lt;/a&gt;&lt;/strong&gt; (February 2008 - Windows Server 2008):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Terminal Services Web Access&lt;/strong&gt;. TS Web Access is a service that makes Windows Server programs (TS RemoteApp) available to users from a Web browser. TS Web Acces is a kind of application inside IIS that lets user start remote applications from a web browser. This feature is not a protocol improvement but a new feature of the windows server and client.&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Network_Level_Authentication&quot;&gt;Network level server authentication&lt;/a&gt;&lt;/strong&gt;. Technology that requires the user to authenticate himself before a session is established with the server. Originally the server loaded the login screen for the remote user, this used up resources on the server, and was a potential area for denial of service attacks.&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://support.microsoft.com/kb/969084&quot;&gt;Version 7.0&lt;/a&gt;&lt;/strong&gt; (October 2009 - Windows Server 2008R2 and Windows 7):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Web Single Sign-On (SSO) and Web forms-based authentication&lt;/strong&gt;. Web SSO makes sure that after a user is logged on, no additional passwords are required for RD Gateway, RD Web Access, RD Session Host servers and RemoteApp programs.&lt;br /&gt;
&lt;li&gt;Multiple improvements in bandwidth (aero glass composed desktop support, smooth fonts, audio and video redirection).&lt;br /&gt;
&lt;li&gt;Multiple features to Virtual Desktop Infrastructure or VDI integration (virtual desktops and pools).&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
So now RDP alone accomplishes all common client requirements. Remote Applications gives to the user a seamless desktop integration, TS Gateway moves RDP and Remote Applications to the internet, Web Access moves again RDP to the web and finally it seems there have been several bandwidth improvements to make a better experience (Microsoft published a good &lt;a href=&quot;http://download.microsoft.com/download/4/d/9/4d9ae285-3431-4335-a86e-969e7a146d1b/RDP_Performance_WhitePaper.docx&quot;&gt;whitepaper about RDP bandwidth&lt;/a&gt; when 6.1 version was released).&lt;br /&gt;
&lt;br /&gt;
Now the main problem is how to integrate RDP inside a portal. The easiest way is just using the TS Web Access inside an iframe (the same technique I used in &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/11-Making-a-SUDOKU-using-CGI.html&quot;&gt;the sudoku entry&lt;/a&gt; to show you the html design). Liferay for example has an &lt;a href=&quot;http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Iframe%20Portlet&quot;&gt;IFrame portlet&lt;/a&gt; that lets you point the portlet region to another page (TS Web Access server in our case), integrating TS web application easily in your portal. But, in my opinion, TS Web Access is not the best option because it works using an ActiveX element which directly bans any OS different than Windows, any web browser different than internet explorer, any RDP client different than windows Remote Desktop Connection (RDC).&lt;br /&gt;
&lt;br /&gt;
As always my solution is maybe more complex but I am sure it is more open and funny. Based on the fact that RDP connection settings can be saved in a RDP file (this way these files can be easily edited, copied, and distributed), my idea is developing a little portlet which shows to the user the remote applications configured and, when clicked,  a generated rdp file is downloaded to be executed by local remote desktop client. This way the solution works in any system that has a RDP compatible application. Microsoft has free &lt;a href=&quot;http://support.microsoft.com/kb/969084&quot;&gt;Remote Desktop Connection 7.0&lt;/a&gt; for windows OSes and &lt;a href=&quot;http://support.microsoft.com/kb/974283&quot;&gt;Microsoft Remote Desktop Connection 2.0.1&lt;/a&gt; Client for Mac (&lt;a href=&quot;http://www.microsoft.com/mac/help.mspx?MODE=ct&amp;amp;CTT=PageView&amp;amp;clr=99-6-0&amp;amp;target=870500bb-d48d-4f90-b993-7d5a3f6f654c1033&amp;amp;srcid=&amp;amp;ep=8&amp;amp;rtype=2&amp;amp;pos=2&amp;amp;quid=3a240d0f-e90f-436f-a28c-c1afd0ee854f&quot;&gt;it supports RDP 6.0&lt;/a&gt;). In a similar way I did with Skype, browser can be configured to open rdp files (&lt;em&gt;application/x-rdp&lt;/em&gt; mime type) with the selected client-side application. Linux and other *nix OSes are another question and I will try to face this problem in a future post.&lt;br /&gt;
&lt;br /&gt;
The solution is a simple JSF 2.0 portlet (deployed on liferay 6.0.2)  that uses cassandra as repository to store the application data (remember I already commented this to you in a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/9-Getting-Started-With-Cassandra.html&quot;&gt;previous entry about cassandra database&lt;/a&gt;). Portlet implementation saves the complete rdp file (the same that is generated and exported from TS Remote Administration application) in the database. When you click the application link the rdp file is fetched from cassandra and downloaded to the client.&lt;br /&gt;
&lt;br /&gt;
This time the video shows the following: on the right a Windows 2008 60-day evaluation version configured as TS Server; on the left my Windows XP with RDC 7.0 installed; using IE8 I access to liferay and search for Notepad application; after clicking on it the rdp file is downloaded from my portlet and the browser asks to open it; accepting the offer RDC client remotely opens Notepad; when a simple text file is saved on administrator desktop it can be shown on windows 2008 server. Take into account I could not install 2008R2 (cos Microsoft only distributes 64 bit version and my laptop is i386), so the server only supports protocol version 6.1. This version lacks new SSO features and TS client application does not ask for user and password cos I locally saved my credentials before and it is reusing them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a class=&quot;myPlayer&quot; href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntegratingTerminalServicesintoaPortal/out-win.flv&quot;&gt;&lt;img src=&quot;http://blogs.nologin.es/rickyepoderi/uploads/flowplayer/play_large.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
Clearly notepad is a useless program but integrating this kind of remote applications can be very very important in some environments (legacy applications, programs with expensive licenses, binaries with local limited access,...). RDP protocol and its new features open up a lot of new possibilities and portlet integration makes its management easier for end users.&lt;br /&gt;
&lt;br /&gt;
Finally I want to point out the use of &lt;a href=&quot;http://cassandra.apache.org/&quot;&gt;cassandra&lt;/a&gt; as repository and &lt;a href=&quot;http://www.portletfaces.org/projects/portletfaces-bridge&quot;&gt;portletfaces bridge&lt;/a&gt; as portlet/JSF 2.0 joint. I already stated the worth of the first one in the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/9-Getting-Started-With-Cassandra.html&quot;&gt;commented cassandra entry&lt;/a&gt; but I had never talked about the second piece of software. Neil Griffin heads this java project to create a portlet bridge for the new JSF 2.0 specification. I used alpha 1 version in my &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/6-Integrating-Skype-into-a-Portal.html&quot;&gt;skype&lt;/a&gt;/&lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/7-Integrating-VoIP-into-a-Portal.html&quot;&gt;pidgin&lt;/a&gt; VoIP solution and alpha 3 in this TS portlet, and I have to mention the outstanding progress. Good job Neil!</description>
	<pubDate>vie, 06 ago 2010 14:01:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Nolife at Nologin: La esencia del usuario</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/123-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/123-La-esencia-del-usuario.html</link>
	<description>&lt;p&gt;Cuando uno es usuario o cliente de lo que sea (desde un restaurante o una tienda a una ventanilla pĂşblica o una consultorĂ­a), se siente demasiadas veces como el comensal del chiste de Coco...&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;En Nologin sabemos lo que es eso y por eso nos adaptamos a las necesidades de nuestros clientes, para que ellos no se tengan que adaptar a nosotros que bastante tienen con lo suyo. Y eso hemos intentado transmitir con &lt;a href=&quot;http://www.nologin.es&quot;&gt;nuestra nueva pĂˇgina web&lt;/a&gt;, en la que confiamos que encontrĂ©is lo que necesitĂˇis. Si no es asĂ­, no dudĂ©is en poneros en contacto con nosotros.&lt;/p&gt;</description>
	<pubDate>lun, 02 ago 2010 22:00:00 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Pon un sol en tu vida: Webs de administraciĂłn y puertos redirigidos</title>
	<guid>http://blogs.nologin.es/slopez/archives/24-guid.html</guid>
	<link>http://blogs.nologin.es/slopez/archives/24-Webs-de-administracion-y-puertos-redirigidos.html</link>
	<description>Si trabajas administrando sistemas, es posible que te hayas encontrado en la tesitura de tener que acceder a la consola de administraciĂłn de algĂşn dispositivo a travĂ©s de un tĂşnel SSH, redirigiendo algĂşn puerto de la mĂˇquina de destino a otro local. Al hacer esto, puedes encontrarte con la circunstancia de que la aplicaciĂłn a la que estĂˇs accediendo tiene referencias estĂˇticas a su IP real, lo cual provoca que no puedas acceder correctamente a ella.&lt;br /&gt;
&lt;br /&gt;
Si este es tu caso, y estĂˇs utilizando GNU/Linux, puedes hacer uso de &lt;i&gt;iptables&lt;/i&gt; para salvar el escollo. Por ejemplo con&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;iptables -t nat -A OUTPUT -p tcp --dport 9000 -j DNAT --to 127.0.0.1:9000&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
estarĂ­amos redigiriendo todo el trĂˇfico saliente hacia el puerto 9000, al mismo puerto en nuestra mĂˇquina local.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description>
	<pubDate>jue, 29 jul 2010 13:41:32 +0000</pubDate>
	<author>nospam@example.com (Sergio Lopez)</author>
</item>
<item>
	<title>Nolife at Nologin: La esencia de la consultorĂ­a informĂˇtica</title>
	<guid>http://blogs.nologin.es/lfabiani/archives/122-guid.html</guid>
	<link>http://blogs.nologin.es/lfabiani/archives/122-La-esencia-de-la-consultoria-informatica.html</link>
	<description>&lt;p&gt;Hay algunas caracterĂ­sticas de la relaciĂłn del consultor con el cliente que ponen de los nervios.&lt;/p&gt;&lt;p&gt;Hay unas caracterĂ­sticas de la relaciĂłn del informĂˇtico con el cliente que sacan de quicio.&lt;/p&gt;&lt;p&gt;Cuando uno es consultor informĂˇtico, se siente la TĂ­a Pepa...&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;
NOTA: Empiezo una serie de recopilatorios de videos &quot;esenciales&quot; con las que confĂ­o alegraros un poco el verano y creĂˇis que estoy trabajando.</description>
	<pubDate>lun, 26 jul 2010 22:32:36 +0000</pubDate>
	<author>nospam@example.com (bufon)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Introducing CalDAV (Part II)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/15-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/15-Introducing-CalDAV-Part-II.html</link>
	<description>In the &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html&quot;&gt;previous entry&lt;/a&gt; the CalDAV protocol was introduced. This protocol is a standard way of managing calendar and scheduling iCalendar data files as WebDAV collections. If you have read the first part the final goal was testing some CalDAV methods against three different providers (&lt;a href=&quot;https://www.google.com/calendar&quot;&gt;Google Calendar&lt;/a&gt;, &lt;a href=&quot;http://calendar.yahoo.com/&quot;&gt;Yahoo! Calendar &lt;/a&gt; and &lt;a href=&quot;http://trac.calendarserver.org/&quot;&gt;Calendar Server&lt;/a&gt; -open source version of Apple iCal Calendar Server-). The tester class was developed using &lt;a href=&quot;http://jackrabbit.apache.org/jackrabbit-webdav-library.html&quot;&gt;jackrabbit-webdav&lt;/a&gt; library for WebDAV protocol and &lt;a href=&quot;http://wiki.modularity.net.au/ical4j/index.php?title=Main_Page&quot;&gt;iCal4j&lt;/a&gt; for iCalendar data processing. In the previous post OPTIONS and PROPFIND methods were presented. The first one returns via headers if CalDAV is supported over an URI. The second method returns the properties of the same calendar CalDAV URI.&lt;br /&gt;
&lt;br /&gt;
This entry continues testing CalDAV with the following methods:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Creation of a calendar VEVENT via PUT method.&lt;br /&gt;
&lt;li&gt;Retrieving the just created VEVENT using calendar-multiget REPORT.&lt;br /&gt;
&lt;li&gt;Querying the VEVENTs using calendar-query REPORT.&lt;br /&gt;
&lt;li&gt;Deletion of the VEVENT.&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;h3&gt;PUT&lt;/h3&gt;&lt;br /&gt;
The PUT method uploads a resource to a web server. Defined in the HTTP specification PUT sends any file inside body part, in case of CalDAV the only requirement is content was of type iCalendar (&lt;em&gt;text/calendar&lt;/em&gt; in &lt;em&gt;Content-Type&lt;/em&gt; header). Because a new event is going to be created I have added a &lt;em&gt;If-None-Match&lt;/em&gt; conditional header to not perform the PUT if any (*) resource already exists in the same URI.&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
PutMethod put = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;UUID uuid = UUID.randomUUID();&lt;br /&gt;
&amp;#160;&amp;#160;CalendarBuilder builder = new CalendarBuilder();&lt;br /&gt;
&amp;#160;&amp;#160;net.fortuna.ical4j.model.Calendar c = new net.fortuna.ical4j.model.Calendar();&lt;br /&gt;
&amp;#160;&amp;#160;c.getProperties().add(new ProdId(&quot;-//Ben Fortuna//iCal4j 1.0//EN&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;c.getProperties().add(Version.VERSION_2_0);&lt;br /&gt;
&amp;#160;&amp;#160;c.getProperties().add(CalScale.GREGORIAN);&lt;br /&gt;
&amp;#160;&amp;#160;TimeZoneRegistry registry = builder.getRegistry();&lt;br /&gt;
&amp;#160;&amp;#160;VTimeZone tz = registry.getTimeZone(&quot;Europe/Madrid&quot;).getVTimeZone();&lt;br /&gt;
&amp;#160;&amp;#160;c.getComponents().add(tz);&lt;br /&gt;
&amp;#160;&amp;#160;VEvent vevent = new VEvent(new net.fortuna.ical4j.model.Date(),&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;new Dur(0, 1, 0, 0), &quot;test&quot;);&lt;br /&gt;
&amp;#160;&amp;#160;vevent.getProperties().add(new Uid(uuid.toString()));&lt;br /&gt;
&amp;#160;&amp;#160;c.getComponents().add(vevent);&lt;br /&gt;
&amp;#160;&amp;#160;String href = uri + uuid.toString() + &quot;.ics&quot;;&lt;br /&gt;
&amp;#160;&amp;#160;put = new PutMethod(href);&lt;br /&gt;
&amp;#160;&amp;#160;put.addRequestHeader(&quot;If-None-Match&quot;, &quot;*&quot;);&lt;br /&gt;
&amp;#160;&amp;#160;put.setRequestEntity(new StringRequestEntity(c.toString(), &quot;text/calendar&quot;, &quot;UTF-8&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(put);&lt;br /&gt;
&amp;#160;&amp;#160;return href;&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (put != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;put.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
This code creates a new iCal4j calendar and assigns timezone and a event to it. After that a PUT method is constructed and the previously iCalendar object is set as its request. In WebDAV (and CalDAV) the client side is the responsible of choosing a name (the URI part) to the resource, here I have used a UUID to generate a random and different &lt;em&gt;href&lt;/em&gt; URI.&lt;br /&gt;
&lt;br /&gt;
As PUT method is almost the same in the three server implementations only Google Calendar trace is presented.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;PUT /calendar/dav/rickyepoderi@gmail.com/events/fca0402c-f00a-493c-9b48-8cec2a203728.ics HTTP/1.1&lt;br /&gt;
If-None-Match: *&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 3041&lt;br /&gt;
Content-Type: text/calendar; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
BEGIN:VCALENDAR&lt;br /&gt;
PRODID:-//Ben Fortuna//iCal4j 1.0//EN&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
CALSCALE:GREGORIAN&lt;br /&gt;
BEGIN:VTIMEZONE&lt;br /&gt;
TZID:Europe/Madrid&lt;br /&gt;
TZURL:http://tzurl.org/zoneinfo/Europe/Madrid&lt;br /&gt;
X-LIC-LOCATION:Europe/Madrid&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
DTSTART:19810329T020000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
DTSTART:19961027T030000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
TZOFFSETFROM:-001444&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
DTSTART:19010101T011444&lt;br /&gt;
RDATE:19010101T011444&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
TZOFFSETFROM:+0000&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
TZNAME:WEST&lt;br /&gt;
DTSTART:19170506T000000&lt;br /&gt;
RDATE:19170506T000000&lt;br /&gt;
RDATE:19180416T000000&lt;br /&gt;
RDATE:19190406T000000&lt;br /&gt;
RDATE:19240417T000000&lt;br /&gt;
RDATE:19260418T000000&lt;br /&gt;
RDATE:19270410T000000&lt;br /&gt;
RDATE:19280415T000000&lt;br /&gt;
RDATE:19290421T000000&lt;br /&gt;
RDATE:19370523T000000&lt;br /&gt;
RDATE:19380323T000000&lt;br /&gt;
RDATE:19390416T000000&lt;br /&gt;
RDATE:19400317T000000&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
DTSTART:19171007T010000&lt;br /&gt;
RDATE:19171007T010000&lt;br /&gt;
RDATE:19181007T010000&lt;br /&gt;
RDATE:19191007T010000&lt;br /&gt;
RDATE:19241005T010000&lt;br /&gt;
RDATE:19261003T010000&lt;br /&gt;
RDATE:19271002T010000&lt;br /&gt;
RDATE:19281007T010000&lt;br /&gt;
RDATE:19291006T010000&lt;br /&gt;
RDATE:19371003T010000&lt;br /&gt;
RDATE:19381002T010000&lt;br /&gt;
RDATE:19391008T010000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
TZNAME:WEMT&lt;br /&gt;
DTSTART:19420503T000000&lt;br /&gt;
RDATE:19420503T000000&lt;br /&gt;
RDATE:19430418T000000&lt;br /&gt;
RDATE:19440416T000000&lt;br /&gt;
RDATE:19450415T000000&lt;br /&gt;
RDATE:19460414T000000&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
TZNAME:WEST&lt;br /&gt;
DTSTART:19420902T010000&lt;br /&gt;
RDATE:19420902T010000&lt;br /&gt;
RDATE:19431004T010000&lt;br /&gt;
RDATE:19441011T010000&lt;br /&gt;
RDATE:19450930T020000&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
DTSTART:19460930T000000&lt;br /&gt;
RDATE:19460930T000000&lt;br /&gt;
RDATE:19490930T010000&lt;br /&gt;
RDATE:19741006T010000&lt;br /&gt;
RDATE:19751005T010000&lt;br /&gt;
RDATE:19760926T010000&lt;br /&gt;
RDATE:19770925T010000&lt;br /&gt;
RDATE:19781001T010000&lt;br /&gt;
RDATE:19790930T030000&lt;br /&gt;
RDATE:19800928T030000&lt;br /&gt;
RDATE:19810927T030000&lt;br /&gt;
RDATE:19820926T030000&lt;br /&gt;
RDATE:19830925T030000&lt;br /&gt;
RDATE:19840930T030000&lt;br /&gt;
RDATE:19850929T030000&lt;br /&gt;
RDATE:19860928T030000&lt;br /&gt;
RDATE:19870927T030000&lt;br /&gt;
RDATE:19880925T030000&lt;br /&gt;
RDATE:19890924T030000&lt;br /&gt;
RDATE:19900930T030000&lt;br /&gt;
RDATE:19910929T030000&lt;br /&gt;
RDATE:19920927T030000&lt;br /&gt;
RDATE:19930926T030000&lt;br /&gt;
RDATE:19940925T030000&lt;br /&gt;
RDATE:19950924T030000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
DTSTART:19490430T230000&lt;br /&gt;
RDATE:19490430T230000&lt;br /&gt;
RDATE:19740413T230000&lt;br /&gt;
RDATE:19750419T230000&lt;br /&gt;
RDATE:19760327T230000&lt;br /&gt;
RDATE:19770402T230000&lt;br /&gt;
RDATE:19780402T230000&lt;br /&gt;
RDATE:19790401T020000&lt;br /&gt;
RDATE:19800406T020000&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
DTSTART:19790101T000000&lt;br /&gt;
RDATE:19790101T000000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
END:VTIMEZONE&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
DTSTAMP:20100709T080233Z&lt;br /&gt;
DTSTART;VALUE=DATE:20100709&lt;br /&gt;
DURATION:PT1H&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
UID:fca0402c-f00a-493c-9b48-8cec2a203728&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 201 Created&lt;br /&gt;
DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;br /&gt;
Content-Type: text/calendar; component=vevent; charset=UTF-8&lt;br /&gt;
Date: Fri, 09 Jul 2010 08:02:35 GMT&lt;br /&gt;
Expires: Fri, 09 Jul 2010 08:02:35 GMT&lt;br /&gt;
Cache-Control: private, max-age=0&lt;br /&gt;
X-Content-Type-Options: nosniff&lt;br /&gt;
X-Frame-Options: SAMEORIGIN&lt;br /&gt;
X-XSS-Protection: 1; mode=block&lt;br /&gt;
Content-Length: 0&lt;br /&gt;
Server: GSE&lt;/blockquote&gt;&lt;br /&gt;
&lt;h3&gt;CALENDAR-MULTIGET REPORT&lt;/h3&gt;&lt;br /&gt;
The first real CalDAV method. A REPORT is an extensible mechanism for obtaining information about resources defined in &lt;a href=&quot;http://tools.ietf.org/html/rfc3253&quot;&gt;RFC-3253&lt;/a&gt;. The value of a report can depend on additional information specified in the REPORT request body and in the REPORT request headers. CalDAV specification defines some of them and &lt;em&gt;calendar-multiget&lt;/em&gt; is the first one to be tested. It returns the specified data (any CalDAV report lets us define the iCalendar information that is going to be returned) for a list of resources (a list of URIs that represents iCalendar resources). As any other WebDAV method calendar-multiget has a standard XML request (defined via DTD) that is sent to the server. The response (like many other reports) is a multi-status response (a list of resource responses that match the report criteria with the properties requested attached). &lt;br /&gt;
&lt;br /&gt;
So, first of all, I developed some classes that implement all the XML stuff (properties and report itself). All this simple classes are inside a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/sample.caldav.xml.zip&quot;&gt;sample.caldav.xml&lt;/a&gt; package and they use the W3C DOM XML parser (jackrabbit-webdav already uses it). Besides jackrabbit-webdav has a &lt;em&gt;ReportMethod&lt;/em&gt; class to execute any report against a WebDAV server, this class uses another one (&lt;em&gt;ReportInfo&lt;/em&gt;) that defines the report to execute. The problem here is jackrabbit assumes all properties to return are specified using only names (simple XML tags like &amp;lt;getetag/&gt; or &amp;lt;getctag/&gt;) and CalDAV properties are more complicated (see the XML classes of the package presented before). For this reason my only chance was extending ReportInfo with a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/CalendarMultiGetReportInfo.java&quot;&gt;CalendarMultiGetReportInfo.java&lt;/a&gt; that constructs the correct XML elements for this report (toXml method). One thing I did not understand completely was why jackrabbit needs all the reports to be registered inside &lt;em&gt;ReportType&lt;/em&gt; class, this registration uses a Report class which I did not see where is used. For this reason I created and registered an empty report &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/CalendarMultiGetReport.java&quot;&gt;CalendarMultiGetReport.java&lt;/a&gt;. A class for constants called &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/CalDavConstants.java&quot;&gt;CalDavConstants.java&lt;/a&gt; is also used in a similar way jackrabbit uses &lt;em&gt;DavConstants.java&lt;/em&gt;. The final code to execute the report that retrieves the previously created event is the following.&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
ReportMethod report = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;// append props GETTETAG&lt;br /&gt;
&amp;#160;&amp;#160;DavPropertyNameSet props = new DavPropertyNameSet();&lt;br /&gt;
&amp;#160;&amp;#160;props.add(DavPropertyName.GETETAG);&lt;br /&gt;
&amp;#160;&amp;#160;// append calendar-data&lt;br /&gt;
&amp;#160;&amp;#160;RequestCalendarData calendarData = new RequestCalendarData();&lt;br /&gt;
&amp;#160;&amp;#160;Comp vcalendar = new Comp(&quot;VCALENDAR&quot;);&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getProp().add(new Prop(&quot;VERSION&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().add(new Comp(&quot;VEVENT&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;SUMMARY&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;UID&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;DTSTART&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;DTEND&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;DURATION&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;RRULE&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;RDATE&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;EXRULE&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;EXDATE&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().get(0).getProp().add(new Prop(&quot;RECURRENCE-ID&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;vcalendar.getComp().add(new Comp(&quot;VTIMEZONE&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;calendarData.setComp(vcalendar);&lt;br /&gt;
&amp;#160;&amp;#160;// create the report&lt;br /&gt;
&amp;#160;&amp;#160;ReportInfo reportInfo = new CalendarMultiGetReportInfo(props, &lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;calendarData, new String[]{createdHref});&lt;br /&gt;
&amp;#160;&amp;#160;report = new ReportMethod(uri, reportInfo);&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(report);&lt;br /&gt;
&amp;#160;&amp;#160;MultiStatus multiStatus = report.getResponseBodyAsMultiStatus();&lt;br /&gt;
&amp;#160;&amp;#160;for (int i = 0; i  multiStatus.getResponses().length; i++) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;MultiStatusResponse multiRes = multiStatus.getResponses()[i];&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;String href = multiRes.DavPropertySet propSet = multiRes.getProperties(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;DavServletResponse.SC_OK);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;DavProperty prop = (DavProperty) propSet.get(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;CalDavConstants.CALDAV_XML_CALENDAR_DATA, CalDavConstants.CALDAV_NAMESPACE);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;System.err.println(&quot;HREF: &quot; + href);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;CalendarBuilder builder = new CalendarBuilder();&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;net.fortuna.ical4j.model.Calendar c = builder.build(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;new StringReader(prop.getValue()));&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;System.err.println(&quot;calendar-data: &quot; + c.toString());&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (report != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;report.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
As you see the example requests for VCALENDAR information (only property VERSION) and, inside it, the VEVENT (with only some properties) and the VTIMEZONE (with all properties). The HREF part must be the one returned in the creation part. I added a &lt;em&gt;ETag&lt;/em&gt; (Entity Tag) property as a non CalDAV property to be retrieved. Studying the below communication traces there are some curious results. First open source Calendar Server follows the guidelines and only returns the requested props but google and yahoo! always return all calendar data. And second only Calendar Server returns exactly the same data put before, google and yahoo! have modified the iCalendar resource (some kind of pre-processing before storing it).&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /calendar/dav/rickyepoderi@gmail.com/events/ HTTP/1.1&lt;br /&gt;
Depth: 0&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 673&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-multiget xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getetag/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;VERSION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;SUMMARY&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;UID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DTSTART&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DTEND&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DURATION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RECURRENCE-ID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VTIMEZONE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
  &amp;lt;D:href&gt;https://www.google.com/calendar/dav/rickyepoderi@gmail.com/events/fca0402c-f00a-493c-9b48-8cec2a203728.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;lt;/C:calendar-multiget&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi-Status&lt;br /&gt;
DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;br /&gt;
Content-Type: application/xml; charset=UTF-8&lt;br /&gt;
Date: Fri, 09 Jul 2010 08:02:36 GMT&lt;br /&gt;
Expires: Fri, 09 Jul 2010 08:02:36 GMT&lt;br /&gt;
Cache-Control: private, max-age=0&lt;br /&gt;
X-Content-Type-Options: nosniff&lt;br /&gt;
X-Frame-Options: SAMEORIGIN&lt;br /&gt;
X-XSS-Protection: 1; mode=block&lt;br /&gt;
Content-Length: 1059&lt;br /&gt;
Server: GSE&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;https://www.google.com/calendar/dav/rickyepoderi@gmail.com/events/fca0402c-f00a-493c-9b48-8cec2a203728.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getetag&gt;&quot;63414345755&quot;&amp;lt;/D:getetag&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&lt;br /&gt;
PRODID:-//Google Inc//Google Calendar 70.9054//EN&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
CALSCALE:GREGORIAN&lt;br /&gt;
X-WR-CALNAME:Ricardo Martin&lt;br /&gt;
X-WR-TIMEZONE:Europe/Paris&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
DTSTART:20100708T220000Z&lt;br /&gt;
DTEND:20100708T230000Z&lt;br /&gt;
DTSTAMP:20100709T080235Z&lt;br /&gt;
UID:fca0402c-f00a-493c-9b48-8cec2a203728&lt;br /&gt;
CREATED:20100709T080235Z&lt;br /&gt;
DESCRIPTION:&lt;br /&gt;
LAST-MODIFIED:20100709T080235Z&lt;br /&gt;
LOCATION:&lt;br /&gt;
SEQUENCE:0&lt;br /&gt;
STATUS:CONFIRMED&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
TRANSP:OPAQUE&lt;br /&gt;
BEGIN:VALARM&lt;br /&gt;
ACTION:DISPLAY&lt;br /&gt;
DESCRIPTION:This is an event reminder&lt;br /&gt;
TRIGGER:-P0DT0H10M0S&lt;br /&gt;
END:VALARM&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:response&gt;&lt;br /&gt;
&amp;lt;/D:multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Yahoo! Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/ HTTP/1.1&lt;br /&gt;
Depth: 0[\n]&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 691&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXXX&lt;br /&gt;
Host: caldav.calendar.yahoo.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-multiget xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getetag/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;VERSION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;SUMMARY&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;UID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DTSTART&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;nbsp;&amp;lt;C:prop name=&quot;DTEND&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DURATION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RECURRENCE-ID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VTIMEZONE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:href&gt;https://caldav.calendar.yahoo.com/dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/b1e1683b-08d5-4ca3-b537-ed6a0c5867b9.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;lt;/C:calendar-multiget&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi Status&lt;br /&gt;
Date: Fri, 09 Jul 2010 09:39:46 GMT&lt;br /&gt;
P3P: policyref=&quot;http://info.yahoo.com/w3c/p3p.xml&quot;, CP=&quot;CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV&quot;&lt;br /&gt;
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule&lt;br /&gt;
DAV: version-control, addressbook, extended-mkcol, calendar-proxy&lt;br /&gt;
DAV: calendarserver-principal-property-search&lt;br /&gt;
Content-Type: text/xml; charset=utf-8&lt;br /&gt;
X-Cache: MISS from store138.c104.cal.gq1.yahoo.com&lt;br /&gt;
Age: 0&lt;br /&gt;
Transfer-Encoding: chunked&lt;br /&gt;
Connection: keep-alive&lt;br /&gt;
Server: YTS/1.17.23&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;/dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/b1e1683b-08d5-4ca3-b537-ed6a0c5867b9.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getetag&gt;&quot;400-400&quot;&amp;lt;/D:getetag&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
PRODID:Zimbra-Calendar-Provider&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
UID:b1e1683b-08d5-4ca3-b537-ed6a0c5867b9&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
DTSTART;VALUE=DATE:20100709&lt;br /&gt;
DURATION:PT1H&lt;br /&gt;
STATUS:CONFIRMED&lt;br /&gt;
CLASS:PUBLIC&lt;br /&gt;
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE&lt;br /&gt;
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY&lt;br /&gt;
TRANSP:OPAQUE&lt;br /&gt;
X-MICROSOFT-DISALLOW-COUNTER:TRUE&lt;br /&gt;
DTSTAMP:20100709T093944Z&lt;br /&gt;
SEQUENCE:0&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:response&gt;&lt;br /&gt;
&amp;lt;/D:multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Calendar Server:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /calendars/users/admin/calendar/ HTTP/1.1&lt;br /&gt;
Depth: 0&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 660&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Digest username=&quot;admin&quot;, realm=&quot;Test Realm&quot;, nonce=&quot;64064457517812303241909094429&quot;, uri=&quot;/calendars/users/admin/calendar/&quot;, response=&quot;3fc6f79c4b2c8ef0c60e415429fc864e&quot;, algorithm=&quot;md5&quot;&lt;br /&gt;
Host: localhost:8008&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-multiget xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getetag/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;VERSION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;SUMMARY&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;UID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DTSTART&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DTEND&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;DURATION&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXRULE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;EXDATE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:prop name=&quot;RECURRENCE-ID&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp name=&quot;VTIMEZONE&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:href&gt;http://localhost:8008/calendars/users/admin/calendar/8fbfb266-6f6b-4201-b51a-a75416640a25.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;lt;/C:calendar-multiget&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi-Status&lt;br /&gt;
Content-Length: 3457&lt;br /&gt;
Accept-Ranges: bytes&lt;br /&gt;
Server: CalendarServer/trunk(r5842M) Twisted/10.0.0 TwistedWeb/9.0.0+r5842&lt;br /&gt;
Last-Modified: Fri, 09 Jul 2010 09:49:08 GMT&lt;br /&gt;
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-availability, inbox-availability, calendar-proxy, calendarserver-private-events, calendarserver-private-comments, calendarserver-sharing, addressbook, calendarserver-principal-property-search&lt;br /&gt;
ETag: W/&quot;285DD2-1000-4C36F094&lt;br /&gt;
Date: Fri, 09 Jul 2010 09:49:08 GMT&lt;br /&gt;
Content-Type: text/xml&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;br /&gt;
&amp;lt;multistatus xmlns='DAV:'&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;href&gt;/calendars/users/admin/calendar/8fbfb266-6f6b-4201-b51a-a75416640a25.ics&amp;lt;/href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;getetag&gt;&quot;234cd0ad246d14829d189feca8c0eead&quot;&amp;lt;/getetag&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;calendar-data xmlns='urn:ietf:params:xml:ns:caldav'&gt;&amp;lt;![CDATA[BEGIN:VCALENDAR&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
PRODID:-//PYVOBJECT//NONSGML Version 1//EN&lt;br /&gt;
BEGIN:VTIMEZONE&lt;br /&gt;
TZID:Europe/Madrid&lt;br /&gt;
TZURL:http://tzurl.org/zoneinfo/Europe/Madrid&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19961027T030000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19010101T011444&lt;br /&gt;
RDATE:19010101T011444&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
TZOFFSETFROM:-001444&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19171007T010000&lt;br /&gt;
RDATE:19171007T010000&lt;br /&gt;
RDATE:19181007T010000&lt;br /&gt;
RDATE:19191007T010000&lt;br /&gt;
RDATE:19241005T010000&lt;br /&gt;
RDATE:19261003T010000&lt;br /&gt;
RDATE:19271002T010000&lt;br /&gt;
RDATE:19281007T010000&lt;br /&gt;
RDATE:19291006T010000&lt;br /&gt;
RDATE:19371003T010000&lt;br /&gt;
RDATE:19381002T010000&lt;br /&gt;
RDATE:19391008T010000&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19460930T000000&lt;br /&gt;
RDATE:19460930T000000&lt;br /&gt;
RDATE:19490930T010000&lt;br /&gt;
RDATE:19741006T010000&lt;br /&gt;
RDATE:19751005T010000&lt;br /&gt;
RDATE:19760926T010000&lt;br /&gt;
RDATE:19770925T010000&lt;br /&gt;
RDATE:19781001T010000&lt;br /&gt;
RDATE:19790930T030000&lt;br /&gt;
RDATE:19800928T030000&lt;br /&gt;
RDATE:19810927T030000&lt;br /&gt;
RDATE:19820926T030000&lt;br /&gt;
RDATE:19830925T030000&lt;br /&gt;
RDATE:19840930T030000&lt;br /&gt;
RDATE:19850929T030000&lt;br /&gt;
RDATE:19860928T030000&lt;br /&gt;
RDATE:19870927T030000&lt;br /&gt;
RDATE:19880925T030000&lt;br /&gt;
RDATE:19890924T030000&lt;br /&gt;
RDATE:19900930T030000&lt;br /&gt;
RDATE:19910929T030000&lt;br /&gt;
RDATE:19920927T030000&lt;br /&gt;
RDATE:19930926T030000&lt;br /&gt;
RDATE:19940925T030000&lt;br /&gt;
RDATE:19950924T030000&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19790101T000000&lt;br /&gt;
RDATE:19790101T000000&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19810329T020000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19170506T000000&lt;br /&gt;
RDATE:19170506T000000&lt;br /&gt;
RDATE:19180416T000000&lt;br /&gt;
RDATE:19190406T000000&lt;br /&gt;
RDATE:19240417T000000&lt;br /&gt;
RDATE:19260418T000000&lt;br /&gt;
RDATE:19270410T000000&lt;br /&gt;
RDATE:19280415T000000&lt;br /&gt;
RDATE:19290421T000000&lt;br /&gt;
RDATE:19370523T000000&lt;br /&gt;
RDATE:19380323T000000&lt;br /&gt;
RDATE:19390416T000000&lt;br /&gt;
RDATE:19400317T000000&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19420503T000000&lt;br /&gt;
RDATE:19420503T000000&lt;br /&gt;
RDATE:19430418T000000&lt;br /&gt;
RDATE:19440416T000000&lt;br /&gt;
RDATE:19450415T000000&lt;br /&gt;
RDATE:19460414T000000&lt;br /&gt;
TZNAME:WEMT&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19420902T010000&lt;br /&gt;
RDATE:19420902T010000&lt;br /&gt;
RDATE:19431004T010000&lt;br /&gt;
RDATE:19441011T010000&lt;br /&gt;
RDATE:19450930T020000&lt;br /&gt;
TZNAME:WEST&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19490430T230000&lt;br /&gt;
RDATE:19490430T230000&lt;br /&gt;
RDATE:19740413T230000&lt;br /&gt;
RDATE:19750419T230000&lt;br /&gt;
RDATE:19760327T230000&lt;br /&gt;
RDATE:19770402T230000&lt;br /&gt;
RDATE:19780402T230000&lt;br /&gt;
RDATE:19790401T020000&lt;br /&gt;
RDATE:19800406T020000&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
X-LIC-LOCATION:Europe/Madrid&lt;br /&gt;
END:VTIMEZONE&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
UID:8fbfb266-6f6b-4201-b51a-a75416640a25&lt;br /&gt;
DTSTART;VALUE=DATE:20100709&lt;br /&gt;
DURATION:PT1H&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&lt;br /&gt;
]]&gt;&amp;lt;/calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;status&gt;HTTP/1.1 200 OK&amp;lt;/status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/response&gt;&lt;br /&gt;
&amp;lt;/multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;h3&gt;CALENDAR-QUERY REPORT&lt;/h3&gt;&lt;br /&gt;
Calendar-query is other report defined in CalDAV to request calendar entries that fulfill a specified filter (entries between dates, iCalendar data with a specified value in a field and so on). In this case the same package presented before manages the XML stuff and, following the same idea, a &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/CalendarQueryReportInfo.java&quot;&gt;CalendarQueryReportInfo.java&lt;/a&gt; extension and &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/CalendarQueryReport.java&quot;&gt;CalendarQueryReport.java&lt;/a&gt; was coded. First class is the ReportInfo for this new report and the second one does the registration part.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
ReportMethod calendarQuery = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;RequestCalendarData calendarData = new RequestCalendarData();&lt;br /&gt;
&amp;#160;&amp;#160;Filter filter = new Filter(&quot;VCALENDAR&quot;);&lt;br /&gt;
&amp;#160;&amp;#160;filter.getCompFilter().add(new Filter(&quot;VEVENT&quot;));&lt;br /&gt;
&amp;#160;&amp;#160;Calendar start = Calendar.getInstance();&lt;br /&gt;
&amp;#160;&amp;#160;start.add(Calendar.MONTH, -1);&lt;br /&gt;
&amp;#160;&amp;#160;Calendar end = Calendar.getInstance();&lt;br /&gt;
&amp;#160;&amp;#160;filter.getCompFilter().get(0).setTimeRange(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;new TimeRange(start.getTime(), end.getTime()));&lt;br /&gt;
&amp;#160;&amp;#160;ReportInfo reportInfo = new CalendarQueryReportInfo(calendarData, filter);&lt;br /&gt;
&amp;#160;&amp;#160;calendarQuery = new ReportMethod(uri, reportInfo);&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(calendarQuery);&lt;br /&gt;
&amp;#160;&amp;#160;MultiStatus multiStatus = calendarQuery.getResponseBodyAsMultiStatus();&lt;br /&gt;
&amp;#160;&amp;#160;for (int i = 0; i  multiStatus.getResponses().length; i++) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;MultiStatusResponse multiRes = multiStatus.getResponses()[i];&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;String href = multiRes.getHref();&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;DavPropertySet propSet = multiRes.getProperties(DavServletResponse.SC_OK);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;DavProperty prop = (DavProperty) propSet.get(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;CalDavConstants.CALDAV_XML_CALENDAR_DATA, CalDavConstants.CALDAV_NAMESPACE);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;System.err.println(&quot;HREF: &quot; + href);&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;CalendarBuilder builder = new CalendarBuilder();&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;net.fortuna.ical4j.model.Calendar c = builder.build(&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;new StringReader(prop.getValue()));&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;System.err.println(&quot;calendar-data: &quot; + c.toString());&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (calendarQuery != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;calendarQuery.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
The sample report performs a query with a filter that returns all the events in a month. In this case all calendar data is requested.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /calendar/dav/rickyepoderi@gmail.com/events/ HTTP/1.1&lt;br /&gt;
Depth: 1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 342&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-query xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;C:filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:time-range end=&quot;20100709T101456Z&quot; start=&quot;20100609T101456Z&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/C:filter&gt;&lt;br /&gt;
&amp;lt;/C:calendar-query&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi-Status&lt;br /&gt;
DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;br /&gt;
Content-Type: application/xml; charset=UTF-8&lt;br /&gt;
Date: Fri, 09 Jul 2010 10:14:57 GMT&lt;br /&gt;
Expires: Fri, 09 Jul 2010 10:14:57 GMT&lt;br /&gt;
Cache-Control: private, max-age=0&lt;br /&gt;
X-Content-Type-Options: nosniff&lt;br /&gt;
X-Frame-Options: SAMEORIGIN&lt;br /&gt;
X-XSS-Protection: 1; mode=block&lt;br /&gt;
Content-Length: 993&lt;br /&gt;
Server: GSE&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;/calendar/dav/rickyepoderi%40gmail.com/events/3fb8047e-4a51-4207-90a9-629e8bed1866.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&lt;br /&gt;
PRODID:-//Google Inc//Google Calendar 70.9054//EN&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
CALSCALE:GREGORIAN&lt;br /&gt;
X-WR-CALNAME:Ricardo Martin&lt;br /&gt;
X-WR-TIMEZONE:Europe/Paris&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
DTSTART:20100708T220000Z&lt;br /&gt;
DTEND:20100708T230000Z&lt;br /&gt;
DTSTAMP:20100709T101456Z&lt;br /&gt;
UID:3fb8047e-4a51-4207-90a9-629e8bed1866&lt;br /&gt;
CREATED:20100709T101456Z&lt;br /&gt;
DESCRIPTION:&lt;br /&gt;
LAST-MODIFIED:20100709T101456Z&lt;br /&gt;
LOCATION:&lt;br /&gt;
SEQUENCE:0&lt;br /&gt;
STATUS:CONFIRMED&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
RANSP:OPAQUE&lt;br /&gt;
BEGIN:VALARM&lt;br /&gt;
ACTION:DISPLAY&lt;br /&gt;
DESCRIPTION:This is an event reminder&lt;br /&gt;
TRIGGER:-P0DT0H10M0S&lt;br /&gt;
END:VALARM&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:response&gt;&lt;br /&gt;
&amp;lt;/D:multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Yahoo! Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/ HTTP/1.1&lt;br /&gt;
Depth: 1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 342&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXXXXXX&lt;br /&gt;
Host: caldav.calendar.yahoo.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-query xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;C:filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:time-range end=&quot;20100709T102151Z&quot; start=&quot;20100609T102151Z&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/C:filter&gt;&lt;br /&gt;
&amp;lt;/C:calendar-query&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi Status&lt;br /&gt;
Date: Fri, 09 Jul 2010 10:21:52 GMT&lt;br /&gt;
P3P: policyref=&quot;http://info.yahoo.com/w3c/p3p.xml&quot;, CP=&quot;CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV&quot;&lt;br /&gt;
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule&lt;br /&gt;
DAV: version-control, addressbook, extended-mkcol, calendar-proxy&lt;br /&gt;
DAV: calendarserver-principal-property-search&lt;br /&gt;
Content-Type: text/xml; charset=utf-8&lt;br /&gt;
X-Cache: MISS from store138.c104.cal.gq1.yahoo.com&lt;br /&gt;
Age: 0&lt;br /&gt;
Transfer-Encoding: chunked&lt;br /&gt;
Connection: keep-alive&lt;br /&gt;
Server: YTS/1.17.23&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;/dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/00584253-ab0d-41c0-b1fe-ee391eab6f78.ics&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;[\n]&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;BEGIN:VCALENDAR&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
PRODID:Zimbra-Calendar-Provider&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
UID:00584253-ab0d-41c0-b1fe-ee391eab6f78&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
DTSTART;VALUE=DATE:20100709&lt;br /&gt;
DURATION:PT1H&lt;br /&gt;
STATUS:CONFIRMED&lt;br /&gt;
CLASS:PUBLIC&lt;br /&gt;
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE&lt;br /&gt;
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY&lt;br /&gt;
TRANSP:OPAQUE&lt;br /&gt;
X-MICROSOFT-DISALLOW-COUNTER:TRUE&lt;br /&gt;
DTSTAMP:20100709T102149Z&lt;br /&gt;
SEQUENCE:0&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&amp;lt;/C:calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:response&gt;&lt;br /&gt;
&amp;lt;/D:multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Calendar Server:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;REPORT /calendars/users/admin/calendar/ HTTP/1.1&lt;br /&gt;
Depth: 1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 342&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Digest username=&quot;admin&quot;, realm=&quot;Test Realm&quot;, nonce=&quot;11647135610574514491121002269&quot;, uri=&quot;/calendars/users/admin/calendar/&quot;, response=&quot;9fc57dc0becf313811f762083aaefe7c&quot;, algorithm=&quot;md5&quot;&lt;br /&gt;
Host: localhost:8008&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;C:calendar-query xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-data/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;C:filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VCALENDAR&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:comp-filter name=&quot;VEVENT&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:time-range end=&quot;20100709T103056Z&quot; start=&quot;20100609T103056Z&quot;/&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/C:comp-filter&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/C:filter&gt;&lt;br /&gt;
&amp;lt;/C:calendar-query&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi-Status&lt;br /&gt;
Content-Length: 8512&lt;br /&gt;
Accept-Ranges: bytes&lt;br /&gt;
Server: CalendarServer/trunk(r5842M) Twisted/10.0.0 TwistedWeb/9.0.0+r5842&lt;br /&gt;
Last-Modified: Fri, 09 Jul 2010 10:30:55 GMT&lt;br /&gt;
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-availability, inbox-availability, calendar-proxy, calendarserver-private-events, calendarserver-private-comments, calendarserver-sharing, addressbook, calendarserver-principal-property-search&lt;br /&gt;
ETag: &quot;285DD2-1000-4C36FA5F&quot;&lt;br /&gt;
Date: Fri, 09 Jul 2010 10:30:56 GMT&lt;br /&gt;
Content-Type: text/xml[\r][\n]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;&quot;?xml version='1.0' encoding='UTF-8'?&gt;&lt;br /&gt;
&amp;lt;multistatus xmlns='DAV:'&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;href&gt;/calendars/users/admin/calendar/2b1785aa-0893-49b6-be52-ede2290bdc4a.ics&amp;lt;/href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;calendar-data xmlns='urn:ietf:params:xml:ns:caldav'&gt;&amp;lt;![CDATA[BEGIN:VCALENDAR&lt;br /&gt;
VERSION:2.0&lt;br /&gt;
CALSCALE:GREGORIAN&lt;br /&gt;
PRODID:-//Ben Fortuna//iCal4j 1.0//EN&lt;br /&gt;
BEGIN:VTIMEZONE&lt;br /&gt;
TZID:Europe/Madrid&lt;br /&gt;
TZURL:http://tzurl.org/zoneinfo/Europe/Madrid&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19961027T030000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19010101T011444&lt;br /&gt;
RDATE:19010101T011444&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
TZOFFSETFROM:-001444&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19171007T010000&lt;br /&gt;
RDATE:19171007T010000&lt;br /&gt;
RDATE:19181007T010000&lt;br /&gt;
RDATE:19191007T010000&lt;br /&gt;
RDATE:19241005T010000&lt;br /&gt;
RDATE:19261003T010000&lt;br /&gt;
RDATE:19271002T010000&lt;br /&gt;
RDATE:19281007T010000&lt;br /&gt;
RDATE:19291006T010000&lt;br /&gt;
RDATE:19371003T010000&lt;br /&gt;
RDATE:19381002T010000&lt;br /&gt;
RDATE:19391008T010000&lt;br /&gt;
TZNAME:WET&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0000&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19460930T000000&lt;br /&gt;
RDATE:19460930T000000&lt;br /&gt;
RDATE:19490930T010000&lt;br /&gt;
RDATE:19741006T010000&lt;br /&gt;
RDATE:19751005T010000&lt;br /&gt;
RDATE:19760926T010000&lt;br /&gt;
RDATE:19770925T010000&lt;br /&gt;
RDATE:19781001T010000&lt;br /&gt;
RDATE:19790930T030000&lt;br /&gt;
RDATE:19800928T030000&lt;br /&gt;
RDATE:19810927T030000&lt;br /&gt;
RDATE:19820926T030000&lt;br /&gt;
RDATE:19830925T030000&lt;br /&gt;
RDATE:19840930T030000&lt;br /&gt;
RDATE:19850929T030000&lt;br /&gt;
RDATE:19860928T030000&lt;br /&gt;
RDATE:19870927T030000&lt;br /&gt;
RDATE:19880925T030000&lt;br /&gt;
RDATE:19890924T030000&lt;br /&gt;
RDATE:19900930T030000&lt;br /&gt;
RDATE:19910929T030000&lt;br /&gt;
RDATE:19920927T030000&lt;br /&gt;
RDATE:19930926T030000&lt;br /&gt;
RDATE:19940925T030000&lt;br /&gt;
RDATE:19950924T030000&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:STANDARD&lt;br /&gt;
DTSTART:19790101T000000&lt;br /&gt;
RDATE:19790101T000000&lt;br /&gt;
TZNAME:CET&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:STANDARD&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19810329T020000&lt;br /&gt;
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19170506T000000&lt;br /&gt;
RDATE:19170506T000000&lt;br /&gt;
RDATE:19180416T000000&lt;br /&gt;
RDATE:19190406T000000&lt;br /&gt;
RDATE:19240417T000000&lt;br /&gt;
RDATE:19260418T000000&lt;br /&gt;
RDATE:19270410T000000&lt;br /&gt;
RDATE:19280415T000000&lt;br /&gt;
RDATE:19290421T000000&lt;br /&gt;
RDATE:19370523T000000&lt;br /&gt;
RDATE:19380323T000000&lt;br /&gt;
RDATE:19390416T000000&lt;br /&gt;
RDATE:19400317T000000&lt;br /&gt;
TZNAME:WEST&lt;br /&gt;
TZOFFSETFROM:+0000&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19420503T000000&lt;br /&gt;
RDATE:19420503T000000&lt;br /&gt;
RDATE:19430418T000000&lt;br /&gt;
RDATE:19440416T000000&lt;br /&gt;
RDATE:19450415T000000&lt;br /&gt;
RDATE:19460414T000000&lt;br /&gt;
TZNAME:WEMT&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19420902T010000&lt;br /&gt;
RDATE:19420902T010000&lt;br /&gt;
RDATE:19431004T010000&lt;br /&gt;
RDATE:19441011T010000&lt;br /&gt;
RDATE:19450930T020000&lt;br /&gt;
TZNAME:WEST&lt;br /&gt;
TZOFFSETFROM:+0200&lt;br /&gt;
TZOFFSETTO:+0100&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
BEGIN:DAYLIGHT&lt;br /&gt;
DTSTART:19490430T230000&lt;br /&gt;
RDATE:19490430T230000&lt;br /&gt;
RDATE:19740413T230000&lt;br /&gt;
RDATE:19750419T230000&lt;br /&gt;
RDATE:19760327T230000&lt;br /&gt;
RDATE:19770402T230000&lt;br /&gt;
RDATE:19780402T230000&lt;br /&gt;
RDATE:19790401T020000&lt;br /&gt;
RDATE:19800406T020000&lt;br /&gt;
TZNAME:CEST&lt;br /&gt;
TZOFFSETFROM:+0100&lt;br /&gt;
TZOFFSETTO:+0200&lt;br /&gt;
END:DAYLIGHT&lt;br /&gt;
X-LIC-LOCATION:Europe/Madrid&lt;br /&gt;
END:VTIMEZONE&lt;br /&gt;
BEGIN:VEVENT&lt;br /&gt;
UID:2b1785aa-0893-49b6-be52-ede2290bdc4a&lt;br /&gt;
DTSTART;VALUE=DATE:20100709&lt;br /&gt;
DURATION:PT1H&lt;br /&gt;
DTSTAMP:20100709T103055Z&lt;br /&gt;
SUMMARY:test&lt;br /&gt;
END:VEVENT&lt;br /&gt;
END:VCALENDAR&lt;br /&gt;
]]&gt;&amp;lt;/calendar-data&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;status&gt;HTTP/1.1 200 OK&amp;lt;/status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/response&gt;&lt;br /&gt;
&amp;lt;/multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;h3&gt;DELETE&lt;/h3&gt;&lt;br /&gt;
Finally a usual HTTP DELETE method is sent. With it the resource previously created is removed. As in the PUT method the three servers act more or less the same way and only google calendar trace is shown.&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
DeleteMethod delete = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;delete = new DeleteMethod(createdHref);&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(delete);&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (delete != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;delete.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
A DELETE method returns &lt;em&gt;No Content&lt;/em&gt; (HTTP code 204) on success.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;DELETE /calendar/dav/rickyepoderi@gmail.com/events/cf3bdc67-df96-46bf-a0a8-86cd72133097.ics HTTP/1.1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 0Authorization: Basic XXXXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 204 No Content&lt;br /&gt;
DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;br /&gt;
Date: Fri, 09 Jul 2010 10:49:33 GMT&lt;br /&gt;
Server: GSE&lt;/blockquote&gt;&lt;br /&gt;
&lt;br /&gt;
This little &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/uploads/IntroducingCalDAVPartII/Main.java&quot;&gt;Main.java&lt;/a&gt; is the client class I have used to obtain the communication traces presented in this entries. And, as a conclusion, jackrabbit-webdav and iCal4j have done a good job. Although caldav4j is a more high level CalDAV API and I am sure it can produce faster results, the chosen libraries let us see some very interesting communication and implementation details. I hope the goal of this two-part series has been achieved, getting some little knowledge about CalDAV access programming.&lt;br /&gt;
&lt;br /&gt;
Have a nice weekend!</description>
	<pubDate>sáb, 24 jul 2010 09:22:00 +0000</pubDate>
	<author>nospam@example.com (rickyepoderi)</author>
</item>
<item>
	<title>Ricky's Hodgepodge: Introducing CalDAV (Part I)</title>
	<guid>http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-guid.html</guid>
	<link>http://blogs.nologin.es/rickyepoderi/index.php?/archives/14-Introducing-CalDAV-Part-I.html</link>
	<description>As in other previous entries the topic of this one is a technology that has been surrounding me several times but never a project finally came out. CalDAV is a standard protocol based on WebDAV (based on HTTP) to access, manage, and share calendaring and scheduling information. It is used by the majority of internet calendar providers like google or yahoo! and &lt;a href=&quot;http://caldav.calconnect.org/implementations/servers.html&quot;&gt;many commercial and open source calendar server applications&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
As you see around CalDAV there are some concepts:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/WebDAV&quot;&gt;WebDAV (Web-based Distributed Authoring and Versioning)&lt;/a&gt; is an extension to HTTP that allows users to edit and manage files collaboratively on remote web servers. &lt;a href=&quot;http://tools.ietf.org/html/rfc4918&quot;&gt;RFC-4918&lt;/a&gt; defines the WebDAV extensions.&lt;br /&gt;
&lt;br /&gt;
In a previous entry &lt;a href=&quot;http://blogs.nologin.es/rickyepoderi/index.php?/archives/11-Making-a-SUDOKU-using-CGI.html&quot;&gt;a simple CGI was used to solve a SUDOKU&lt;/a&gt; and there I explained the GET and POST HTTP methods. &lt;a href=&quot;http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods&quot;&gt;HyperText Transfer Protocol (HTTP) has another methods&lt;/a&gt; like PUT (uploads a specified resource) or DELETE (deletes a web resource). WebDAV extends HTTP with more of them like PROPFIND (retrieves properties of resources), MKCOL (creates a new WebDAV collection), COPY and MOVE (copies and moves one resource from one URI to another) or LOCK and UNLOCK (creates and removes a shared or exclusive lock over a resource). Several RFCs have improved WebDAV with even more extensions like &lt;a href=&quot;http://tools.ietf.org/html/rfc3253&quot;&gt;RFC-3253&lt;/a&gt;, versioning extensions to the HTTP/1.1 protocol (CHECKOUT, CHECKIN,...) and many others.&lt;br /&gt;
&lt;br /&gt;
WebDAV RFC chooses XML as the language to use over HTTP communication and there are &lt;a href=&quot;http://en.wikipedia.org/wiki/Document_Type_Definition&quot;&gt;DTDs (Document Type Definition)&lt;/a&gt; to define the XML data exchanged in every method. Subsequent extensions (CalDAV too) do exactly the same in their respective RFCs.&lt;br /&gt;
&lt;br /&gt;
Commonly speaking WebDAV protocol lets people manage collections of files stored in the internet. And many internet providers use it to provide virtual disk services to their customers.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/CalDAV&quot;&gt;CalDAV (Calendaring Extensions to WebDAV)&lt;/a&gt; is just another extension over WebDAV (&lt;a href=&quot;http://tools.ietf.org/html/rfc4791&quot;&gt;RFC-4791&lt;/a&gt;) to specify a standard way of accessing, managing and sharing calendaring data based on the iCalendar format.  In summary it is a protocol to manage typical calendar resources (calendars, events, to-dos,...) as internet WebDAV collections.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/ICalendar&quot;&gt;iCalendar (Internet Calendaring and Scheduling Core Object Specification)&lt;/a&gt; is a data format (&lt;a href=&quot;http://tools.ietf.org/html/rfc5545&quot;&gt;RFC-5545&lt;/a&gt; replaced &lt;a href=&quot;http://tools.ietf.org/html/rfc2445&quot;&gt;RFC-2445&lt;/a&gt; and now defines the standard) for representing and exchanging calendaring and scheduling information such as events, to-dos, journal entries, and free/busy information, independent of any particular calendar service or protocol. So, while CalDAV is the protocol to access and manage calendar resources, iCalendar is the format of the data stored in and retrieved from the server. Other way of saying the same, a calendar server manages collections of iCalendar formatted resources accessed by users via CalDAV protocol.&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
After it is clear what CalDAV means the next question to answer would be what is the current status of the development libraries about this protocol (in java of course). The little investigation I have done (very scattered I admit) gives us some links:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;CalDAV. The only library (I found) written in Java which directly implements CalDAV protocol is &lt;a href=&quot;http://code.google.com/p/caldav4j/&quot;&gt;caldav4j&lt;/a&gt;. caldav4j is a project hosted by google which extends &lt;a href=&quot;http://jakarta.apache.org/slide/&quot;&gt;Apache Slide&lt;/a&gt; WebDAV protocol library and uses iCal4j for iCalendar data processing. The main problem with caldav4j is that Apache abandoned Slide in 2007 and therefore it is based on a deprecated library (now Apache advises to consider Jackrabbit project instead).&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;WebDAV. &lt;a href=&quot;http://jackrabbit.apache.org/&quot;&gt;Apache Jackrabbit&lt;/a&gt; is a fully conforming implementation of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Content_repository_API_for_Java&quot;&gt;Content Repository for Java Technology API or JCR&lt;/a&gt;. Not going deep into JCR this API grew out of the needs of content management systems, which require storage of documents and other binary objects with associated metadata. Any JCR needs WebDAV to provide access to the repository, so &lt;a href=&quot;http://jackrabbit.apache.org/jackrabbit-webdav-library.html&quot;&gt;Jackrabbit gives a WebDAV protocol library&lt;/a&gt; which can be downloaded separately from the rest of the project &lt;a href=&quot;https://repository.apache.org/content/repositories/releases/org/apache/jackrabbit/jackrabbit-webdav/&quot;&gt;here&lt;/a&gt;. But jackrabbit-webdav is not very well documented and any extension needs some study of the library source code (welcome to open source!).&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;iCalendar. For iCalendar file format there is a well old known project called &lt;a href=&quot;http://wiki.modularity.net.au/ical4j/index.php?title=Main_Page&quot;&gt;iCal4j&lt;/a&gt;. iCal4j is a Java API that provides support for the iCalendar specification including a Parser, Object Model and Generator for iCalendar data streams.&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
Although caldav4j is a very good option (and I am sure this project will slowly move from Slide to Jackrabbit library) I preferred to use jackrabbit-webdav directly. On one hand I wanted to understand CalDAV protocol (and using a high level API that hides all below communication was a bad idea) and, on the other, it is always better to develop with the correct library (and it is the obvious future option even for caldav4j). Finally I decided to code a little Java test class with the following features:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The class will use iCal4j and jackrabbit-webdav libraries. Take into account that WebDAV part also uses &lt;a href=&quot;http://hc.apache.org/httpclient-3.x/&quot;&gt;Apache's HttpClient library&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;The resulting Java program will be tested against three different CalDAV servers:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.google.com/calendar&quot;&gt;Google calendar&lt;/a&gt;. Google calendar gives CalDAV access for long time ago and the online help explains &lt;a href=&quot;http://www.google.com/support/calendar/bin/answer.py?answer=99358&quot;&gt;how to configure some CalDAV clients&lt;/a&gt; (Apple iCal and Mozilla Lightning/Sunbird). In my case my CalDAV URL is the following:&lt;br /&gt;
       &lt;strong&gt;https://www.google.com/calendar/dav/rickyepoderi@gmail.com/events/&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://calendar.yahoo.com&quot;&gt;Yahoo! Calendar&lt;/a&gt; (which is based on Zimbra). Same as google Yahoo! help provides &lt;a href=&quot;http://help.yahoo.com/l/us/yahoo/calendar/yahoocalendar/sync/sync-05.html&quot;&gt;some information about how to configure Mozilla client&lt;/a&gt;. Using that info my Yahoo! calendar is in the following CalDAV URL:&lt;br /&gt;
       &lt;strong&gt;https://caldav.calendar.yahoo.com/dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;&lt;a href=&quot;http://trac.calendarserver.org/&quot;&gt;Calendar Server&lt;/a&gt;. The open source porting for Apple Darwin (iCal) Calendar Server. I set Calendar Server up following its &lt;a href=&quot;http://trac.calendarserver.org/wiki/QuickStart&quot;&gt;quickstart instructions&lt;/a&gt; and, as in the other two servers, there is &lt;a href=&quot;http://trac.calendarserver.org/wiki/CalendarClients&quot;&gt;information about how to configure some CalDAV clients&lt;/a&gt;. In the default installation there is an admin user with the following CalDAV URL:&lt;br /&gt;
       &lt;strong&gt;http://localhost:8008/calendars/users/admin/calendar/&lt;/strong&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;li&gt;The Java program will perform the following steps:&lt;br /&gt;
&lt;br /&gt;
    &lt;ul&gt;&lt;li&gt;Execute an OPTIONS method. This answers if CalDAV is supported.&lt;br /&gt;
    &lt;li&gt;Send a PROPFIND to the root calendar URI of a user. This returns some standard output with calendar information.&lt;br /&gt;
    &lt;li&gt;Create a new VEVENT for today using PUT.&lt;br /&gt;
    &lt;li&gt;Recover the VEVENT using calendar-multiget REPORT.&lt;br /&gt;
    &lt;li&gt;Query for the event using calendar-query REPORT.&lt;br /&gt;
    &lt;li&gt;Delete the event.&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
In this first entry only the first two methods (OPTIONS and PROPFIND) are going to be presented. The rest of them (the ones that really need extensions) will appear in the next post.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;OPTIONS&lt;/h3&gt;&lt;br /&gt;
The idea is quite simple, performing a direct HTTP OPTIONS method to the CalDAV URI via Jackrabbit. By default OPTIONS method returns the list of methods supported by the specified URI (in the &lt;em&gt;Allow&lt;/em&gt; header). But any CalDAV server must include &lt;em&gt;calendar-access&lt;/em&gt; as a field in the &lt;em&gt;DAV&lt;/em&gt; response header from an OPTIONS request on any resource that supports any calendar properties, reports, or methods. A value of &lt;em&gt;calendar-access&lt;/em&gt; in the &lt;em&gt;DAV&lt;/em&gt; header indicates that the server supports all MUST level requirements and REQUIRED features specified by the CalDAV RFC.&lt;br /&gt;
&lt;br /&gt;
Here it is the Java code:&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
OptionsMethod options = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;options = new OptionsMethod(uri);&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(options);&lt;br /&gt;
&amp;#160;&amp;#160;System.err.println(options.getStatusLine());&lt;br /&gt;
&amp;#160;&amp;#160;for (int i = 0; i  options.getResponseHeaders().length; i++) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;System.err.println(options.getResponseHeaders()[i].getName() + &quot;: &quot;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;+ options.getResponseHeaders()[i].getValue());&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (options != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;options.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
If you check the responses for every server some providers support more DAV extensions than others. In this entry I am just checking &lt;em&gt;calendar-access&lt;/em&gt; but, of course, there are extensions over CalDAV to support more sophisticated features. &lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;OPTIONS /calendar/dav/lrickyepoderi@gmail.com/events/ HTTP/1.1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Authorization: Basic XXXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 200 OK&lt;br /&gt;
&lt;strong&gt;DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;/strong&gt;&lt;br /&gt;
Allow: OPTIONS, PROPFIND, HEAD, GET, REPORT, PROPPATCH, PUT, DELETE, POST&lt;br /&gt;
Content-Type: application/xml; charset=UTF-8&lt;br /&gt;
Date: Tue, 06 Jul 2010 14:52:17 GMT&lt;br /&gt;
Expires: Tue, 06 Jul 2010 14:52:17 GMT&lt;br /&gt;
Cache-Control: private, max-age=0&lt;br /&gt;
X-Content-Type-Options: nosniff&lt;br /&gt;
X-Frame-Options: SAMEORIGIN&lt;br /&gt;
X-XSS-Protection: 1; mode=block&lt;br /&gt;
Content-Length: 0&lt;br /&gt;
Server: GSE&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Yahoo! Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;OPTIONS /dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/ HTTP/1.1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Authorization: Basic XXXXXXXXX&lt;br /&gt;
Host: caldav.calendar.yahoo.com&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 200 OK&lt;br /&gt;
Date: Tue, 06 Jul 2010 15:09:27 GMT&lt;br /&gt;
P3P: policyref=&quot;http://info.yahoo.com/w3c/p3p.xml&quot;, CP=&quot;CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV&quot;&lt;br /&gt;
Allow: PROPPATCH, COPY, DELETE, POST, MKCALENDAR, GET, REPORT, PROPFIND, PUT&lt;br /&gt;
Allow: MOVE, UNLOCK, OPTIONS, ACL, HEAD, LOCK, MKCOL&lt;br /&gt;
&lt;strong&gt;DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;DAV: version-control, addressbook, extended-mkcol, calendar-proxy&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;DAV: calendarserver-principal-property-search&lt;/strong&gt;&lt;br /&gt;
X-Cache: MISS from store138.c104.cal.gq1.yahoo.com&lt;br /&gt;
Content-Type: text/plain; charset=utf-8&lt;br /&gt;
Age: 1&lt;br /&gt;
Transfer-Encoding: chunked&lt;br /&gt;
Connection: keep-alive&lt;br /&gt;
Server: YTS/1.17.23&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Calendar Server:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;OPTIONS /calendars/users/admin/calendar/ HTTP/1.1&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Authorization: Digest username=&quot;admin&quot;, realm=&quot;Test Realm&quot;, nonce=&quot;19089203782138543154880100606&quot;, uri=&quot;/calendars/users/admin/calendar/&quot;, response=&quot;26c3007948457e549d7564bdf558558c&quot;, algorithm=&quot;md5&quot;&lt;br /&gt;
Host: localhost:8008&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 200 OK&lt;br /&gt;
Content-Length: 0&lt;br /&gt;
Server: CalendarServer/trunk(r5842M) Twisted/10.0.0 TwistedWeb/9.0.0+r5842&lt;br /&gt;
Last-Modified: Sun, 04 Jul 2010 16:45:37 GMT&lt;br /&gt;
&lt;strong&gt;DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-availability, inbox-availability, calendar-proxy, calendarserver-private-events, calendarserver-private-comments, calendarserver-sharing, addressbook, calendarserver-principal-property-search&lt;/strong&gt;&lt;br /&gt;
ETag: &quot;285DD2-1000-4C30BAB1&quot;&lt;br /&gt;
Allow: ACL, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, TRACE, UNLOCK&lt;br /&gt;
Date: Tue, 06 Jul 2010 15:19:57 GMT&lt;/blockquote&gt;&lt;br /&gt;
&lt;h3&gt;PROPFIND&lt;/h3&gt;&lt;br /&gt;
The PROPFIND WebDAV method retrieves properties for a specified resource, in case of a CalDAV collection URI it can return an optional property &lt;em&gt;calendar-description&lt;/em&gt; and must return &lt;em&gt;calendar&lt;/em&gt; and &lt;em&gt;collection&lt;/em&gt; as &lt;em&gt;resourcetype&lt;/em&gt; property.&lt;br /&gt;
&lt;br /&gt;
The code for a PROPFIND requesting all properties with DEPTH 0 (only the collection URI) is below. The answer must be a multi-status response (a WebDAV defined XML response with HTTP code 207) with all the properties for every resource found.&lt;br /&gt;
&lt;blockquote&gt;HttpClient client = ...&lt;br /&gt;
PropFindMethod propFind = null;&lt;br /&gt;
try {&lt;br /&gt;
&amp;#160;&amp;#160;propFind = new PropFindMethod(uri,&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;DavConstants.PROPFIND_ALL_PROP, DavConstants.DEPTH_0);&lt;br /&gt;
&amp;#160;&amp;#160;client.executeMethod(propFind);&lt;br /&gt;
&amp;#160;&amp;#160;MultiStatus multiStatus = propFind.getResponseBodyAsMultiStatus();&lt;br /&gt;
} finally {&lt;br /&gt;
&amp;#160;&amp;#160;if (propFind != null) {&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;propFind.releaseConnection();&lt;br /&gt;
&amp;#160;&amp;#160;}&lt;br /&gt;
}&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Google Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;PROPFIND /calendar/dav/rickyepoderi@gmail.com/events/ HTTP/1.1&lt;br /&gt;
Depth: 0&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 90&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXX&lt;br /&gt;
Host: www.google.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:propfind xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:allprop/&gt;&lt;br /&gt;
&amp;lt;/D:propfind&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi-Status&lt;br /&gt;
DAV: 1, calendar-access, calendar-schedule, calendar-proxy&lt;br /&gt;
Content-Type: application/xml; charset=UTF-8&lt;br /&gt;
Date: Tue, 06 Jul 2010 16:04:32 GMT&lt;br /&gt;
Expires: Tue, 06 Jul 2010 16:04:32 GMT&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;/calendar/dav/rickyepoderi@gmail.com/events/&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar-description xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot;&gt;rickyepoderi@gmail.com&amp;lt;/C:calendar-description&gt;&lt;/strong&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;A:calendar-color xmlns:A=&quot;http://apple.com/ns/ical/&quot;&gt;#2952A3&amp;lt;/A:calendar-color&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:getcontenttype&gt;text/calendar; component=vevent&amp;lt;/D:getcontenttype&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:displayname&gt;Ricardo Martin&amp;lt;/D:displayname&gt;&lt;br /&gt;
&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:resourcetype&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:collection /&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;C:calendar xmlns:C=&quot;urn:ietf:params:xml:ns:caldav&quot; /&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:resourcetype&gt;&lt;/strong&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;CS:getctag xmlns:CS=&quot;http://calendarserver.org/ns/&quot;&gt;63414112150&amp;lt;/CS:getctag&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;/D:response&gt;&lt;br /&gt;
&amp;lt;/D:multistatus&gt;&lt;/blockquote&gt;&lt;br /&gt;
&lt;strong&gt;Yahoo! Calendar:&lt;/strong&gt;&lt;br /&gt;
&lt;blockquote&gt;PROPFIND /dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/ HTTP/1.1&lt;br /&gt;
Depth: 0&lt;br /&gt;
User-Agent: Jakarta Commons-HttpClient/3.1&lt;br /&gt;
Content-Length: 90&lt;br /&gt;
Content-Type: text/xml; charset=UTF-8&lt;br /&gt;
Authorization: Basic XXXXXXXXX&lt;br /&gt;
Host: caldav.calendar.yahoo.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;
&amp;lt;D:propfind xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:allprop/&gt;&lt;br /&gt;
&amp;lt;/D:propfind&gt;&lt;br /&gt;
&lt;br /&gt;
HTTP/1.1 207 Multi Status&lt;br /&gt;
Date: Tue, 06 Jul 2010 15:59:20 GMT&lt;br /&gt;
P3P: policyref=&quot;http://info.yahoo.com/w3c/p3p.xml&quot;, CP=&quot;CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV&quot;&lt;br /&gt;
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule&lt;br /&gt;
DAV: version-control, addressbook, extended-mkcol, calendar-proxy&lt;br /&gt;
DAV: calendarserver-principal-property-search&lt;br /&gt;
Content-Type: text/xml; charset=utf-8&lt;br /&gt;
X-Cache: MISS from store138.c104.cal.gq1.yahoo.com&lt;br /&gt;
Age: 0&lt;br /&gt;
Transfer-Encoding: chunked&lt;br /&gt;
Connection: keep-alive&lt;br /&gt;
Server: YTS/1.17.23&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;br /&gt;
&amp;lt;D:multistatus xmlns:D=&quot;DAV:&quot;&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;lt;D:response&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:href&gt;/dav/rickyepoderi@yahoo.es/Calendar/Ricardo_Martin/&amp;lt;/D:href&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:propstat&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:status&gt;HTTP/1.1 200 OK&amp;lt;/D:status&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;D:prop&gt;&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&
