<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-578610887231886448</id><updated>2011-11-27T15:55:27.371-08:00</updated><category term='linux'/><category term='sqlmagazine'/><category term='cassandra'/><category term='virtualbox'/><category term='postgresql'/><category term='admin'/><category term='java'/><category term='flight'/><category term='glassfish'/><category term='maven'/><category term='tomcat'/><category term='cloud'/><category term='junk'/><category term='mongodb'/><category term='oracle'/><category term='databases'/><category term='gastronomia'/><category term='zabbix'/><category term='demoiselle'/><category term='jpa'/><category term='shell'/><category term='persistence'/><category term='nintendo'/><category term='jboss'/><category term='snmp'/><category term='windows'/><category term='nosql'/><category term='eclipse'/><category term='fts'/><category term='j2ee'/><category term='msdos'/><category term='backup'/><title type='text'>Agajorte: Java, Linux e Gastronomia</title><subtitle type='html'>Dicas, exemplos e dados sobre tecnologia da informação e assuntos tangenciais</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.hjort.co/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.hjort.co/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6634476023773595486</id><published>2011-11-10T06:12:00.000-08:00</published><updated>2011-11-10T06:19:00.678-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='databases'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><category scheme='http://www.blogger.com/atom/ns#' term='mongodb'/><title type='text'>NoSQL: onde, como e por quê? Cassandra e MongoDB</title><content type='html'>&lt;br /&gt;&lt;div class="separator" style="clear: both;"&gt;&lt;a href="http://3.bp.blogspot.com/-ySj591-m8CA/TrvbXNOpIDI/AAAAAAAAAb4/htYC0AHQNxM/s1600/nosql-apres-hjort.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="400" src="http://3.bp.blogspot.com/-ySj591-m8CA/TrvbXNOpIDI/AAAAAAAAAb4/htYC0AHQNxM/s400/nosql-apres-hjort.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Segue material da apresentação que fiz no dia 10/11 no &lt;a href="http://www.softwarelivre.gov.br/eventos/seminario-de-gerenciamento-de-dados-em-software-livre" target="nova"&gt;Seminário de Gerenciamento de Dados em Software Livre&lt;/a&gt; no SERPRO.&lt;/p&gt;&lt;div style="width:425px" id="__ss_10104600;"&gt;&lt;object id="__sse10104600" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nosql-ondecomoeporqu-hjort-111110074847-phpapp01&amp;stripped_title=nosql-onde-como-e-por-qu-cassandra-e-mongodb&amp;userName=hjort" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse10104600" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nosql-ondecomoeporqu-hjort-111110074847-phpapp01&amp;stripped_title=nosql-onde-como-e-por-qu-cassandra-e-mongodb&amp;userName=hjort" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/hjort" target="_blank"&gt;Rodrigo Hjort&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Visão geral sobre &lt;b&gt;bancos de dados NoSQL&lt;/b&gt; e detalhes técnicos dos modelos de dados e arquiteturas das implementações &lt;b&gt;Apache Cassandra&lt;/b&gt; e &lt;b&gt;MongoDB&lt;/b&gt;.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6634476023773595486?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6634476023773595486/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/11/nosql-onde-como-porque-cassandra.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6634476023773595486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6634476023773595486'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/11/nosql-onde-como-porque-cassandra.html' title='NoSQL: onde, como e por quê? Cassandra e MongoDB'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-ySj591-m8CA/TrvbXNOpIDI/AAAAAAAAAb4/htYC0AHQNxM/s72-c/nosql-apres-hjort.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2358830853998029826</id><published>2011-10-19T08:22:00.000-07:00</published><updated>2011-10-19T08:22:47.701-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='oracle'/><title type='text'>A Linux trick on Oracle setup</title><content type='html'>&lt;p&gt;Have you ever tried to install &lt;b&gt;Oracle Database&lt;/b&gt; on &lt;b&gt;GNU/Linux&lt;/b&gt; and faced the insufficient memory issue below?&lt;/p&gt;&lt;p&gt;&lt;b&gt;Oracle Database 10g Express Edition requires 1024 MB of swap space. This system has ??? MB of swap space.&lt;/b&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ccy7BOGvHrw/Tp7q4x9SVII/AAAAAAAAAbM/Jz4ZcOi1FaE/s1600/oracle-airplane2.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="233" width="400" src="http://2.bp.blogspot.com/-ccy7BOGvHrw/Tp7q4x9SVII/AAAAAAAAAbM/Jz4ZcOi1FaE/s400/oracle-airplane2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Well, I've just been caught by that when attempting to set it up on a virtual machine.&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# dpkg -i oracle-xe-universal_10.2.0.1-1.1_i386.deb&lt;br /&gt;(Reading database ... 125364 files and directories currently installed.)&lt;br /&gt;Unpacking oracle-xe-universal (from oracle-xe-universal_10.2.0.1-1.1_i386.deb) ...&lt;br /&gt;This system does not meet the minimum requirements for swap space.  Based on &lt;br /&gt;the amount of physical memory available on the system, Oracle Database 10g &lt;br /&gt;Express Edition requires 1024 MB of swap space. This system has 1019 MB &lt;br /&gt;of swap space.  Configure more swap space on the system and retry the installation.&lt;br /&gt;dpkg: error processing oracle-xe-universal_10.2.0.1-1.1_i386.deb (--install):&lt;br /&gt; subprocess new pre-installation script returned error exit status 1&lt;br /&gt;Errors were encountered while processing:&lt;br /&gt; oracle-xe-universal_10.2.0.1-1.1_i386.deb&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Fortunately a true Operating System can handle it seamlessly! Here are the steps I followed.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/--dJ1I16vsoE/Tp7q42L6RwI/AAAAAAAAAbY/q-G3B7yVST4/s1600/powered-linux2b.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="200" src="http://2.bp.blogspot.com/--dJ1I16vsoE/Tp7q42L6RwI/AAAAAAAAAbY/q-G3B7yVST4/s400/powered-linux2b.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Setup is claiming about just 5 megabytes... Well, let's give him it. But no more and no less! Let's create a zeroed dummy file with &lt;b&gt;dd&lt;/b&gt;:&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# dd if=/dev/zero of=5m.swp bs=1M count=5&lt;br /&gt;5+0 records in&lt;br /&gt;5+0 records out&lt;br /&gt;5242880 bytes (5.2 MB) copied, 0.0132488 s, 396 MB/s&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Here you go, an exactly 5 MB size zeroed file:&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# ls -la 5m.swp &lt;br /&gt;-rw-r--r-- 1 root root 5242880 2011-10-19 10:39 5m.swp&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Let's check out the available memory in the system using &lt;b&gt;free&lt;/b&gt;:&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# free&lt;br /&gt;             total       used       free     shared    buffers     cached&lt;br /&gt;Mem:       1026080     921612     104468          0      27036     674936&lt;br /&gt;-/+ buffers/cache:     219640     806440&lt;br /&gt;Swap:      1046524       2552    1043972&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Alright, you need it, we'll give you:&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# swapon 5m.swp&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Are you satisfied now?&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# free&lt;br /&gt;             total       used       free     shared    buffers     cached&lt;br /&gt;Mem:       1026080     921736     104344          0      27044     674936&lt;br /&gt;-/+ buffers/cache:     219756     806324&lt;br /&gt;Swap:      1051640       2552    1049088&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Let's retry running Oracle installer:&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# dpkg -i oracle-xe-universal_10.2.0.1-1.1_i386.deb&lt;br /&gt;(Reading database ... 125364 files and directories currently installed.)&lt;br /&gt;Unpacking oracle-xe-universal (from oracle-xe-universal_10.2.0.1-1.1_i386.deb) ...&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That's it! Although that ridiculous additional 5 MB swap won't be automatically available for the next reboot, we still can tune Oracle to allocate less memory than standard settings.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2358830853998029826?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2358830853998029826/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/10/linux-trick-on-oracle-setup.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2358830853998029826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2358830853998029826'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/10/linux-trick-on-oracle-setup.html' title='A Linux trick on Oracle setup'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ccy7BOGvHrw/Tp7q4x9SVII/AAAAAAAAAbM/Jz4ZcOi1FaE/s72-c/oracle-airplane2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6529464692420493933</id><published>2011-10-13T11:07:00.000-07:00</published><updated>2011-10-13T11:10:03.000-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Générer des fichiers checksum pour Maven</title><content type='html'>&lt;p&gt;Dans un répertoire Maven v2 les fichiers JAR ont l'intégrité contrôlée par des fichiers contenant des sommes MD5 et SHA1. En général ces fichiers auxiliaires sont appelés comme le nom du fichier JAR accompagnés des extensions ".md5" ou ".sha1". Par exemple, pour la librairie "jcommon-0.9.6.jar" il doit exister "jcommon-0.9.6.jar.md5" et "jcommon-0.9.6.jar.sha1".&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-9fnoMJyQCnQ/TpcobLlETlI/AAAAAAAAAbA/gl1B3TLWWiI/s1600/maven-logo.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="105" width="307" src="http://2.bp.blogspot.com/-9fnoMJyQCnQ/TpcobLlETlI/AAAAAAAAAbA/gl1B3TLWWiI/s400/maven-logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Ces ".md5" et ".sha1" ne sont que des fichiers texte avec une chaîne string correspondant à la somme de contrôle calculée à partir de l'archive. Cette somme représente une signature unique pour chaque fichier et peut garantir qu'il ne soit pas craqué ou corrompu.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-FU5EOiiR2kk/Tpcoa9DunwI/AAAAAAAAAa0/HsVpycdBFj0/s1600/security-fingerprint.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="300" src="http://3.bp.blogspot.com/-FU5EOiiR2kk/Tpcoa9DunwI/AAAAAAAAAa0/HsVpycdBFj0/s400/security-fingerprint.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Pour générer ces fichiers au moment de la livraison d'une librairie Java, ils existent des plugins Maven pour les créer automatiquement. Néanmoins, on peut avoir le cas où des librairies JAR n'aient pas ses fichiers de contrôle (par exemple, si on a créé cette partie du répo manuellement). Cette façon, lors d'une résolution de dépendance au Maven, on va avoir des notifications telles qu'au-dessous :&lt;/p&gt;&lt;b&gt;&lt;pre&gt;[WARNING] *** CHECKSUM FAILED - Checksum failed on download&lt;/pre&gt;&lt;/b&gt;&lt;p&gt;Pour illustrer ce soucis, voici un exemple d'un arbre partiel au Maven :&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;|-- jfree-former&lt;br /&gt;|   |-- jcommon&lt;br /&gt;|   |   `-- 0.9.6&lt;br /&gt;|   |       |-- jcommon-0.9.6.jar&lt;br /&gt;|   |       `-- jcommon-0.9.6.pom&lt;br /&gt;|   `-- jfreechart&lt;br /&gt;|       `-- 0.9.21&lt;br /&gt;|           |-- jfreechart-0.9.21.jar&lt;br /&gt;|           `-- jfreechart-0.9.21.pom&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Il faut d'abord créer un script Shell appelée &lt;b&gt;checksum.sh&lt;/b&gt; avec le contenu ci-dessous :&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;if [ $# -ne 2 ]&lt;br /&gt;then&lt;br /&gt;	echo "Usage : checksum [md5|sha1] &amp;lt;file-name&amp;gt;"&lt;br /&gt;	echo "Sample: checksum sha1 /tmp/dir/myfile.jar"&lt;br /&gt;	exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;format=$1&lt;br /&gt;file="$2"&lt;br /&gt;&lt;br /&gt;if [ ! -f $file ]&lt;br /&gt;then&lt;br /&gt;	echo "File not found: $file"&lt;br /&gt;	exit 2&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;if [ "$format" == "md5" -o "$format" == "sha1" ]&lt;br /&gt;then&lt;br /&gt;	${format}sum "$file" | cut -d' ' -f1 | tr -d "\n" &amp;gt; "$file.$format"&lt;br /&gt;else&lt;br /&gt;	echo "Please choose a format: md5 or sha1"&lt;br /&gt;	exit 2&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;echo "Created checksum file $file.$format"&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Ensuite, on doit créer un autre script nommé &lt;b&gt;generate-checksums.sh&lt;/b&gt; contenant ces lignes :&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;EXTENSIONS="jar pom"&lt;br /&gt;ALGORITHMS="sha1 md5"&lt;br /&gt;&lt;br /&gt;PROGDIR=`dirname $0`&lt;br /&gt;export PATH="$PATH:$PROGDIR"&lt;br /&gt;&lt;br /&gt;for ext in $EXTENSIONS&lt;br /&gt;do&lt;br /&gt;	for alg in $ALGORITHMS&lt;br /&gt;	do&lt;br /&gt;		find -type f -name "*.$ext" -exec checksum.sh $alg {} \;&lt;br /&gt;	done&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;N'oubliez pas de donner des permissions d'exécution à ses fichiers .sh, en roulant le commande &lt;b&gt;chmod -x *.sh&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Maintenant, il faut seulement aller au répertoire désiré et ensuite exécuter le script &lt;b&gt;generate-checksums.sh&lt;/b&gt;. Voyez :&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ cd /var/maven/repo/&lt;br /&gt;&lt;br /&gt;$ /home/user/scripts/generate-checksums.sh&lt;br /&gt;Created checksum file ./jfree-former/jcommon/0.9.6/jcommon-0.9.6.jar.sha1&lt;br /&gt;Created checksum file ./jfree-former/jfreechart/0.9.21/jfreechart-0.9.21.jar.sha1&lt;br /&gt;Created checksum file ./jfree-former/jcommon/0.9.6/jcommon-0.9.6.jar.md5&lt;br /&gt;Created checksum file ./jfree-former/jfreechart/0.9.21/jfreechart-0.9.21.jar.md5&lt;br /&gt;Created checksum file ./jfree-former/jcommon/0.9.6/jcommon-0.9.6.pom.sha1&lt;br /&gt;Created checksum file ./jfree-former/jfreechart/0.9.21/jfreechart-0.9.21.pom.sha1&lt;br /&gt;Created checksum file ./jfree-former/jcommon/0.9.6/jcommon-0.9.6.pom.md5&lt;br /&gt;Created checksum file ./jfree-former/jfreechart/0.9.21/jfreechart-0.9.21.pom.md5&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Et voici le résultat pour le cas d'exemple :&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;|-- jfree-former&lt;br /&gt;|   |-- jcommon&lt;br /&gt;|   |   `-- 0.9.6&lt;br /&gt;|   |       |-- jcommon-0.9.6.jar&lt;br /&gt;|   |       |-- jcommon-0.9.6.jar.md5&lt;br /&gt;|   |       |-- jcommon-0.9.6.jar.sha1&lt;br /&gt;|   |       |-- jcommon-0.9.6.pom&lt;br /&gt;|   |       |-- jcommon-0.9.6.pom.md5&lt;br /&gt;|   |       `-- jcommon-0.9.6.pom.sha1&lt;br /&gt;|   `-- jfreechart&lt;br /&gt;|       `-- 0.9.21&lt;br /&gt;|           |-- jfreechart-0.9.21.jar&lt;br /&gt;|           |-- jfreechart-0.9.21.jar.md5&lt;br /&gt;|           |-- jfreechart-0.9.21.jar.sha1&lt;br /&gt;|           |-- jfreechart-0.9.21.pom&lt;br /&gt;|           |-- jfreechart-0.9.21.pom.md5&lt;br /&gt;|           `-- jfreechart-0.9.21.pom.sha1&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Voilà ! Désormais votre répertoire Maven contient des informations de vérification pour les fichiers et la résolution de dépendances ne lancera plus le message "CHECKSUM FAILED".&lt;/p&gt;&lt;p&gt;Si vous voulez, le code source complet peut être obtenu dans cette adresse : &lt;a href="https://gitorious.org/shell-scripts/checksum" target="new"&gt;https://gitorious.org/shell-scripts/checksum&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6529464692420493933?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6529464692420493933/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/10/generer-des-fichiers-checksum-pour.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6529464692420493933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6529464692420493933'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/10/generer-des-fichiers-checksum-pour.html' title='Générer des fichiers checksum pour Maven'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-9fnoMJyQCnQ/TpcobLlETlI/AAAAAAAAAbA/gl1B3TLWWiI/s72-c/maven-logo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6892222031194940548</id><published>2011-10-04T07:32:00.000-07:00</published><updated>2011-10-04T07:43:23.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='fts'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Mantendo atualizado o índice FTS no PostgreSQL</title><content type='html'>&lt;br /&gt;&lt;br /&gt;Dando sequência ao post anterior &lt;a href="http://www.hjort.co/2011/07/full-text-search-em-portugues-no.html" target="new"&gt;"Full Text Search em português no PostgreSQL"&lt;/a&gt;, veremos como manter atualizado o índice de busca textual, particularmente no caso de os dados da tabela sofrerem muitas atualizações (i.e., inclusões e modificações).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-J2AMj0fS3OE/TosX6vT41kI/AAAAAAAAAas/sGgyNCKsKt8/s1600/Kleer-Fax-44908-HiTech-Deluxe-Ring-Book-Index-Divider2b.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="335" src="http://4.bp.blogspot.com/-J2AMj0fS3OE/TosX6vT41kI/AAAAAAAAAas/sGgyNCKsKt8/s400/Kleer-Fax-44908-HiTech-Deluxe-Ring-Book-Index-Divider2b.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Só para relembrar, o diagrama a seguir ilustra o funcionamento do mecanismo de &lt;b&gt;Full Text Search no PostgreSQL&lt;/b&gt;, em que fazem parte processos como parser, normalizador e indexador:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-YPNiQf_KukA/TosX6SVMdEI/AAAAAAAAAac/gYwcEFv_v08/s1600/pg-fts-diag.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="292" width="400" src="http://3.bp.blogspot.com/-YPNiQf_KukA/TosX6SVMdEI/AAAAAAAAAac/gYwcEFv_v08/s400/pg-fts-diag.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Para exemplificar o problema apresentado no início desse post, considere que a tabela MUNICIPIOS esteja devidamente populada, tendo a coluna de suporte para a busca textual criada e o índice do tipo GIN (ou GiST) associado. Sendo assim, podemos fazer consultas SQL desse tipo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;SELECT nome, uf FROM municipios&lt;br /&gt;WHERE busca @@ plainto_tsquery(simples('agua lindoia'));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Veja o resultado:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;curso=# SELECT nome, uf FROM municipios&lt;br /&gt;curso-# WHERE busca @@ plainto_tsquery(simples('agua lindoia'))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nome&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | uf &lt;br /&gt;------------------+----&lt;br /&gt;&amp;nbsp;Águas de Lindóia | SP&lt;br /&gt;(1 registro)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;O que acontece agora se incluirmos um novo registro na tabela? Veja:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;INSERT INTO municipios (codigo, nome, uf)&lt;br /&gt;VALUES (100, 'Águas de Lindóia do Sul', 'RS');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ao executarmos a busca anterior, o município recém-incluído não aparecerá... Isso porque a coluna de suporte à busca não foi atualizada. Veja o conteúdo dela:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;curso=# SELECT nome, uf, busca FROM municipios WHERE codigo = 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nome&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | uf | busca &lt;br /&gt;-------------------------+----+-------&lt;br /&gt;&amp;nbsp;Águas de Lindóia do Sul | RS | &lt;br /&gt;(1 registro)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para manter essa coluna atualizada automaticamente em operações de INSERT ou UPDATE, precisamos de um disparador (trigger). No PostgreSQL criamos uma função em linguagem procedural (geralmente em PL/pgSQL) e em seguida a associamos a um disparador.&lt;br /&gt;&lt;br /&gt;Sendo assim, crie a função de trigger com o código abaixo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;CREATE FUNCTION municipios_trigger()&lt;br /&gt;RETURNS trigger AS $$&lt;br /&gt;begin&lt;br /&gt;&amp;nbsp; new.busca := to_tsvector(simples(new.nome));&lt;br /&gt;&amp;nbsp; return new;&lt;br /&gt;end&lt;br /&gt;$$ LANGUAGE plpgsql;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ao ser chamada, ela fará com que o conteúdo da coluna "busca" seja preenchido com o texto gerado da normalização da coluna "nome".&lt;br /&gt;&lt;br /&gt;Em seguida, crie o disparador de atualização:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;CREATE TRIGGER municipios_tsupdate&lt;br /&gt;BEFORE INSERT OR UPDATE ON municipios&lt;br /&gt;FOR EACH ROW EXECUTE PROCEDURE municipios_trigger();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ou seja, antes de cada INSERT ou UPDATE na tabela, a função municipios_trigger() será invocada para preencher automaticamente a coluna "busca".&lt;br /&gt;&lt;br /&gt;Agora experimente modificar aquele registro inserido acima:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;UPDATE municipios SET uf = uf WHERE codigo = 100;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Observe como ficou o conteúdo daquela linha:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;curso=# SELECT nome, uf, busca FROM municipios WHERE codigo = 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nome&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | uf |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; busca&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;-------------------------+----+---------------------------&lt;br /&gt;&amp;nbsp;Águas de Lindóia do Sul | RS | 'agu':1 'lindo':3 'sul':5&lt;br /&gt;(1 registro)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finalmente efetue a busca textual que havia falhado:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;curso=# SELECT nome, uf FROM municipios&lt;br /&gt;curso-# WHERE busca @@ plainto_tsquery(simples('agua lindoia'));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nome&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | uf &lt;br /&gt;-------------------------+----&lt;br /&gt;&amp;nbsp;Águas de Lindóia do Sul | RS&lt;br /&gt;&amp;nbsp;Águas de Lindóia&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | SP&lt;br /&gt;(2 registros)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Tente agora fazer uma modificação no nome desse município:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;UPDATE municipios SET nome = 'Águas Quentes do Sul' WHERE codigo = 100;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;E então refaça a busca considerando o novo nome:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;curso=# SELECT codigo, nome, uf FROM municipios&lt;br /&gt;WHERE busca @@ plainto_tsquery(simples('agua quente'));&lt;br /&gt;&amp;nbsp;codigo |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nome&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | uf &lt;br /&gt;--------+----------------------+----&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 100 | Águas Quentes do Sul | RS&lt;br /&gt;(1 registro)&lt;br /&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-CKGE1JJDC7U/TosX6ulwgvI/AAAAAAAAAak/uRB2IVqUZpk/s1600/idx-pd606837b.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="206" width="400" src="http://4.bp.blogspot.com/-CKGE1JJDC7U/TosX6ulwgvI/AAAAAAAAAak/uRB2IVqUZpk/s400/idx-pd606837b.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Índice sempre up-to-date! Muito fácil, né? :D&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Referências&lt;/h2&gt;&lt;br /&gt;[1] &lt;a href="http://www.postgresql.org/docs/8.3/static/textsearch-features.html#TEXTSEARCH-UPDATE-TRIGGERS" target="_blank"&gt;PostgreSQL 8.3 Documentation - Full Text Search&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6892222031194940548?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6892222031194940548/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/10/mantendo-atualizado-o-indice-fts-no.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6892222031194940548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6892222031194940548'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/10/mantendo-atualizado-o-indice-fts-no.html' title='Mantendo atualizado o índice FTS no PostgreSQL'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-J2AMj0fS3OE/TosX6vT41kI/AAAAAAAAAas/sGgyNCKsKt8/s72-c/Kleer-Fax-44908-HiTech-Deluxe-Ring-Book-Index-Divider2b.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-471583136657177680</id><published>2011-09-08T19:59:00.000-07:00</published><updated>2011-09-09T06:43:36.789-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='nintendo'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Transferring photos to Nintendo 3DS</title><content type='html'>&amp;nbsp;&lt;a href="http://2.bp.blogspot.com/-_1mDx7mnU8w/TmmVnscIQrI/AAAAAAAAAYI/L598N5XCNfQ/s1600/n3ds-console.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5650211716689576626" src="http://2.bp.blogspot.com/-_1mDx7mnU8w/TmmVnscIQrI/AAAAAAAAAYI/L598N5XCNfQ/s400/n3ds-console.jpg" style="cursor: pointer; display: block; height: 270px; margin: 0px auto 10px; text-align: center; width: 300px;" /&gt;&lt;/a&gt;&lt;p&gt;Yesterday my daughter was playing with her &lt;span style="font-weight: bold;"&gt;Nintendo 3DS&lt;/span&gt; console and then asked me to put in there some pictures I had in the computer.&lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/-cmCuiGW_ujw/TmmWK2dhD2I/AAAAAAAAAYQ/sGzMli7pcZg/s1600/sd-card.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5650212320675172194" src="http://4.bp.blogspot.com/-cmCuiGW_ujw/TmmWK2dhD2I/AAAAAAAAAYQ/sGzMli7pcZg/s400/sd-card.jpg" style="cursor: pointer; display: block; height: 219px; margin: 0px auto 10px; text-align: center; width: 173px;" /&gt;&lt;/a&gt;&lt;p&gt;I thought that should be fairly easy, as the system is provided with a regular &lt;span style="font-weight: bold;"&gt;SD card&lt;/span&gt; and I already copied there some MP3 files which worked successfully.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Well, after connecting the SD card into my laptop, I just started browsing its folders and quickly found some named with the pattern "199NIN03" inside DCIM. They were there: files with &lt;span style="font-weight: bold;"&gt;JPG and MPO extensions&lt;/span&gt;. The latter is actually a twice-JPG, the so-called "3D picture" taken with the console's dual camera.&lt;/p&gt;&lt;p&gt;My first attempt was to create a new directory with the name I'd like and start copying JPG files in there. Unmounted the drive in Linux, put it on the console, start it and go to its photo browser application. Nothing!&lt;/p&gt;&lt;p&gt;Yes, I had previously read the f*cking manual [RTFM], but I've found nothing about transferring pictures from a computer to Nintendo 3DS. Indeed the way back is possible (i.e., to copy files from the console to a PC).&lt;/p&gt;&lt;p&gt;What do we do in these cases? We start gooooogleing! \o/&lt;/p&gt;&lt;p&gt;There were not so much entries, but this post was bulls-eye: &lt;a href="http://techforums.nintendo.com/message/33675"&gt;http://techforums.nintendo.com/message/33675&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic;"&gt;"I got my N3DS the day after its release, and I've been enjoying it except there's nothing telling me how to put pictures from a PC to the SD card. I looked around and only found a guide on putting music on my SD card. Help appreciated."&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Okey-dokey! That guy is sharing my sufferings. Look what the "expert" user answered:&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic;"&gt;"Sorry, but there isn't an easy way to transfer pictures from a PC to the 3DS, as the pictures would need to be in the exact same format, size and have all the information on them as if the 3DS had actually taken the picture.&lt;/span&gt;  &lt;span style="font-style: italic;"&gt;And it is the same as with the DSi and XL, so really the only easy work around would be to view the picture on a computer monitor and take its picture with the 3DS. ;)"&lt;/span&gt;&lt;/p&gt;&lt;p&gt;OMG, I didn't believe what I've read. To take pictures of the computer screen with Nintendo 3DS? It just can't be true, what a noob's advice!&lt;/p&gt;&lt;p&gt;Now that sounded like challenge for me! :D&lt;/p&gt;&lt;p&gt;My next step was to analyze the files taken with 3DS, as they were perfectly visible in its browsing tool. That's what I realized from the files:&lt;/p&gt;&lt;p&gt;1. they are &lt;span style="font-weight: bold;"&gt;named with the pattern&lt;/span&gt; "HNI_9999.JPG" and "HNI_9999.MPO" (when taken "in 3D")&lt;br /&gt;2. their &lt;span style="font-weight: bold;"&gt;resolution&lt;/span&gt; was 640x480&lt;br /&gt;3. their &lt;span style="font-weight: bold;"&gt;average size&lt;/span&gt; was 50kB&lt;br /&gt;4. they had several fields in &lt;span style="font-weight: bold;"&gt;JPEG's header&lt;/span&gt;: camera make and model, and date/time taken&lt;br /&gt;5. &lt;span style="font-weight: bold;"&gt;file&lt;/span&gt; command gave this output:HNI_0018.JPG:  JPEG image data, EXIF standard 2.2, baseline, precision 0, 4360x480&lt;/p&gt;&lt;p&gt;Then I started hacking around with these f*cking procedures: plug SD card into PC, analyze and copy files, remove SD, plug it into Nintendo 3DS, and... nothing appeared! First I tried renaming folders and filenames according to the patterns the console was expecting. Second I tried to rescale the pictures to 640x480, by using &lt;span style="font-weight: bold;"&gt;ImageMagick&lt;/span&gt; (see my &lt;a href="http://agajorte.blogspot.com/2011/08/easily-creating-thumbnails-on-linux.html" target="new"&gt;other post&lt;/a&gt;):&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: courier new;"&gt;$ convert -scale 640x480 -quality 85 source/HNI_0018.JPG destin/HNI_0018.JPG&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Yet nothing! I wondered the issue was with the JPEG's header. Then I asked &lt;span style="font-weight: bold;"&gt;Debian's APT&lt;/span&gt; for some magical tool designed to handle those cr*ppy header fields... Among several options, I chose &lt;a href="http://www.sentex.net/%7Emwandel/jhead/" target="new"&gt;&lt;span style="font-weight: bold;"&gt;jhead&lt;/span&gt;&lt;/a&gt;. Indeed I found &lt;span style="font-weight: bold;"&gt;jhead&lt;/span&gt; wonderful, so that I could easily manipulate a &lt;span style="font-weight: bold;"&gt;JPEG's EXIF header&lt;/span&gt; from the Linux shell.&lt;/p&gt;&lt;p&gt;When issuing jhead onto the original 3DS file, I had this:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: courier new;"&gt;$ jhead HNI_0018.JPG&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;File name    : HNI_0018.JPG&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;File size    : 49610 bytes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;File date    : 2011:09:08 20:20:09&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Camera make  : Nintendo&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Camera model : Nintendo 3DS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Date/Time    : 2011:09:05 14:31:20&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Resolution   : 640 x 480&lt;/span&gt;&lt;/p&gt;&lt;p&gt;So I found an interesting option on jhead: it can copy a JPEG's file header into another file! That's what I did:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: courier new;"&gt;$ jhead -te HNI_0018.JPG HNI_0030.JPG&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Well, now at least my desired JPEG file had the proper and expected header, right? F*cking cycle again and... nothing! The console was still not recognizing my picture files copied from a PC.&lt;/p&gt;&lt;p&gt;I thought it could be an issue of duplicated timestamps, so I tried to change the file's timestamp (through &lt;span style="font-weight: bold;"&gt;touch&lt;/span&gt; command) and the date/time in JPEG's header (via &lt;span style="font-weight: bold;"&gt;jhead&lt;/span&gt;). No way!&lt;/p&gt;&lt;p&gt;That expert guy in the forum was definitely wrong: even with the proper naming and file formats, the console still does not accept pictures from the outside world! That lock-in stinks like some other company's behavior. Then I turned Nintendo 3DS over looking for some fruit logo on its back! :P&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/-1oeDFzQ8rK0/TmmYwh8IRrI/AAAAAAAAAYY/SxVhXLqIeP0/s1600/n3ds-fruit.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5650215167024711346" src="http://2.bp.blogspot.com/-1oeDFzQ8rK0/TmmYwh8IRrI/AAAAAAAAAYY/SxVhXLqIeP0/s400/n3ds-fruit.jpg" style="cursor: pointer; display: block; height: 173px; margin: 0px auto 10px; text-align: center; width: 295px;" /&gt;&lt;/a&gt;&lt;p&gt;Deep breath. I realized that 3DS was able to save pictures from the Internet browser that comes with the system. Hmmm, that should be a hint! When observing JPEG files taken from Internet, I discovered that they didn't bear those blessed EXIF headers... :P (Well, at least I learned about jhead tool.)&lt;/p&gt;&lt;p&gt;What if I put my own picture files in the Internet and try to access the respective HTML page from 3DS? That's what I did: raised my &lt;span style="font-weight: bold;"&gt;apache2&lt;/span&gt; service on Linux and pointed the browser in 3DS to my local URL address. After displaying the image, I was able to save it locally in the console! OK, that should be a solution.&lt;/p&gt;&lt;p&gt;Indeed the JPEG was successfully persisted in the proper folder with its preferred name. However, the original file format and EXIM header were kept (I checked it using Linux &lt;span style="font-weight: bold;"&gt;diff&lt;/span&gt; command).&lt;/p&gt;&lt;p&gt;The task of choosing which pictures to import into 3DS I gave to my daughter, but I still needed to make it easier for her. So, in order to display thumbnails rather than Apache's default file listing, I created a small Shell Script:&lt;/p&gt;&lt;pre&gt;$ for a in *.JPG *.jpg; do echo "&amp;lt;a href='$a'&amp;gt;&amp;lt;img src='$a' border=5 height='25%'/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;"; done &amp;gt; fotos.html&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This was to be run inside each folder containing candidate pictures to be saved into 3DS. In Apache HTTPD's &lt;span style="font-weight: bold;"&gt;/var/www/&lt;/span&gt; directory I created symbolic links to those directories.&lt;/p&gt;&lt;a href="http://3.bp.blogspot.com/-y-p_lyg0gV8/Tmmbh2G8bII/AAAAAAAAAYg/8CYVjilwJtE/s1600/page-thumbs.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5650218213275626626" src="http://3.bp.blogspot.com/-y-p_lyg0gV8/Tmmbh2G8bII/AAAAAAAAAYg/8CYVjilwJtE/s400/page-thumbs.jpg" style="cursor: pointer; display: block; height: 265px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;p&gt;After checking the availability of my local pages from 3DS, I finally returned this gadget to my daughter. Then I taught her how to browse the pages and save the pictures she wanted. She was quite happy for that besides the extended effort.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/-0ZlzUD2iQyI/TmmbiLvRScI/AAAAAAAAAYo/4YGs0A2pxqQ/s1600/page-photo.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5650218219081910722" src="http://1.bp.blogspot.com/-0ZlzUD2iQyI/TmmbiLvRScI/AAAAAAAAAYo/4YGs0A2pxqQ/s400/page-photo.jpg" style="cursor: pointer; display: block; height: 265px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;p&gt;Wooh, what a lotta work! Life could be easier, isn't it Nintendo?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-471583136657177680?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/471583136657177680/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/09/transferring-photos-to-nintendo-3ds.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/471583136657177680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/471583136657177680'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/09/transferring-photos-to-nintendo-3ds.html' title='Transferring photos to Nintendo 3DS'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-_1mDx7mnU8w/TmmVnscIQrI/AAAAAAAAAYI/L598N5XCNfQ/s72-c/n3ds-console.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2312873341803708094</id><published>2011-08-13T21:42:00.000-07:00</published><updated>2011-08-13T22:39:44.351-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><category scheme='http://www.blogger.com/atom/ns#' term='mongodb'/><title type='text'>Introdução ao MongoDB</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-sGMJ-KCRuCE/Tkdet-8HH1I/AAAAAAAAAV8/soXJ3jA3Wy4/s1600/logo-mongodb-onwhite-300x100.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 100px;" src="http://4.bp.blogspot.com/-sGMJ-KCRuCE/Tkdet-8HH1I/AAAAAAAAAV8/soXJ3jA3Wy4/s400/logo-mongodb-onwhite-300x100.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5640581202387083090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Aplicações modernas provaram que bancos de dados do tipo &lt;b&gt;NoSQL&lt;/b&gt; são inevitáveis para o sucesso e continuidade de empresas altamente dependentes da Internet. Vide exemplos como Google, Yahoo, Amazon, Twitter e Facebook.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Todavia, existem inúmeras soluções disponíveis e nenhum padrão sobre como manipular, trafegar ou consultar as informações contidas nos bancos NoSQL. Mesmo a classificação (ou melhor dizer, a taxonomia) dessa zoologia de novos bancos ainda está (perdoem-me o trocadilho!) nebulosa... Quem sabe futuramente tenhamos um ANSI-NoSQL...&lt;/p&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-ZikNDCwZiyM/Tkdet4fnN7I/AAAAAAAAAWE/x8xwVKva7OE/s1600/mongodb303183_5.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 320px;" src="http://4.bp.blogspot.com/-ZikNDCwZiyM/Tkdet4fnN7I/AAAAAAAAAWE/x8xwVKva7OE/s400/mongodb303183_5.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5640581200656938930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;O fato é que algumas dessas tecnologias provaram ser apenas estufas para o meio acadêmico, enquanto que outras chegaram a evoluir a ponto de serem aceitas por empresas que apostam no pioneirismo. Uma dessas tecnologias de sucesso foi o &lt;b&gt;MongoDB&lt;/b&gt;.&lt;/p&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_8846185"&gt;&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/8846185" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;&lt;i&gt;View more presentations from &lt;a href="http://www.slideshare.net/hjort" target="_blank"&gt;hjort&lt;/a&gt;.&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Nesta apresentação são introduzidos conceitos como as Grandes Rupturas (IMS x RDBMS x NoSQL), o que é o MongoDB, o Modelo de Dados Orientado a Documentos, JSON e BSON, tipos de dados no MongoDB, operações (Insert, Update, Delete), Modificadores Atômicos, Linguagem de Consulta, Indexação, Agregação e Map/Reduce, Capped Collections, GridFS, Server-Side Scripting, Replicação (Master/Slave e Replica Sets), Arquitetura com Sharding, Auto-Sharding + Replicação e outras tecnologias e detalhes envolvidos no banco de dados MongoDB.&lt;/p&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2312873341803708094?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2312873341803708094/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/08/introducao-ao-mongodb.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2312873341803708094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2312873341803708094'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/08/introducao-ao-mongodb.html' title='Introdução ao MongoDB'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-sGMJ-KCRuCE/Tkdet-8HH1I/AAAAAAAAAV8/soXJ3jA3Wy4/s72-c/logo-mongodb-onwhite-300x100.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-3759561225543916629</id><published>2011-08-08T11:39:00.000-07:00</published><updated>2011-08-08T13:29:50.185-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Easily creating thumbnails on Linux</title><content type='html'>&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Have you ever needed to scale down a bunch of picture files to a smaller resolution?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you used a GUI-based program such as &lt;a style="font-weight: bold;" href="http://www.gimp.org/"&gt;gimp&lt;/a&gt; or &lt;span style="font-weight: bold;"&gt;Photoshop&lt;/span&gt;, and spent a reasonable time on that task, you'll surely appreciate this post. The same applies if you're not a slave on mice and thus prefer to open command-line terminals rather than double-clicks.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();}  catch(e) {}" href="http://4.bp.blogspot.com/-F7832_HuBQM/TkBF0Cidw0I/AAAAAAAAAVk/Heu6867pxtc/s1600/thumbnails-sample.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 298px;" src="http://4.bp.blogspot.com/-F7832_HuBQM/TkBF0Cidw0I/AAAAAAAAAVk/Heu6867pxtc/s400/thumbnails-sample.jpg" alt="" id="BLOGGER_PHOTO_ID_5638583493804802882" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;On Linux there is &lt;a href="http://www.imagemagick.org/"&gt;&lt;b&gt;ImageMagick&lt;/b&gt;&lt;/a&gt;, a software suite that lets you create, edit, and compose bitmap images. It can read, convert and write images in a variety of formats including GIF, JPEG, PNG, TIFF, etc. We can use it to translate, flip, mirror, rotate, scale, shear and transform images, adjust image colors, apply various special effects, or draw text, lines, polygons, ellipses and Bezier curves.&lt;br /&gt;&lt;br /&gt;The most important feature to consider here is that ImageMagick includes a number of command-line utilities for manipulating images. That is, text-mode, no GUI needed for editing your images.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();}  catch(e) {}" href="http://4.bp.blogspot.com/-QUFGcFgUkHc/TkBF0VNo_nI/AAAAAAAAAVs/Dw1Oq9UlXiA/s1600/ImageMagickLogo.png"&gt;&lt;img style="cursor: pointer; width: 154px; height: 160px;" src="http://4.bp.blogspot.com/-QUFGcFgUkHc/TkBF0VNo_nI/AAAAAAAAAVs/Dw1Oq9UlXiA/s400/ImageMagickLogo.png" alt="" id="BLOGGER_PHOTO_ID_5638583498817732210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We say that ImageMagick can modify or create images automagically and dynamically!&lt;br /&gt;&lt;br /&gt;For instance, to rescale (to 800 by 600 pixels) and lower the quality (by 70%) of a JPEG file, the following instruction can be used:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;$ convert -scale 800x600 -quality 70 before.jpg after.jpg&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Thus, suppose you have a directory hierarchy named &lt;span style="font-weight: bold;"&gt;source&lt;/span&gt; filled with your pictures and you need to create a similar structure but with thumbnails instead. The resulting directory will be called &lt;span style="font-weight: bold;"&gt;destin&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;First of all, open a terminal. :D Then, change to &lt;span style="font-weight: bold;"&gt;source&lt;/span&gt; directory and create the new &lt;span style="font-weight: bold;"&gt;destin&lt;/span&gt; (in this example they're parallel):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;$ cd source&lt;br /&gt;$ mkdir ../destin&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Second, create subdirectories on &lt;span style="font-weight: bold;"&gt;destin&lt;/span&gt; following the existing &lt;span style="font-weight: bold;"&gt;source&lt;/span&gt; structure:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;$ find -type d -exec mkdir -p "../destin/{}" \;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you wish, issue a &lt;span style="font-style: italic;"&gt;tree&lt;/span&gt; or simple &lt;span style="font-style: italic;"&gt;find&lt;/span&gt; command on &lt;span style="font-weight: bold;"&gt;destin&lt;/span&gt; just to check its contents.&lt;br /&gt;&lt;br /&gt;At last, run &lt;span style="font-style: italic;"&gt;find&lt;/span&gt; command along with &lt;span style="font-style: italic;"&gt;convert&lt;/span&gt; in order to create thumbnails in batch mode:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;$ find -type f -exec convert -scale 1024x768 -quality 85 "{}" "../destin/{}" \;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it, Power to the Shell! And a Happy 20th Anniversary, Linux!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();}  catch(e) {}" href="http://2.bp.blogspot.com/-MLymdhyRJcw/TkBF0TOi5WI/AAAAAAAAAV0/GJJI2vweykQ/s1600/shell-picture.jpg"&gt;&lt;img style="cursor: pointer; width: 259px; height: 194px;" src="http://2.bp.blogspot.com/-MLymdhyRJcw/TkBF0TOi5WI/AAAAAAAAAV0/GJJI2vweykQ/s400/shell-picture.jpg" alt="" id="BLOGGER_PHOTO_ID_5638583498284655970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-3759561225543916629?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/3759561225543916629/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/08/easily-creating-thumbnails-on-linux.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3759561225543916629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3759561225543916629'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/08/easily-creating-thumbnails-on-linux.html' title='Easily creating thumbnails on Linux'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-F7832_HuBQM/TkBF0Cidw0I/AAAAAAAAAVk/Heu6867pxtc/s72-c/thumbnails-sample.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6500553344076967028</id><published>2011-07-29T13:51:00.000-07:00</published><updated>2011-10-04T07:43:23.541-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='fts'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Full Text Search em português no PostgreSQL</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Full Text Searching&lt;/b&gt; (ou simplesmente busca textual ou FTS) é uma poderosa ferramenta disponível em bancos de dados que visa aumentar a probabilidade de sucesso nas consultas efetuadas pelos usuários.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Tm8Z3geDm_0/TjMd77-3fiI/AAAAAAAAAVM/gdJbATYm8Hk/s1600/module-full-text-search2.jpg"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 208px;" src="http://4.bp.blogspot.com/-Tm8Z3geDm_0/TjMd77-3fiI/AAAAAAAAAVM/gdJbATYm8Hk/s400/module-full-text-search2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5634880474321485346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Operadores de busca textual existem nos SGBDs há anos. O &lt;b&gt;PostgreSQL&lt;/b&gt; oferece, além do LIKE, o ILIKE (versão que desconsidera a capitalização) e operadores baseados em expressão regular (i.e., ~ e ~*) para tipos de dados textuais. Entretanto, tais operadores falham ao não prover muitas propriedades essenciais requeridas por sistemas de informações modernos, tais como suporte linguístico, ranking dos resultados e indexação [1].&lt;br /&gt;&lt;br /&gt;Na Universidade de Moscou foi criado o projeto &lt;b&gt;Tsearch2&lt;/b&gt; [2], no qual os russos Oleg Bartunov e Teodor Sigaev desenvolveram um motor do tipo full text inteiramente integrado ao SGBD PostgreSQL. Além da referida solução de busca textual, foram criados dois poderosos mecanismos de indexação: GiST e GIN.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-OF8HSf3CxMQ/TjMd8MO7ObI/AAAAAAAAAVc/Fn7TrqlM2yU/s1600/oleg-teodor-2.jpg"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 300px; height: 170px;" src="http://1.bp.blogspot.com/-OF8HSf3CxMQ/TjMd8MO7ObI/AAAAAAAAAVc/Fn7TrqlM2yU/s400/oleg-teodor-2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5634880478683806130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;O Tsearch2 residiu no diretório contrib do PostgreSQL até a sua versão 8.1, sendo finalmente incorporado ao core do SGBD na versão 8.3, tornando-se a opção default para FTS nele.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-tr-_YvpPVeA/TjMd73U8fYI/AAAAAAAAAVU/0fDmLv-8enE/s1600/features_search%2Btext2.jpg"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://1.bp.blogspot.com/-tr-_YvpPVeA/TjMd73U8fYI/AAAAAAAAAVU/0fDmLv-8enE/s400/features_search%2Btext2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5634880473071910274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para ilustrar, tomemos como exemplo o clássico cadastro de municípios brasileiros. A missão é efetuar buscas textuais (neste caso pelo nome dos municípios) usando FTS.&lt;br /&gt;&lt;br /&gt;Eis uma tabela no PostgreSQL populada com as cidades:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;        nome         | uf &lt;br /&gt;---------------------+----&lt;br /&gt; Abadia de Goiás     | GO&lt;br /&gt; Abadia dos Dourados | MG&lt;br /&gt; Abadiânia           | GO&lt;br /&gt; Abaeté              | MG&lt;br /&gt; Abaetetuba          | PA&lt;br /&gt; Abaiara             | CE&lt;br /&gt; Abaíra              | BA&lt;br /&gt; Abaré               | BA&lt;br /&gt; Abatiá              | PR&lt;br /&gt; Abdon Batista       | SC&lt;br /&gt; ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A ideia é fazer com que buscas aproximadas possam ser efetuadas pelo usuário, ou seja, algo mais "poderoso" que um falho operador LIKE.&lt;br /&gt;&lt;br /&gt;A primeira modificação será criar uma coluna adicional, chamada de "busca", a fim de armazenar os vetores já normalizados dos termos para ser usada posteriormente nas consultas.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;ALTER TABLE municipios ADD busca tsvector;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Eis a estrutura da tabela após a execução do comando:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;         Table "public.municipios"&lt;br /&gt; Column |         Type          | Modifiers &lt;br /&gt;--------+-----------------------+-----------&lt;br /&gt; nome   | character varying(50) | &lt;br /&gt; uf     | character(2)          | &lt;br /&gt; busca  | tsvector              | &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como o foco deste estudo é usar o idioma português, e considerando que o servidor PostgreSQL esteja configurado com a codificação UTF-8 (i.e., Unicode), precisaremos criar algumas funções adicionais. Baseando-se em [3] e [4], criei essas funções:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;CREATE FUNCTION to_ascii(bytea, name) RETURNS text AS&lt;br /&gt; 'to_ascii_encname'&lt;br /&gt; LANGUAGE internal STRICT;&lt;br /&gt;&lt;br /&gt;CREATE FUNCTION simples(texto varchar) RETURNS varchar AS&lt;br /&gt; 'select lower(to_ascii(convert_to($1, ''latin1''), ''latin1''))'&lt;br /&gt; LANGUAGE sql IMMUTABLE STRICT;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Veja o que essa nova função simples() é capaz de fazer:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;brasil=# select simples('Pinhão com Açaí');&lt;br /&gt;    simples     &lt;br /&gt;----------------&lt;br /&gt; pinhao com acai&lt;br /&gt;(1 row)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou seja, trata-se de uma função de transformação que normaliza o texto recebido como argumento. Ela será essencial para os passos a seguir.&lt;br /&gt;&lt;br /&gt;Podemos usar a função simples() em conjunto com to_tsvector() a fim de produzir o vetor de lexemas (termos processados a serem usados nas buscas). Veja:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;brasil=# select to_tsvector(simples('Pinhão com Açaí'));&lt;br /&gt;    to_tsvector    &lt;br /&gt;-------------------&lt;br /&gt; 'aca':3 'pinha':1&lt;br /&gt;(1 row)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Voltando à tabela de municípios, execute o comando SQL a seguir para popular a recém-criada coluna "busca" com o vetor transformado em cada uma de suas tuplas.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;UPDATE municipios SET busca = to_tsvector(simples(nome));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pronto! Agora que os textos foram pré-processados, basta executar as consultas SQL usando o operador especial @@ no PostgreSQL. Veja um exemplo de uso no qual o usuário digitou o texto "sao mateus" na aplicação. A consulta SQL fica assim:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;brasil=# select nome, uf from municipios&lt;br /&gt;brasil=# where busca @@ plainto_tsquery(simples('sao mateus'));&lt;br /&gt;          nome          | uf &lt;br /&gt;------------------------+----&lt;br /&gt; São Mateus             | ES&lt;br /&gt; São Mateus do Maranhão | MA&lt;br /&gt; São Mateus do Sul      | PR&lt;br /&gt;(3 rows)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note que além do vetor (coluna "busca" do tipo tsvector) é preciso especificar um tipo tsquery, fornecido pelas funções to_tsquery() e plainto_tsquery(). A função simples() foi usada novamente para realizar a transformação do texto informado.&lt;br /&gt;&lt;br /&gt;Ótimo! É só isso?&lt;br /&gt;&lt;br /&gt;Não... Funcionou, mas o desempenho não pode ser garantido. Na realidade a busca com essa abordagem será mais feliz que se usássemos um ardiloso LIKE "%sao mateus%". (Jogue a primeira pedra quem nunca encontrou um monstrinho desses em uma aplicação!).&lt;br /&gt;&lt;br /&gt;Vejamos como o SGBD está tratando a consulta SQL acima:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;brasil=# explain select nome, uf from municipios&lt;br /&gt;brasil=# where busca @@ plainto_tsquery(simples('sao mateus'));&lt;br /&gt;                         QUERY PLAN                          &lt;br /&gt;-------------------------------------------------------------&lt;br /&gt; Seq Scan on municipios  (cost=0.00..163.60 rows=6 width=16)&lt;br /&gt;   Filter: (busca @@ plainto_tsquery('sao mateus'::text))&lt;br /&gt;(2 rows)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ops, uma varredura sequencial (também conhecido por full scan ou sequential scan) está sendo efetuada! Se você não sabe o que é isso, consulte o seu DBA. Se ele for teu amigo, não irá te xingar.&lt;br /&gt;&lt;br /&gt;Bom, e como podemos corrigir isso? Criando um índice! :D&lt;br /&gt;&lt;br /&gt;Neste caso específico do FTS no PostgreSQL, temos a escolha de usar uma das duas opções de índices, GiST ou GIN (lembra dos russos?). Cada uma tem a sua aplicação. Escolhi o GIN por esta apresentar maior precisão para esta aplicação. Veja como criar o índice:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;CREATE INDEX municipios_gidx ON municipios USING gin(busca);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E agora, será que funcionou? Roda o EXPLAIN novamente! Veja:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;brasil=# explain select nome, uf from municipios&lt;br /&gt;brasil=# where busca @@ plainto_tsquery(simples('sao mateus'));&lt;br /&gt;                                  QUERY PLAN                                  &lt;br /&gt;------------------------------------------------------------------------------&lt;br /&gt; Bitmap Heap Scan on municipios  (cost=4.30..23.49 rows=6 width=16)&lt;br /&gt;   Recheck Cond: (busca @@ plainto_tsquery('sao mateus'::text))&lt;br /&gt;   -&gt;  Bitmap Index Scan on municipios_gidx  (cost=0.00..4.30 rows=6 width=0)&lt;br /&gt;         Index Cond: (busca @@ plainto_tsquery('sao mateus'::text))&lt;br /&gt;(4 rows)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sucesso! Agora a busca textual com FTS está devidamente indexada no PostgreSQL.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Referências&lt;/h2&gt;&lt;br /&gt;[1] &lt;a href="http://www.postgresql.org/docs/8.3/static/textsearch.html" target="_blank"&gt;PostgreSQL 8.3 Documentation - Full Text Search&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;[2] &lt;a href="http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/docs/tsearch-V2-intro.html" target="_blank"&gt;Tsearch2 - full text search extension for PostgreSQL&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;[3] &lt;a href="http://www.laudatio.com/wordpress/2008/11/05/postgresql-83-to_ascii-utf8/" target="_blank"&gt;PostgreSQL: TO_ASCII &amp; UTF8&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;[4] &lt;a href="http://www.postgresql.org/docs/8.3/static/functions-string.html" target="_blank"&gt;PostgreSQL 8.3 Documentation - String Functions and Operators&lt;/a&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6500553344076967028?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6500553344076967028/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/07/full-text-search-em-portugues-no.html#comment-form' title='5 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6500553344076967028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6500553344076967028'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/07/full-text-search-em-portugues-no.html' title='Full Text Search em português no PostgreSQL'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Tm8Z3geDm_0/TjMd77-3fiI/AAAAAAAAAVM/gdJbATYm8Hk/s72-c/module-full-text-search2.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4624016534784805965</id><published>2011-06-15T11:18:00.000-07:00</published><updated>2011-06-15T12:38:00.967-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Buscar palavras do dicionário para registrar domínio</title><content type='html'>&lt;br/&gt;&lt;br /&gt;No início do mês de junho foram finalmente &lt;a href="http://www.cointernet.co/"&gt;oferecidos registros&lt;/a&gt; para o domínio colombiano .CO. Em pouco tempo já haviam &lt;a href="http://news.idg.no/cw/art.cfm?id=17F98A90-1A64-67EA-E4D9E9ABBFA5D6DA"&gt;um milhão de pedidos de registro&lt;/a&gt;! Empresas de destaque na Internet, como Amazon e Twitter foram atraídas pela novidade, e com isso impulsionaram uma corrida desenfreada junto às empresas de registro.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-4SxEQZE2nU0/TfkEGcTvWpI/AAAAAAAAAUY/jArxAnxCw4o/s1600/domain.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 258px;" src="http://4.bp.blogspot.com/-4SxEQZE2nU0/TfkEGcTvWpI/AAAAAAAAAUY/jArxAnxCw4o/s400/domain.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5618526518846118546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pensando nas possibilidades de negócio de se garantir um nome de Internet rentável com o sufixo &lt;b&gt;.co&lt;/b&gt;, decidi cruzar os dados de um dicionário e fui buscar ajuda ao amigo Shell... Irei mostrar nas linhas a seguir o que consegui com essa brincadeira!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-YI6pOLQ2OtM/TfkH1RE0_pI/AAAAAAAAAUo/ZMVhEqGolqU/s1600/shell-de.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 313px;" src="http://1.bp.blogspot.com/-YI6pOLQ2OtM/TfkH1RE0_pI/AAAAAAAAAUo/ZMVhEqGolqU/s400/shell-de.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5618530621819518610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para iniciar, instalei um dicionário de correção ortográfica do &lt;b&gt;OpenOffice.org&lt;/b&gt;, o &lt;b&gt;myspell&lt;/b&gt;. No Debian, basta executar o comando a seguir como super usuário:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;apt-get install myspell-pt-br&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Entre diversos arquivos, o que me interessou foi o &lt;b&gt;pt_BR.dic&lt;/b&gt;. Com cerca de 4,5 MB, ele possui mais de 300 mil verbetes da língua portuguesa! Para não correr o risco de danificá-lo, copiei para minha área (i.e., home):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;cp /usr/share/hunspell/pt_BR.dic ~&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O arquivo é originariamente codificado com &lt;b&gt;ISO-8859-1&lt;/b&gt;. Pra me livrar dessa orelhada, o converti para o formato &lt;b&gt;Unicode&lt;/b&gt; (i.e., UTF-8) usando o &lt;b&gt;iconv&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;iconv -f iso-8859-1 -t utf-8 pt_BR.dic &amp;gt; pt_BR-utf8.dic&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Eis um trecho do arquivo &lt;b&gt;pt_BR-utf8.dic&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;abacalhoar/akYMjL&lt;br /&gt;abacamartado/D&lt;br /&gt;aba?anar/akYMjL&lt;br /&gt;abacanto/D&lt;br /&gt;abacatada/B&lt;br /&gt;abacataia/B&lt;br /&gt;abacatal/BR&lt;br /&gt;abacate/BP&lt;br /&gt;abacate-do-mato&lt;br /&gt;abacateiral/BR&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Não sei precisar que tipo de informação é carregada após o sinal de barra em cada linha do arquivo, mas com certeza não me interessa nesse momento. Vamos removê-la e filtrar apenas as palavras que terminam em "co" com a ajuda de um conhecido amigo, o &lt;b&gt;SED&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;sed -e 's/\/.\+$//' -e '/co$/!d' pt_BR-utf8.dic &amp;gt; palavras-co.txt&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E eis o arquivo resultante &lt;b&gt;palavras-co.txt&lt;/b&gt;, bem mais comportado:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;abrodílico&lt;br /&gt;abrotanínico&lt;br /&gt;abrotonínico&lt;br /&gt;absalônico&lt;br /&gt;abscísico&lt;br /&gt;abscíssico&lt;br /&gt;absenteístico&lt;br /&gt;absentístico&lt;br /&gt;absintático&lt;br /&gt;absintêmico&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É certo que existem palavras muito esdrúxulas da amada língua portuguesa que jamais seriam usadas num nome da Internet. Usando um outro carinha legal, o &lt;b&gt;AWK&lt;/b&gt;, além do comando &lt;b&gt;sort&lt;/b&gt;, criei um outro arquivo contendo a quantidade de letras e a palavra, ordenando pela primeira coluna. Eis a mágica:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;awk '{print length($0)"\t"$0}' palavras-co.txt | sort -n &amp;gt; palavras-co2.txt&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E olha só como ficou o arquivo &lt;b&gt;palavras-co2.txt&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;5 dorco&lt;br /&gt;5 écico&lt;br /&gt;5 édico&lt;br /&gt;5 efuco&lt;br /&gt;5 élico&lt;br /&gt;5 êmico&lt;br /&gt;5 emoco&lt;br /&gt;5 ênico&lt;br /&gt;5 épico&lt;br /&gt;5 Érico&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora resta a parte mais divertida do trabalho: varrer a lista de palavras do dicionário e analisar se cada uma delas já não foi registrada nesse novo domínio ".co". O resultado será um outro arquivo de texto, semelhante ao anterior, mas com a adição de uma terceira coluna, que dirá a disponibilidade do domínio "palavra.co".&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-98ejNDT7xlY/TfkEPL1p9pI/AAAAAAAAAUg/63aJw4tnMT8/s1600/wwwart_01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 332px; height: 267px;" src="http://1.bp.blogspot.com/-98ejNDT7xlY/TfkEPL1p9pI/AAAAAAAAAUg/63aJw4tnMT8/s400/wwwart_01.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5618526669043791506" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para essa tarefa, usei comandos como &lt;b&gt;while&lt;/b&gt;, &lt;b&gt;read&lt;/b&gt;, &lt;b&gt;echo&lt;/b&gt; e &lt;b&gt;cut&lt;/b&gt; do Shell e carinhas legais como o &lt;b&gt;sed&lt;/b&gt; (de novo!) e &lt;b&gt;curl&lt;/b&gt;. Como consegui a URL de teste? Tive que fuçar nos fontes da página do &lt;a href="http://www.cointernet.co/"&gt;cointernet.co&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-mUDnPiUq2Po/TfkIDq5JBCI/AAAAAAAAAUw/zoNdPy0Al4I/s1600/sed_awk_book2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 305px; height: 400px;" src="http://3.bp.blogspot.com/-mUDnPiUq2Po/TfkIDq5JBCI/AAAAAAAAAUw/zoNdPy0Al4I/s400/sed_awk_book2.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5618530869267989538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Bom, eis o código resultante em &lt;b&gt;Shell&lt;/b&gt;. Ficaria mais bonito eu ter colocado num arquivo Shell Script, mas fiquei com preguiça...&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;&amp;gt; palavras-co3.txt&lt;br /&gt;while read linha&lt;br /&gt;do&lt;br /&gt;    letras=`echo $linha | cut -f1 -d' '`&lt;br /&gt;    palavra=`echo $linha | cut -f2 -d' '`&lt;br /&gt;    token=`echo $palavra | sed 's/co$/.co/'`&lt;br /&gt;    disp=`curl -s "http://www.opportunity.co/register/whois-lookup.php?oppurl=$token"`&lt;br /&gt;    echo "$palavra"&lt;br /&gt;    echo -e "$linha\t$disp" &amp;gt;&amp;gt; palavras-co3.txt&lt;br /&gt;done &amp;lt; palavras-co2.txt&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Olha só que legal o resultado disso: o arquivo de texto resultante (um outro!) trará &lt;b&gt;TRUE&lt;/b&gt; caso a palavra esteja disponível para o registro ou &lt;b&gt;FALSE&lt;/b&gt; se alguém já tiver tido essa ideia!&lt;br /&gt;&lt;br /&gt;Eis um trecho do arquivo &lt;b&gt;palavras-co3.txt&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;5 dorco FALSE&lt;br /&gt;5 écico TRUE&lt;br /&gt;5 édico TRUE&lt;br /&gt;5 efuco FALSE&lt;br /&gt;5 élico TRUE&lt;br /&gt;5 êmico TRUE&lt;br /&gt;5 emoco FALSE&lt;br /&gt;5 ênico TRUE&lt;br /&gt;5 épico TRUE&lt;br /&gt;5 Érico TRUE&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Legal, funcionou, mas e agora?!&lt;br /&gt;&lt;br /&gt;Chuá...! &lt;i&gt;[balde-de-água-na-cabeça]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Ao rodar o script e gerar o arquivo, disparei um &lt;b&gt;tail -f&lt;/b&gt; e cheguei à conclusão de que alguém já fez esse trabalho e tratou de registrar tudo quanto é palavra do dicionário de português... (Malditos!)&lt;br /&gt;&lt;br /&gt;Aliás, só apareceram como disponíveis as palavras acentuadas, que provavelmente não poderão ser registradas caso haja a versão normalizada delas (ex: "mímico" vs "mimico").&lt;br /&gt;&lt;br /&gt;Ou seja, se você tinha esperanças de conseguir algo como &lt;i&gt;bote.co&lt;/i&gt;, &lt;i&gt;magi.co&lt;/i&gt;, &lt;i&gt;sova.co&lt;/i&gt; ou &lt;i&gt;peni.co&lt;/i&gt;, perca-as... Ou senão entre em contato com o feladamãe que registrou antes de você e negocie o nome de domínio...&lt;br /&gt;&lt;br /&gt;Bom, pelo menos serviu para brincar um pouco com o Shell. :D&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Desafio&lt;/b&gt;: tente normalizar as palavras do arquivo &lt;b&gt;palavras-co.txt&lt;/b&gt; (i.e., deixando tudo em minúsculo e retirando os acentos e caracteres especiais) antes de fazer as consultas WHOIS com o script.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4624016534784805965?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4624016534784805965/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/06/buscar-palavras-do-dicionario-para.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4624016534784805965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4624016534784805965'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/06/buscar-palavras-do-dicionario-para.html' title='Buscar palavras do dicionário para registrar domínio'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4SxEQZE2nU0/TfkEGcTvWpI/AAAAAAAAAUY/jArxAnxCw4o/s72-c/domain.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6757197567865307198</id><published>2011-06-06T10:10:00.000-07:00</published><updated>2011-06-06T10:49:10.354-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><title type='text'>Persistência nas Nuvens com NoSQL</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;p&gt;Um termo recorrente quando se fala em &lt;b&gt;computação em nuvem&lt;/b&gt; é a persistência dos dados em bancos do tipo &lt;b&gt;NoSQL&lt;/b&gt;, ou seja, em uma forma não-relacional. Essa tecnologia não substitui os consolidados Sistemas Gerenciadores de Bancos de Dados Relacionais (SGBDRs), mas ao invés disso torna-se uma nova ferramenta disponível ao desenvolvedor.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Implantar uma aplicação na nuvem não significa que NoSQL será utilizada. Entretanto, as funcionalidades que essa tecnologia provê são altamente convergentes com as propostas da computação em nuvem: performance, escalabilidade horizontal, alta disponibilidade e flexibilidade.&lt;/p&gt;&lt;br /&gt;&lt;div style="width: 425px;" id="__ss_8224329"&gt;&lt;br /&gt;&lt;iframe src="http://www.slideshare.net/slideshow/embed_code/8224329" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" height="355" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;div style="padding: 5px 0pt 12px;"&gt;View more presentations from &lt;a href="http://www.slideshare.net/hjort"&gt;hjort&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;Nesta apresentação são introduzidos conceitos como Computação em Nuvem, Persistência de Dados, Bancos de Dados Relacionais, o movimento NoSQL, o modelo de dados do Bigtable da Google, a arquitetura do Dynamo da Amazon e detalhes técnicos do Apache Cassandra.&lt;/p&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6757197567865307198?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6757197567865307198/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/06/persistencia-nas-nuvens-com-nosql.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6757197567865307198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6757197567865307198'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/06/persistencia-nas-nuvens-com-nosql.html' title='Persistência nas Nuvens com NoSQL'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6880201179325138320</id><published>2011-05-09T06:17:00.000-07:00</published><updated>2011-05-09T06:52:58.226-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><title type='text'>Cassandra: Rompendo o Paradigma Relacional com NoSQL</title><content type='html'>&lt;p/&gt;&lt;br /&gt;Apresentação sobre o &lt;span style="font-weight: bold;"&gt;Apache Cassandra&lt;/span&gt; a ser realizada na &lt;a href="http://www.consegi.gov.br/oficinas/apache-cassandra/"&gt;oficina&lt;/a&gt; do &lt;span style="font-weight: bold;"&gt;Demoiselle Cassandra&lt;/span&gt; no &lt;span style="font-weight: bold;"&gt;CONSEGI 2011&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-mK9aIzgV2CQ/TcfqZxyUEQI/AAAAAAAAAPA/Aaxe-Y0HSAU/s1600/img1.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-mK9aIzgV2CQ/TcfqZxyUEQI/AAAAAAAAAPA/Aaxe-Y0HSAU/s400/img1.jpg" alt="" id="BLOGGER_PHOTO_ID_5604705989867868418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-POhvgL6TKEk/TcfqaXOMbqI/AAAAAAAAAPI/N_zemxnIZdU/s1600/img2.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-POhvgL6TKEk/TcfqaXOMbqI/AAAAAAAAAPI/N_zemxnIZdU/s400/img2.jpg" alt="" id="BLOGGER_PHOTO_ID_5604705999916920482" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-E4jmcLoYbow/TcfqaTFMOaI/AAAAAAAAAPQ/-ayIOEkP0QI/s1600/img3.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-E4jmcLoYbow/TcfqaTFMOaI/AAAAAAAAAPQ/-ayIOEkP0QI/s400/img3.jpg" alt="" id="BLOGGER_PHOTO_ID_5604705998805416354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-B6t6LoDhfpI/TcfqauXEbcI/AAAAAAAAAPY/f-TkR-Ch_2U/s1600/img4.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-B6t6LoDhfpI/TcfqauXEbcI/AAAAAAAAAPY/f-TkR-Ch_2U/s400/img4.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706006128160194" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-i75CtxbJozU/Tcfqa5tjOQI/AAAAAAAAAPg/74MdL9mWxbc/s1600/img5.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-i75CtxbJozU/Tcfqa5tjOQI/AAAAAAAAAPg/74MdL9mWxbc/s400/img5.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706009175243010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-M3DL3MAnUHo/TcfqpXNMDzI/AAAAAAAAAPo/gCGbcWb7Zu8/s1600/img6.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-M3DL3MAnUHo/TcfqpXNMDzI/AAAAAAAAAPo/gCGbcWb7Zu8/s400/img6.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706257610739506" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-OOFUGuk1zi4/TcfqpsVTiLI/AAAAAAAAAPw/gsGr5bjWzzE/s1600/img7.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-OOFUGuk1zi4/TcfqpsVTiLI/AAAAAAAAAPw/gsGr5bjWzzE/s400/img7.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706263281928370" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-xhTQGpIDcYM/Tcfqpz2Pj-I/AAAAAAAAAP4/5Z6Rzww3Kos/s1600/img8.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-xhTQGpIDcYM/Tcfqpz2Pj-I/AAAAAAAAAP4/5Z6Rzww3Kos/s400/img8.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706265299128290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-KQHpPgO8o6c/TcfqqYx5soI/AAAAAAAAAQA/dv5v9RzLjG8/s1600/img9.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-KQHpPgO8o6c/TcfqqYx5soI/AAAAAAAAAQA/dv5v9RzLjG8/s400/img9.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706275213030018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-akwwAw1izHM/Tcfqqi52eWI/AAAAAAAAAQI/HwkiUTixIUU/s1600/img10.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-akwwAw1izHM/Tcfqqi52eWI/AAAAAAAAAQI/HwkiUTixIUU/s400/img10.jpg" alt="" id="BLOGGER_PHOTO_ID_5604706277930727778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-uiq7HC1rfw8/Tcfr1OMbF3I/AAAAAAAAAQQ/eGggNoEe-l8/s1600/img11.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-uiq7HC1rfw8/Tcfr1OMbF3I/AAAAAAAAAQQ/eGggNoEe-l8/s400/img11.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707560861669234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-qBJLuOIWO04/Tcfr1UwobDI/AAAAAAAAAQY/ldszaug9Go0/s1600/img12.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-qBJLuOIWO04/Tcfr1UwobDI/AAAAAAAAAQY/ldszaug9Go0/s400/img12.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707562624150578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-ZIy1so8xdH4/Tcfr1s8_biI/AAAAAAAAAQg/wsYqobH9u4E/s1600/img13.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-ZIy1so8xdH4/Tcfr1s8_biI/AAAAAAAAAQg/wsYqobH9u4E/s400/img13.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707569118440994" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-hnnU_M7tWkk/Tcfr17DS7UI/AAAAAAAAAQo/xaRQn8wlWxs/s1600/img14.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-hnnU_M7tWkk/Tcfr17DS7UI/AAAAAAAAAQo/xaRQn8wlWxs/s400/img14.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707572902980930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-pvpfV8N-Bjs/Tcfr2Ye79qI/AAAAAAAAAQw/UKEo9eeEqis/s1600/img15.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-pvpfV8N-Bjs/Tcfr2Ye79qI/AAAAAAAAAQw/UKEo9eeEqis/s400/img15.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707580803544738" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-K1jI5iTviZs/TcfsE9H8ZoI/AAAAAAAAAQ4/6_hka1dJzKw/s1600/img16.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-K1jI5iTviZs/TcfsE9H8ZoI/AAAAAAAAAQ4/6_hka1dJzKw/s400/img16.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707831157384834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-vqeZrwFKUlk/TcfsEyFnXYI/AAAAAAAAARA/fOwGTZsEsYQ/s1600/img17.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-vqeZrwFKUlk/TcfsEyFnXYI/AAAAAAAAARA/fOwGTZsEsYQ/s400/img17.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707828194827650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-5djDqAM516c/TcfsFMMZd5I/AAAAAAAAARI/4z2UHTaoJYU/s1600/img18.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-5djDqAM516c/TcfsFMMZd5I/AAAAAAAAARI/4z2UHTaoJYU/s400/img18.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707835202598802" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-FSU6HA1hRys/TcfsFUy9qpI/AAAAAAAAARQ/3yjvD5DoSWE/s1600/img19.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-FSU6HA1hRys/TcfsFUy9qpI/AAAAAAAAARQ/3yjvD5DoSWE/s400/img19.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707837511838354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-y4WuEI78WEQ/TcfsFcs5efI/AAAAAAAAARY/n-xTHW7BD1o/s1600/img20.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-y4WuEI78WEQ/TcfsFcs5efI/AAAAAAAAARY/n-xTHW7BD1o/s400/img20.jpg" alt="" id="BLOGGER_PHOTO_ID_5604707839633881586" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-JtkLdrMxNuM/TcfsU0trQ7I/AAAAAAAAARg/QVTGOtR_xfk/s1600/img21.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-JtkLdrMxNuM/TcfsU0trQ7I/AAAAAAAAARg/QVTGOtR_xfk/s400/img21.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708103777633202" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-_tJbgkwQSy4/TcfsU-xJvvI/AAAAAAAAARo/0n3o6RiTRf0/s1600/img22.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-_tJbgkwQSy4/TcfsU-xJvvI/AAAAAAAAARo/0n3o6RiTRf0/s400/img22.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708106476568306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-kLqWLJ36Yro/TcfsVP6XhhI/AAAAAAAAARw/EIU7zTFV7vQ/s1600/img23.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-kLqWLJ36Yro/TcfsVP6XhhI/AAAAAAAAARw/EIU7zTFV7vQ/s400/img23.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708111078622738" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-x1hB5CE16Zs/TcfsVY0R6aI/AAAAAAAAAR4/Cfpnb0NZB6M/s1600/img24.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-x1hB5CE16Zs/TcfsVY0R6aI/AAAAAAAAAR4/Cfpnb0NZB6M/s400/img24.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708113469008290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-8x80ujicGdM/TcfsVvv3YGI/AAAAAAAAASA/_r-Tkvf5iy8/s1600/img25.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-8x80ujicGdM/TcfsVvv3YGI/AAAAAAAAASA/_r-Tkvf5iy8/s400/img25.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708119624507490" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-rdfbvokdYd0/Tcfs04BfEtI/AAAAAAAAASI/ZroqoBkmoWM/s1600/img26.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-rdfbvokdYd0/Tcfs04BfEtI/AAAAAAAAASI/ZroqoBkmoWM/s400/img26.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708654421840594" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-wkjPFtwllBQ/Tcfs1MA8X8I/AAAAAAAAASQ/FWHebwfpnWs/s1600/img27.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-wkjPFtwllBQ/Tcfs1MA8X8I/AAAAAAAAASQ/FWHebwfpnWs/s400/img27.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708659788275650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-E6iOY8u_8cQ/Tcfs1C58_sI/AAAAAAAAASY/hie8cs63SUs/s1600/img28.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-E6iOY8u_8cQ/Tcfs1C58_sI/AAAAAAAAASY/hie8cs63SUs/s400/img28.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708657343037122" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-R-lfqMfTs1k/Tcfs1U7N60I/AAAAAAAAASg/eePYfRT0CxQ/s1600/img29.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-R-lfqMfTs1k/Tcfs1U7N60I/AAAAAAAAASg/eePYfRT0CxQ/s400/img29.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708662180178754" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-8yuDzBSjWvs/Tcfs1T9bm-I/AAAAAAAAASo/FsywB9aijNE/s1600/img30.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-8yuDzBSjWvs/Tcfs1T9bm-I/AAAAAAAAASo/FsywB9aijNE/s400/img30.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708661921029090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-IRw9k1m7AA8/TcftHVzBWLI/AAAAAAAAASw/moIY0W52k8Y/s1600/img31.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-IRw9k1m7AA8/TcftHVzBWLI/AAAAAAAAASw/moIY0W52k8Y/s400/img31.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708971651881138" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Jr2J86404TM/TcftHis9AcI/AAAAAAAAAS4/52O_ON0kSK4/s1600/img32.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-Jr2J86404TM/TcftHis9AcI/AAAAAAAAAS4/52O_ON0kSK4/s400/img32.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708975116091842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-5WE713RTWfc/TcftHnTlt5I/AAAAAAAAATA/af0tCe4eW3M/s1600/img33.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-5WE713RTWfc/TcftHnTlt5I/AAAAAAAAATA/af0tCe4eW3M/s400/img33.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708976351885202" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-vW4r-f0NCl4/TcftIJa1qRI/AAAAAAAAATI/JfgwIuMyJcQ/s1600/img34.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-vW4r-f0NCl4/TcftIJa1qRI/AAAAAAAAATI/JfgwIuMyJcQ/s400/img34.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708985509095698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-c3T8nkaTMpg/TcftIKxrHVI/AAAAAAAAATQ/Fnn6QJL8Fbc/s1600/img35.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-c3T8nkaTMpg/TcftIKxrHVI/AAAAAAAAATQ/Fnn6QJL8Fbc/s400/img35.jpg" alt="" id="BLOGGER_PHOTO_ID_5604708985873309010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-ar0rNCCVSjY/TcftTzIQxrI/AAAAAAAAATY/CgYgzMHSmeE/s1600/img36.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-ar0rNCCVSjY/TcftTzIQxrI/AAAAAAAAATY/CgYgzMHSmeE/s400/img36.jpg" alt="" id="BLOGGER_PHOTO_ID_5604709185684031154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-co1sT59PsuI/TcftUAaEsaI/AAAAAAAAATg/XqdB1T6RKXw/s1600/img37.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-co1sT59PsuI/TcftUAaEsaI/AAAAAAAAATg/XqdB1T6RKXw/s400/img37.jpg" alt="" id="BLOGGER_PHOTO_ID_5604709189248397730" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-5ORlcLo-mlc/TcftUV1pAGI/AAAAAAAAATo/As3vp4K8k78/s1600/img38.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-5ORlcLo-mlc/TcftUV1pAGI/AAAAAAAAATo/As3vp4K8k78/s400/img38.jpg" alt="" id="BLOGGER_PHOTO_ID_5604709195001167970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-_mDlnQ31L98/TcftUvab8wI/AAAAAAAAATw/DB-3TRQE77E/s1600/img39.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-_mDlnQ31L98/TcftUvab8wI/AAAAAAAAATw/DB-3TRQE77E/s400/img39.jpg" alt="" id="BLOGGER_PHOTO_ID_5604709201866388226" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-s0JFnpczeXQ/TcftVHUO8TI/AAAAAAAAAT4/PJc6nh1jMoI/s1600/img40.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-s0JFnpczeXQ/TcftVHUO8TI/AAAAAAAAAT4/PJc6nh1jMoI/s400/img40.jpg" alt="" id="BLOGGER_PHOTO_ID_5604709208282820914" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6880201179325138320?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6880201179325138320/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2011/05/cassandra-rompendo-o-paradigma.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6880201179325138320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6880201179325138320'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2011/05/cassandra-rompendo-o-paradigma.html' title='Cassandra: Rompendo o Paradigma Relacional com NoSQL'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-mK9aIzgV2CQ/TcfqZxyUEQI/AAAAAAAAAPA/Aaxe-Y0HSAU/s72-c/img1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8871504247171905465</id><published>2010-12-21T06:06:00.000-08:00</published><updated>2010-12-21T06:50:25.147-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Buscar diferenças entre diretórios</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Eis um problema que já tive que enfrentar diversas vezes: alterar um parâmetro de configuração que não sabia onde estava! Ou ainda: investigar o que foi alterado em algo que antes funcionava e passou a dar problema.&lt;br /&gt;&lt;br /&gt;Como na informática tudo gira em torno de 0s e 1s, se algo mudou, tem que haver diferença entre arquivos e ou diretórios. Digamos que você possua dois diretórios contendo parâmetros de configuração de determinado software. Um deles funciona, o outro não. Como saber o que há de diferente entre eles?&lt;br /&gt;&lt;br /&gt;Richard Stallman, junto com outros colaboradores da GNU nos proveu o utilitário &lt;b&gt;diff&lt;/b&gt; no Linux (ou melhor, GNU/Linux), o qual permite a comparação entre dois arquivos de texto ou binários. O problema é que esse comando precisa ser invocado para cada par de arquivos, o que pode se tornar um complexo "trabalho de estagiário" dependendo da quantidade de subdiretórios e arquivos considerados.&lt;br /&gt;&lt;br /&gt;Para atacar essa questão, criei o script em Shell &lt;b&gt;diffdirs.sh&lt;/b&gt; contendo o código a seguir:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;if [ $# -ne 2 ]&lt;br /&gt;then&lt;br /&gt;    echo "Uso: $0 &amp;lt;dir1&amp;gt; &amp;lt;dir2&amp;gt;"&lt;br /&gt;    exit 1&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;dir1="$1"&lt;br /&gt;dir2="$2"&lt;br /&gt;list="/tmp/$$.list"&lt;br /&gt;cont="/tmp/$$.cont"&lt;br /&gt;&lt;br /&gt;cd $dir1&lt;br /&gt;find -type f | sed 's/^\.\///' &amp;gt; $list&lt;br /&gt;cd - &amp;gt; /dev/null&lt;br /&gt;&lt;br /&gt;echo "Analisando diferenças entre diretórios:"&lt;br /&gt;echo "- $dir1"&lt;br /&gt;echo "- $dir2"&lt;br /&gt;&lt;br /&gt;while read arq&lt;br /&gt;do&lt;br /&gt;    if ! diff $dir1/$arq $dir2/$arq &amp;gt; $cont&lt;br /&gt;    then&lt;br /&gt;        echo -e "\n$arq:"&lt;br /&gt;        cat $cont&lt;br /&gt;    fi&lt;br /&gt;done &amp;lt; $list&lt;br /&gt;&lt;br /&gt;rm -f $list $cont&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No caso em questão, precisava saber em qual diretório e arquivo residia uma configuração específica da IDE Eclipse. Como não dispunha de ambiente gráfico, a opção foi fazer tudo em modo texto. E esse script resolveu o problema! Veja o resultado exibido após a sua execução:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ ./diffdirs.sh &lt;br /&gt;Uso: ./diffdirs.sh &amp;lt;dir1&amp;gt; &amp;lt;dir2&amp;gt;&lt;br /&gt;&lt;br /&gt;$ ./diffdirs.sh ws35a/ ws35b/&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Analisando diferenças entre diretórios:&lt;br /&gt;- ws35a&lt;br /&gt;- ws35b&lt;br /&gt;&lt;br /&gt;.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache:&lt;br /&gt;Os arquivos binários ws35a/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache e ws35b/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache são diferentes&lt;br /&gt;&lt;br /&gt;.metadata/.plugins/org.eclipse.core.runtime/.settings/org.maven.ide.eclipse.prefs:&lt;br /&gt;1c1&lt;br /&gt;&amp;lt; #Tue Dec 21 09:47:38 AMT 2010&lt;br /&gt;---&lt;br /&gt;&amp;gt; #Tue Dec 21 09:48:27 AMT 2010&lt;br /&gt;3d2&lt;br /&gt;&amp;lt; eclipse.m2.downloadSources=true&lt;br /&gt;10d8&lt;br /&gt;&amp;lt; eclipse.m2.downloadJavadoc=true&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora é só copiar o script para um diretório no PATH do usuário. :D&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8871504247171905465?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8871504247171905465/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/12/buscar-diferencas-entre-diretorios.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8871504247171905465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8871504247171905465'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/12/buscar-diferencas-entre-diretorios.html' title='Buscar diferenças entre diretórios'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8800807014270219074</id><published>2010-09-24T07:17:00.000-07:00</published><updated>2010-09-24T07:48:58.903-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><title type='text'>Assembling a local Cassandra cluster in Linux</title><content type='html'>&lt;br/&gt;&lt;br /&gt;In order to build a &lt;b&gt;Apache Cassandra&lt;/b&gt; [1] cluster exclusively for availability and replication testings, here is a simple solution, based on a single Linux instance, with no virtualization at all.&lt;br /&gt;&lt;br /&gt;The idea is to initialize every node, run a testing client, and then manually kill some nodes processes in order to check the service continuous availability and data replication with several replication factors.&lt;br /&gt;&lt;br /&gt;Cassandra's last stable version at this post date was 0.6.5, and this is the released considered in the study.&lt;br /&gt;&lt;br /&gt;Thinking of a cluster using 3 nodes, we'll create the following file system structure on Linux:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;/opt/apache-cassandra-0.6.5/nodes&lt;br /&gt;|&lt;br /&gt;|-- node1&lt;br /&gt;|   |-- bin&lt;br /&gt;|   |-- conf&lt;br /&gt;|   |-- data&lt;br /&gt;|   |-- log&lt;br /&gt;|   `-- txs&lt;br /&gt;|&lt;br /&gt;|-- node2&lt;br /&gt;|   |-- bin&lt;br /&gt;|   |-- conf&lt;br /&gt;|   |-- data&lt;br /&gt;|   |-- log&lt;br /&gt;|   `-- txs&lt;br /&gt;|&lt;br /&gt;`-- node3&lt;br /&gt;    |-- bin&lt;br /&gt;    |-- conf&lt;br /&gt;    |-- data&lt;br /&gt;    |-- log&lt;br /&gt;    `-- txs&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That is, each node has its own set of directories, namely:&lt;br /&gt;- bin: binaries (mostly Shell Scripts) tuned for the instance&lt;br /&gt;- conf: configuration files for the node&lt;br /&gt;- data: database binary files&lt;br /&gt;- log: system log in text format&lt;br /&gt;- txs: transaction logs (i.e. commit logs)&lt;br /&gt;&lt;br /&gt;In the following sections the steps will be described in detail.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Cassandra installation&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;First of all, get the required packages for Cassandra from its &lt;a href="http://cassandra.apache.org/download" target="new"&gt;download site&lt;/a&gt;. Extract the file contents into &lt;b&gt;/opt/apache-cassandra-0.6.5/&lt;/b&gt; directory (you'll need administrator privileges in order to do so). Make sure your regular user owns this entire directory tree (use chown if needed).&lt;br /&gt;&lt;br /&gt;Certify that you already has Java Virtual Machine (JVM) installed on the system, at least version 1.6. Cassandra is implemented in Java, so it needs JVM to be executed.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Supplying additional network interfaces&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;As we are building a pseudo-cluster, consider there are no more network interfaces than existing ones. Since Cassandra is a distributed system, their participant nodes must have an exclusive IP address each one. Fortunately we can simulate it on Linux using aliases to the existent loopback interface (i.e., "lo").&lt;br /&gt;&lt;br /&gt;Therefore, using root user, we'll issue the instructions below in order to create the aliases lo:2 and lo:3, respectively pointing to 127.0.0.2 and 127.0.0.3:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# ifconfig lo:2 127.0.0.2 up&lt;br /&gt;# ifconfig lo:3 127.0.0.3 up&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can check the overcome of these instructions by invoking ifconfig using no arguments:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ ifconfig&lt;br /&gt;lo        Link encap:Local Loopback&lt;br /&gt;          inet addr:127.0.0.1  Mask:255.0.0.0&lt;br /&gt;          inet6 addr: ::1/128 Scope:Host&lt;br /&gt;          UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;          RX packets:30848 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;          TX packets:30848 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;          collisions:0 txqueuelen:0&lt;br /&gt;          RX bytes:2946793 (2.9 MB)  TX bytes:2946793 (2.9 MB)&lt;br /&gt;&lt;br /&gt;lo:2      Link encap:Local Loopback&lt;br /&gt;          inet addr:127.0.0.2  Mask:255.0.0.0&lt;br /&gt;          UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;&lt;br /&gt;lo:3      Link encap:Local Loopback&lt;br /&gt;          inet addr:127.0.0.3  Mask:255.0.0.0&lt;br /&gt;          UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That way, node1's IP is 127.0.0.1, node2's 127.0.0.2, and so forth.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Registering node hostnames locally&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Instead of using IP addresses in the sequential steps, we'll assign hostnames to them and use those names when referencing a cluster node.&lt;br /&gt;&lt;br /&gt;As we have no DNS in this configuration, we need to edit &lt;b&gt;/etc/hosts&lt;/b&gt; file and assign those IP mappings there. Change this file according to the example below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;/etc/hosts:&lt;br /&gt;127.0.0.1    localhost    node1&lt;br /&gt;127.0.0.2    node2&lt;br /&gt;127.0.0.3    node3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;From now on, we'll call the nodes simply as node1, node2, and node3. In order to finally test hostnames, try pinging the nodes as exemplified:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ ping node2&lt;br /&gt;PING node2 (127.0.0.2) 56(84) bytes of data.&lt;br /&gt;64 bytes from node2 (127.0.0.2): icmp_seq=1 ttl=64 time=0.018 ms&lt;br /&gt;64 bytes from node2 (127.0.0.2): icmp_seq=2 ttl=64 time=0.015 ms&lt;br /&gt;^C&lt;br /&gt;--- node2 ping statistics ---&lt;br /&gt;2 packets transmitted, 2 received, 0% packet loss, time 999ms&lt;br /&gt;rtt min/avg/max/mdev = 0.015/0.016/0.018/0.004 ms&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating the first node structure&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;We'll first create the directory structure for node1 and after replicate it to remaining nodes. Switch to Cassandra's root directory, create subdirectories and copy files by issuing the following shell commands using your regular Linux user:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ cd /opt/apache-cassandra-0.6.5/&lt;br /&gt;$ mkdir -p nodes/node1&lt;br /&gt;$ cp -R bin/ conf/ nodes/node1/&lt;br /&gt;$ cd nodes/node1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The next step is to modify some default settings in the configuration files. Here I opted to use relative paths instead of absolute paths for simplification purposes.&lt;br /&gt;&lt;br /&gt;Edit a single line in &lt;b&gt;conf/log4j.properties&lt;/b&gt; file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# Edit the next line to point to your logs directory&lt;br /&gt;log4j.appender.R.File=./log/system.log&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now in &lt;b&gt;conf/storage-conf.xml&lt;/b&gt; several tag values must be changed. Be sure to modify the correct tags, as indicated below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;  &amp;lt;Keyspaces&amp;gt;&lt;br /&gt;    &amp;lt;Keyspace Name="Keyspace1"&amp;gt;&lt;br /&gt;      ...&lt;br /&gt;&lt;br /&gt;      &amp;lt;ReplicationFactor&amp;gt;2&amp;lt;/ReplicationFactor&amp;gt;&lt;br /&gt;      ...&lt;br /&gt;&lt;br /&gt;    &amp;lt;/Keyspace&amp;gt;&lt;br /&gt;  &amp;lt;Keyspaces&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;CommitLogDirectory&amp;gt;./txs&amp;lt;/CommitLogDirectory&amp;gt;&lt;br /&gt;  &amp;lt;DataFileDirectories&amp;gt;&lt;br /&gt;      &amp;lt;DataFileDirectory&amp;gt;./data&amp;lt;/DataFileDirectory&amp;gt;&lt;br /&gt;  &amp;lt;/DataFileDirectories&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;ListenAddress&amp;gt;node1&amp;lt;/ListenAddress&amp;gt;&lt;br /&gt;  &amp;lt;StoragePort&amp;gt;7000&amp;lt;/StoragePort&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;ThriftAddress&amp;gt;&amp;lt;/ThriftAddress&amp;gt;&lt;br /&gt;  &amp;lt;ThriftPort&amp;gt;9160&amp;lt;/ThriftPort&amp;gt;&lt;br /&gt;  &amp;lt;ThriftFramedTransport&amp;gt;false&amp;lt;/ThriftFramedTransport&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As we are building a special directory arrangement, we'll need to adequate some paths in the scripts. Thus, edit the file &lt;b&gt;bin/cassandra.in.sh&lt;/b&gt; by providing the lines below appropriately:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;for jar in $cassandra_home/../../lib/*.jar; do&lt;br /&gt;    CLASSPATH=$CLASSPATH:$jar&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first node is finally concluded. So, let's turn our attentions to the other two nodes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating the remaining nodes&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;We are gonna take advantage of the first node directory structure to create the two remaining nodes. Thus, issue the instructions below in order to perform the cloning:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ cd /opt/apache-cassandra-0.6.5/nodes/&lt;br /&gt;$ mkdir node2 node3&lt;br /&gt;$ cp -R node1/* node2&lt;br /&gt;$ cp -R node1/* node3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When you're done, call a tree command (if available) as illustrated below to check the whole structure:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ tree -L 2&lt;br /&gt;.&lt;br /&gt;|-- node1&lt;br /&gt;|   |-- bin&lt;br /&gt;|   `-- conf&lt;br /&gt;|-- node2&lt;br /&gt;|   |-- bin&lt;br /&gt;|   `-- conf&lt;br /&gt;`-- node3&lt;br /&gt;    |-- bin&lt;br /&gt;    `-- conf&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you compare this structure to the other one in the beginning of this article, you should note that there are some subdirectories missing (i.e., log, data, txs). That's because they will be created automatically when the server starts up the first time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Final settings on nodes&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The first node is deemed a contact point, i.e., a seed. Other nodes should start the Gossip-based protocol by connecting to it.&lt;br /&gt;&lt;br /&gt;Besides, we should make specific settings on each node. Firstly, each node must listen to it's own hostname (i.e., node1, node2, node3). Thus, edit the &lt;b&gt;nodeX/conf/storage-conf.xml&lt;/b&gt; for each node by replacing the line below (this example applies to node2):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;  &amp;lt;ListenAddress&amp;gt;node2&amp;lt;/ListenAddress&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Monitoring on Cassandra is provided through JMX, listening to every host by default on TCP port 8080. As we are building the cluster on the same real instance, this is not possible anymore. Thus, JMX interfaces must be bound to the same host, but we must change the port on each node. Therefore, first node will be listening on 8081, node2 on 8082, and node3 on 8083.&lt;br /&gt;&lt;br /&gt;This parameter is configured in &lt;b&gt;nodeX/bin/cassandra.in.sh&lt;/b&gt;, so we must change only the port as exemplified below (applying to node2):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# Arguments to pass to the JVM&lt;br /&gt;JVM_OPTS=" \&lt;br /&gt;        -ea \&lt;br /&gt;        -Xms1G \&lt;br /&gt;        -Xmx1G \&lt;br /&gt;        -XX:+UseParNewGC \&lt;br /&gt;        -XX:+UseConcMarkSweepGC \&lt;br /&gt;        -XX:+CMSParallelRemarkEnabled \&lt;br /&gt;        -XX:SurvivorRatio=8 \&lt;br /&gt;        -XX:MaxTenuringThreshold=1 \&lt;br /&gt;        -XX:+HeapDumpOnOutOfMemoryError \&lt;br /&gt;        -Dcom.sun.management.jmxremote.port=8082 \&lt;br /&gt;        -Dcom.sun.management.jmxremote.ssl=false \&lt;br /&gt;        -Dcom.sun.management.jmxremote.authenticate=false"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Starting up every server&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;For this step it is very interesting to open a new Linux terminal for each node. Thus, issue the instructions below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ node1/bin/cassandra -f&lt;br /&gt;&lt;br /&gt;$ node2/bin/cassandra -f&lt;br /&gt;&lt;br /&gt;$ node3/bin/cassandra -f&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pay attention to the console output on each node. A simple misconfiguration will be related there. Also note the relationship between the nodes. They must discover one another automatically in seconds.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Check services availability&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Since every node in the cluster is up and running, their respective TCP ports must appear to the system when executing a &lt;b&gt;netstat&lt;/b&gt; command.&lt;br /&gt;&lt;br /&gt;In order to check listening TCP ports on Cassandra, one must search for 9160 (Thrift service), 7000 (internal storage), and 808X (JMX interface). Take a look at the example below of a successful cluster startup.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ netstat -lptn&lt;br /&gt;Active Internet connections (only servers)&lt;br /&gt;Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name&lt;br /&gt;tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -             &lt;br /&gt;tcp6       0      0 127.0.0.3:9160          :::*                    LISTEN      8520/java     &lt;br /&gt;tcp6       0      0 127.0.0.2:9160          :::*                    LISTEN      8424/java     &lt;br /&gt;tcp6       0      0 127.0.0.1:9160          :::*                    LISTEN      8336/java     &lt;br /&gt;tcp6       0      0 :::46954                :::*                    LISTEN      8424/java     &lt;br /&gt;tcp6       0      0 :::53418                :::*                    LISTEN      8336/java     &lt;br /&gt;tcp6       0      0 :::49035                :::*                    LISTEN      8520/java     &lt;br /&gt;tcp6       0      0 :::80                   :::*                    LISTEN      -             &lt;br /&gt;tcp6       0      0 :::42737                :::*                    LISTEN      8520/java     &lt;br /&gt;tcp6       0      0 :::8081                 :::*                    LISTEN      8336/java     &lt;br /&gt;tcp6       0      0 :::8082                 :::*                    LISTEN      8424/java     &lt;br /&gt;tcp6       0      0 :::8083                 :::*                    LISTEN      8520/java     &lt;br /&gt;tcp6       0      0 :::60310                :::*                    LISTEN      8424/java     &lt;br /&gt;tcp6       0      0 :::46167                :::*                    LISTEN      8336/java     &lt;br /&gt;tcp6       0      0 ::1:631                 :::*                    LISTEN      -             &lt;br /&gt;tcp6       0      0 127.0.0.3:7000          :::*                    LISTEN      8520/java     &lt;br /&gt;tcp6       0      0 127.0.0.2:7000          :::*                    LISTEN      8424/java     &lt;br /&gt;tcp6       0      0 127.0.0.1:7000          :::*                    LISTEN      8336/java     &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The last test was from a network perspective. You might want to ask Cassandra whether these nodes are talking to each other and participating on a healthy partitioning scheme. In order to do so, another checking is to invoke nodetool's ring command.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ cd /opt/apache-cassandra-0.6.5/&lt;br /&gt;&lt;br /&gt;$ ./bin/nodetool -h localhost -p 8081 ring&lt;br /&gt;Address       Status     Load          Range                                      Ring&lt;br /&gt;                                       142865723918937898194528652808268231850  &lt;br /&gt;127.0.0.1     Up         3,1 KB        39461784941927371686416024510057184051     |&amp;lt;--|&lt;br /&gt;127.0.0.3     Up         3,1 KB        54264004217607518447601711663387808864     |   |&lt;br /&gt;127.0.0.2     Up         2,68 KB       142865723918937898194528652808268231850    |--&amp;gt;|&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here it is, the local cluster is up and running with three nodes! :D&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/TJy3K0wshLI/AAAAAAAAAOI/ogAvf8Ckq3k/s1600/cassandra-ring2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 229px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/TJy3K0wshLI/AAAAAAAAAOI/ogAvf8Ckq3k/s320/cassandra-ring2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5520488639838848178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can also check Cassandra's availability by using its simple client application:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ ./bin/cassandra-cli --host node1 --port 9160&lt;br /&gt;Connected to: "Test Cluster" on node1/9160&lt;br /&gt;Welcome to cassandra CLI.&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; set Keyspace1.Standard1['rowkey']['column'] = 'value'&lt;br /&gt;Value inserted.&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get Keyspace1.Standard1['rowkey']['column']          &lt;br /&gt;=&amp;gt; (column=636f6c756d6e, value=value, timestamp=1285273581745000)&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get Keyspace1.Standard1['rowkey']          &lt;br /&gt;=&amp;gt; (column=636f6c756d6e, value=value, timestamp=1285273581745000)&lt;br /&gt;Returned 1 results.&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; del Keyspace1.Standard1['rowkey']                    &lt;br /&gt;row removed.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As we set replication factor to 2 for this given keyspace Keyspace1, it is expected that each value saved in the Cassandra cluster is replicated to two nodes.&lt;br /&gt;&lt;br /&gt;Do you really believe it is happening? If not, save another value (using &lt;i&gt;set&lt;/i&gt;) and then kill one of the three node processes. Do not kill more than one! Then, retrieve that key again (using &lt;i&gt;get&lt;/i&gt;). The system should be capable of automatically recovering from this intentional disaster.&lt;br /&gt;&lt;br /&gt;You can easily make a node participate in the cluster again just by executing its respective &lt;b&gt;bin/cassandra&lt;/b&gt; command. Take a look at all console outputs after every step, they are very interesting!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;References&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;[1] &lt;a title="Apache Cassandra" href="http://cassandra.apache.org/" target="_blank"&gt;Apache Cassandra&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8800807014270219074?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8800807014270219074/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/assembling-local-cassandra-cluster-in.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8800807014270219074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8800807014270219074'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/assembling-local-cassandra-cluster-in.html' title='Assembling a local Cassandra cluster in Linux'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YGilJHLjrrI/TJy3K0wshLI/AAAAAAAAAOI/ogAvf8Ckq3k/s72-c/cassandra-ring2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-94682448752770201</id><published>2010-09-17T10:30:00.000-07:00</published><updated>2010-10-14T06:56:05.002-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>PGDay Manaus 2010</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://1.bp.blogspot.com/_YGilJHLjrrI/TJOmPjlFWWI/AAAAAAAAAOA/FpZ6AczSHDo/s400/pgday-am-2010.gif" alt="PGDay AM 2010" id="BLOGGER_PHOTO_ID_5517936754638018914" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;No dia &lt;span style="font-weight: bold;"&gt;15 de outubro&lt;/span&gt; ocorrerá o &lt;span style="font-weight: bold;"&gt;PGDay Manaus 2010&lt;/span&gt; na Universidade Federal do Amazonas (UFAM), em Manaus.&lt;br /&gt;&lt;br /&gt;Trata-se de um dia inteiro dedicado ao SGBD PostgreSQL, contendo oficinas, palestras e mostras de trabalhos.&lt;br /&gt;&lt;br /&gt;Para maiores informações, consulte o site do evento:&lt;br /&gt;&lt;a href="http://www.postgresql.org.br/eventos/pgday/am/2010"&gt;http://www.postgresql.org.br/eventos/pgday/am/2010&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As inscrições já estão abertas nessa mesma página, participe! :D&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/TLcG_PCzA-I/AAAAAAAAAOQ/l4IPhB5VWUY/s1600/ufam-campus2b.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 234px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/TLcG_PCzA-I/AAAAAAAAAOQ/l4IPhB5VWUY/s320/ufam-campus2b.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5527894751060362210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-94682448752770201?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/94682448752770201/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/pgday-manaus-2010.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/94682448752770201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/94682448752770201'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/pgday-manaus-2010.html' title='PGDay Manaus 2010'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/TJOmPjlFWWI/AAAAAAAAAOA/FpZ6AczSHDo/s72-c/pgday-am-2010.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4936678584059996979</id><published>2010-09-14T08:59:00.000-07:00</published><updated>2010-09-14T10:20:03.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='snmp'/><category scheme='http://www.blogger.com/atom/ns#' term='virtualbox'/><title type='text'>Monitorando serviços com SNMP e Zabbix</title><content type='html'>&lt;h3 class="western" style="page-break-before: always;"&gt;&lt;br /&gt;&lt;/h3&gt;&lt;h3 class="western" style="page-break-before: always;"&gt;&lt;span style="font-style: normal;"&gt;Inicialização do servidor SNMP e coleta da rede&lt;/span&gt;&lt;/h3&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Entre no terminal da máquina virtual e &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;inicialize o serviço SNMP &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;nela através do comando:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# service snmpd restart&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Ainda no terminal, execute os comandos &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;snmpget&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;snmpgetnext &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;e &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;snmpwalk &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;a fim de testar o cliente e servidor SNMP fornecido pela implementação do Net-SNMP:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpget -v 1 -c public localhost sysDescr.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpget -v 1 -c public localhost system.sysName.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpget -v 1 -c public localhost ifDescr.2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpgetnext -v 1 -c public localhost interfaces&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpgetnext -v 1 -c public localhost host&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpgetnext -v 1 -c public localhost snmpV2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpwalk -v 1 -c public localhost system&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpwalk -v 1 -c public localhost interfaces&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Repita os comandos anteriores utilizando os parâmetros &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;-On&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;-Os&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt; e &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;-Of&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Volte ao frontend do Zabbix e inclua um item com as seguintes configurações:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;eth0  in/s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;SNMPv1  agent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  OID: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;interfaces.ifTable.ifEntry.ifInOctets.2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  community: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  port: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;161&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;eth0.in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type  of information: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Numeric  (unsigned)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Store  value: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Delta  (speed per second)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-sp7vGa6I/AAAAAAAAANg/x-3BZeX7JdU/s1600/zbx-eth0in.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 318px; height: 320px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-sp7vGa6I/AAAAAAAAANg/x-3BZeX7JdU/s320/zbx-eth0in.png" alt="" id="BLOGGER_PHOTO_ID_5516817904962005922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Repita a operação para incluir este outro indicador:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;eth0  out/s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;SNMPv1  agent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  OID: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;ifOutOctets.2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  community: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  port: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;161&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;eth0.out&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type  of information: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Numeric  (unsigned)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Store  value: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Delta  (speed per second)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Aguarde alguns minutos e então acesse o menu &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;Monitoring &gt; Latest data&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt; e abra os gráficos correspondente as coletas dos indicadores recém-criados:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r7LsldGI/AAAAAAAAANY/qrjuuLxyH1g/s1600/zbx-cpuloadgr.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 111px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r7LsldGI/AAAAAAAAANY/qrjuuLxyH1g/s320/zbx-cpuloadgr.png" alt="" id="BLOGGER_PHOTO_ID_5516817101792572514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;h3 class="western" style="page-break-before: always;"&gt;&lt;span style="font-style: normal;"&gt;Coleta da carga da CPU e gráficos customizados&lt;/span&gt;&lt;/h3&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Entre no terminal da máquina virtual e explore a &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;UCD-MIB &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;executando os comandos a seguir:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpwalk -v 1 -c public localhost ucdavis | less&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpbulkget -v 2c -c public localhost -C r3 laNames laLoadInt -Os&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Observe a carga média dos processadores executando as instruções a seguir:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# uptime&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# snmpwalk -v 1 -c public localhost laLoadInt -Os&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Provoque o aumento no consumo de CPU executando diversas vezes o comando abaixo:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# cat /dev/urandom | md5sum &amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Dica:  para cancelar a execução desses processos, utilize os comandos  &lt;span style="font-family:Andale Mono;"&gt;jobs&lt;/span&gt; e &lt;span style="font-family:Andale Mono;"&gt;kill&lt;/span&gt;  do Linux.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;De volta ao frontend do Zabbix, cadastre o seguinte indicador para o host:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;cpu  load-1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;SNMPv1  agent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  OID: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.1    &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;i&gt;&lt;span style="font-weight: normal;"&gt;(pode  ser OID completo – textual ou numérico)&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP community:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP port: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;161&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type of information:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Numeric  (float)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Use multiplier:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Custom  multiplier&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;Custom multiplier: &lt;/b&gt;&lt;span style="font-weight: normal;"&gt;0.01&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r6XAoeBI/AAAAAAAAANI/Lw7mxyYUB7w/s1600/zbx-load1.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 217px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r6XAoeBI/AAAAAAAAANI/Lw7mxyYUB7w/s320/zbx-load1.png" alt="" id="BLOGGER_PHOTO_ID_5516817087649576978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; page-break-before: always;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Utilizando a funcionalidade de clonagem de indicadores, crie mais dois indicadores alterando apenas os campos indicados abaixo:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;cpu  load-5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  OID: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;cpu  load-15&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;SNMP  OID: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm; font-style: normal;" align="LEFT"&gt;  &lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;laLoadInt.3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm; font-style: normal; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Acesse o menu &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Configuration &gt; Hosts&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt; e crie um novo gráfico contendo os três indicadores de carga de CPU recém incluídos para o host:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r6_VuKgI/AAAAAAAAANQ/oYZoYx8Pxr4/s1600/zbx-newgraph.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 230px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-r6_VuKgI/AAAAAAAAANQ/oYZoYx8Pxr4/s320/zbx-newgraph.png" alt="" id="BLOGGER_PHOTO_ID_5516817098475448834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Acesse o menu &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Monitoring &gt; Latest data&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt; e o menu &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Monitoring &gt; Graphs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt; para acompanhar a evolução da coleta destes indicadores:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm; font-weight: normal;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-sqG9ttcI/AAAAAAAAANo/odne9PsitSY/s1600/zbx-eth0gr.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 257px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-sqG9ttcI/AAAAAAAAANo/odne9PsitSY/s320/zbx-eth0gr.png" alt="" id="BLOGGER_PHOTO_ID_5516817907976091074" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Referências&lt;/b&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;/p&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;VirtualBox:  &lt;a href="http://www.virtualbox.org/"&gt;http://www.virtualbox.org/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Net-SNMP:  &lt;a href="http://www.net-snmp.org/"&gt;http://www.net-snmp.org/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Zabbix:  &lt;a href="http://www.zabbix.org/"&gt;http://www.zabbix.org/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Ubuntu  VirtualBox: &lt;a href="https://help.ubuntu.com/community/VirtualBox"&gt;https://help.ubuntu.com/community/VirtualBox&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Zabbix  Appliance:  &lt;a href="http://www.zabbix.com/documentation/1.8/manual/installation/appliance"&gt;http://www.zabbix.com/documentation/1.8/manual/installation/appliance&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4936678584059996979?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4936678584059996979/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/monitorando-servicos-com-snmp-e-zabbix.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4936678584059996979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4936678584059996979'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/monitorando-servicos-com-snmp-e-zabbix.html' title='Monitorando serviços com SNMP e Zabbix'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YGilJHLjrrI/TI-sp7vGa6I/AAAAAAAAANg/x-3BZeX7JdU/s72-c/zbx-eth0in.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-9103339036284647806</id><published>2010-09-14T08:14:00.000-07:00</published><updated>2010-09-14T10:02:36.683-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='virtualbox'/><title type='text'>Testando Zabbix Appliance com VirtualBox</title><content type='html'>&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Baixe a partir do endereço a seguir o&lt;b&gt; pacote Debian&lt;/b&gt; adequado a sua distribuição Linux:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://www.virtualbox.org/wiki/Linux_Downloads"&gt;http://www.virtualbox.org/wiki/Linux_Downloads&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Instale o pacote via &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;DPKG&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt; utilizando as instruções abaixo:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# dpkg -i virtualbox-*.deb&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# apt-get -f install&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Baixe a imagem ISO do &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Zabbix Appliance&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt; a partir do endereço a seguir:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://www.zabbix.com/download.php"&gt;http://www.zabbix.com/download.php&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l1eakM4I/AAAAAAAAAMI/Lcipu3loT2o/s1600/zbx-appliance.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 133px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l1eakM4I/AAAAAAAAAMI/Lcipu3loT2o/s320/zbx-appliance.png" alt="" id="BLOGGER_PHOTO_ID_5516810406668284802" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Execute o VirtualBox e crie uma &lt;b&gt;nova máquina&lt;/b&gt; utilizando os parâmetros seguintes:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Nome:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;  Zabbix 1.8&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Sistema  Operacional:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;  Linux&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Versão:  &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;openSUSE&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Memória:  &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;512 MB&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Disco  rígido:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;  (nenhum)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l1ugTtTI/AAAAAAAAAMQ/29QBhxftifY/s1600/vbox-nova.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 195px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l1ugTtTI/AAAAAAAAAMQ/29QBhxftifY/s320/vbox-nova.png" alt="" id="BLOGGER_PHOTO_ID_5516810410987337010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Clique na máquina recém-criada e associe a &lt;b&gt;imagem ISO&lt;/b&gt; do Zabbix Appliance no &lt;b&gt;drive de CD&lt;/b&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l16jyz0I/AAAAAAAAAMY/0VzvmaDZhYw/s1600/vbox-cdiso.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 178px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l16jyz0I/AAAAAAAAAMY/0VzvmaDZhYw/s320/vbox-cdiso.png" alt="" id="BLOGGER_PHOTO_ID_5516810414223183682" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Configure a &lt;b&gt;rede &lt;/b&gt;para utilizar a opção &lt;b&gt;“host-only”&lt;/b&gt; e a &lt;b&gt;interface “vboxnet0”&lt;/b&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/TI-l2AIo-zI/AAAAAAAAAMg/fub6TGp2yw8/s1600/vbox-net.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 178px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/TI-l2AIo-zI/AAAAAAAAAMg/fub6TGp2yw8/s320/vbox-net.png" alt="" id="BLOGGER_PHOTO_ID_5516810415719906098" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Inicie a nova máquina virtual e aguarde o completo carregamento do sistema operacional.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;No prompt que se abrirá, entre com o &lt;b&gt;usuário “root”&lt;/b&gt; e a &lt;b&gt;senha “zabbix”&lt;/b&gt;&lt;span style="font-weight: normal;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Carregue o mapa de teclados adequado e confira o endereço IP associado à máquina virtual através dos comandos a seguir:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# loadkeys br-abnt2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; background: none repeat scroll 0% 0% rgb(230, 230, 230); font-weight: normal;"&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style=""&gt;&lt;span style="font-size:85%;"&gt;# ifconfig eth0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Anote o endereço IP exibido (ex: 192.168.56.101).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Abra no navegador o endereço HTTP correspondente ao &lt;b&gt;frontend do Zabbix&lt;/b&gt;. Ex:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;a href="http://192.168.56.101/zabbix/"&gt;http://192.168.56.101/zabbix/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Entre na aplicação utilizando o &lt;b&gt;login “Admin”&lt;/b&gt; e a &lt;b&gt;password “zabbix”&lt;/b&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/TI-l2YomKBI/AAAAAAAAAMo/gad-Kiustrc/s1600/zbx-frontend.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 190px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/TI-l2YomKBI/AAAAAAAAAMo/gad-Kiustrc/s320/zbx-frontend.png" alt="" id="BLOGGER_PHOTO_ID_5516810422296389650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Acesse o menu &lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;Configuration &gt; Hosts&lt;/span&gt; e crie um novo host utilizando essas configurações:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Name:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;  Local&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Groups:  &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Linux  servers&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;IP  address:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;  127.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Connect  to:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt; IP  address&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-mMXLQWSI/AAAAAAAAAMw/6-UZ5HQg7WA/s1600/zbx-newhost.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 196px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/TI-mMXLQWSI/AAAAAAAAAMw/6-UZ5HQg7WA/s320/zbx-newhost.png" alt="" id="BLOGGER_PHOTO_ID_5516810799862012194" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Acesse os indicadores do host e inclua um novo conforme indicado a seguir:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Description:  &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;cpu  load&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;  Zabbix agent&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Key:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;  system.cpu.load&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Type  of information: &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: normal;"&gt;Numeric  (float)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/TI-mMnwqORI/AAAAAAAAAM4/MnZnOuAdxWU/s1600/zbx-cpuload.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 239px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/TI-mMnwqORI/AAAAAAAAAM4/MnZnOuAdxWU/s320/zbx-cpuload.png" alt="" id="BLOGGER_PHOTO_ID_5516810804313864466" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Aguarde alguns minutos e então acesse o menu &lt;span style="font-family:DejaVu Sans Mono,monospace;"&gt;Monitoring &gt; Latest data&lt;/span&gt;, procurando pelos dados históricos e gráficos gerados pela coleta do &lt;b&gt;indicador “cpu load”&lt;/b&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ol start="0"&gt;&lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;/p&gt;&lt;/ol&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="LEFT"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/TI-mM9B_III/AAAAAAAAANA/_xs6kniRHGE/s1600/zbx-cpugr.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 257px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/TI-mM9B_III/AAAAAAAAANA/_xs6kniRHGE/s320/zbx-cpugr.png" alt="" id="BLOGGER_PHOTO_ID_5516810810023682178" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Referências&lt;/b&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;/p&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;VirtualBox:  &lt;a href="http://www.virtualbox.org/"&gt;http://www.virtualbox.org/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Zabbix:  &lt;a href="http://www.zabbix.org/"&gt;http://www.zabbix.org/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Ubuntu  VirtualBox: &lt;a href="https://help.ubuntu.com/community/VirtualBox"&gt;https://help.ubuntu.com/community/VirtualBox&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family:Arial,sans-serif;"&gt;&lt;span style="font-size:85%;"&gt;Zabbix  Appliance:  &lt;a href="http://www.zabbix.com/documentation/1.8/manual/installation/appliance"&gt;http://www.zabbix.com/documentation/1.8/manual/installation/appliance&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-9103339036284647806?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/9103339036284647806/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/testando-zabbix-appliance-com.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/9103339036284647806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/9103339036284647806'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/testando-zabbix-appliance-com.html' title='Testando Zabbix Appliance com VirtualBox'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YGilJHLjrrI/TI-l1eakM4I/AAAAAAAAAMI/Lcipu3loT2o/s72-c/zbx-appliance.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-5232113855328913449</id><published>2010-09-02T13:35:00.000-07:00</published><updated>2010-09-02T13:57:42.397-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><title type='text'>Simplifying Cassandra interactions with Helena</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;br /&gt;In the previous article &lt;b&gt;"Talking to Cassandra using Java and DAO pattern"&lt;/b&gt; [1] we saw an introduction to NoSQL-based databases and especially one called &lt;b&gt;Apache Cassandra&lt;/b&gt; [2]. After a quick explanation of its data model, we analyzed what it takes to implement a Java code which goal was to access and yet modify key-value pairs stored on a Cassandra keyspace. At that time we used a low-level interface API named &lt;b&gt;Thrift&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;You might have noticed that a large amount of code was needed to build an entire and yet simple persistence class, namely a structure based on Data Access Object design pattern. If we compare it to currently most used persistence technologies and frameworks in Java (i.e. JPA and Hibernate), we would probably get crazy!&lt;br /&gt;&lt;br /&gt;Is this the price we pay for high-availability and scalability when changing from a traditional relational database model to a newly key-value data store? Poor developers... Well, that's not the end, fortunately! There are already available several high level clients for Cassandra in multiple programming languages (see [3]).&lt;br /&gt;&lt;br /&gt;One of these clients, &lt;b&gt;HelenaORM&lt;/b&gt; [4] (created by Marcus Thiesen), is the study subject this time. As this library is addressed to Java language, our aim will be to implement the persistence of a simple object using Helena's support.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating the entity&lt;/h2&gt;&lt;br /&gt;As in the other article, we'll choose the "group" entity to exemplify our codes. This time, in addition to the plain old Java class elements, in the &lt;b&gt;Group&lt;/b&gt; class we need to annotate it with &lt;b&gt;@HelenaBean&lt;/b&gt; and &lt;b&gt;@KeyProperty&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The annotation &lt;b&gt;@HelenaBean&lt;/b&gt; is used to specify keyspace and column family for the class, whereas &lt;b&gt;@KeyProperty&lt;/b&gt; must indicate which field in the class should be considered the row key in Cassandra - currently annotation only works at getter or setter methods, not in the variable itself. Both annotations are analogous to JPA's @Entity and @Id annotations.&lt;br /&gt;&lt;br /&gt;Take a look at the Group entity class properly prepared to be used by HelenaORM:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;@HelenaBean(keyspace="ContactList", columnFamily="Groups")&lt;br /&gt;public class Group {&lt;br /&gt;&lt;br /&gt;  private Integer id;&lt;br /&gt;  private String name;&lt;br /&gt;&lt;br /&gt;  public Group() {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Group(Integer id, String name) {&lt;br /&gt;      this.id = id;&lt;br /&gt;      this.name = name;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @KeyProperty&lt;br /&gt;  public Integer getId() {&lt;br /&gt;      return id;&lt;br /&gt;  }&lt;br /&gt;  public String getName() {&lt;br /&gt;      return name;&lt;br /&gt;  }&lt;br /&gt;  public void setId(Integer id) {&lt;br /&gt;      this.id = id;&lt;br /&gt;  }&lt;br /&gt;  public void setName(String name) {&lt;br /&gt;      this.name = name;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public String toString() {&lt;br /&gt;      return "Group [id=" + id + ", name=" + name + "]";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Creating the tests&lt;/h2&gt;&lt;br /&gt;The most interesting new is about to come: with Helena there's no need of traditional building a DAO interface and class!&lt;br /&gt;&lt;br /&gt;Helena brings a factory &lt;b&gt;HelenaORMDAOFactory&lt;/b&gt; designed to create ready-to-use DAO classes type-safely pointed to a given entity. The classes it produces, of &lt;b&gt;HelenaDAO&lt;/b&gt; type, provides these methods: &lt;b&gt;insert()&lt;/b&gt;, &lt;b&gt;delete()&lt;/b&gt;, and &lt;b&gt;get()&lt;/b&gt;. They are out-of-box implementations respectively for inserting (or editing), removing, and retrieving entire object instances from Cassandra.&lt;br /&gt;&lt;br /&gt;So, here is the corresponding unitary test class in JUnit reserved for invoking inserts, deletions, and retrievals of Java object instances into Cassandra with the support of Helena:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class GroupTest {&lt;br /&gt;&lt;br /&gt;    static HelenaORMDAOFactory factory;&lt;br /&gt;    private HelenaDAO&amp;lt;Group&amp;gt; dao;&lt;br /&gt;&lt;br /&gt;    private static final Integer GROUP_ID = 123;&lt;br /&gt;    private static final String GROUP_NAME = "Test Group";&lt;br /&gt;&lt;br /&gt;    @BeforeClass&lt;br /&gt;    public static void setUpBeforeClass() throws Exception {&lt;br /&gt;        factory = HelenaORMDAOFactory.withConfig(&lt;br /&gt;                "localhost", 9160, SerializeUnknownClasses.YES);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @AfterClass&lt;br /&gt;    public static void tearDownAfterClass() throws Exception {&lt;br /&gt;        factory = null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void setUp() throws Exception {&lt;br /&gt;        dao = factory.makeDaoForClass(Group.class);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @After&lt;br /&gt;    public void tearDown() throws Exception {&lt;br /&gt;        dao = null;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Test&lt;br /&gt;    public void testSave() {&lt;br /&gt;&lt;br /&gt;        System.out.println("GroupDAOTest.testSave()");&lt;br /&gt;&lt;br /&gt;        Group group = new Group();&lt;br /&gt;        group.setId(GROUP_ID);&lt;br /&gt;        group.setName(GROUP_NAME);&lt;br /&gt;&lt;br /&gt;        System.out.println("Saving group: " + group);&lt;br /&gt;        dao.insert(group);&lt;br /&gt;        Assert.assertTrue(true);&lt;br /&gt;&lt;br /&gt;        Group retrieved = dao.get(GROUP_ID.toString());&lt;br /&gt;        System.out.println("Retrieved group: " + retrieved);&lt;br /&gt;        Assert.assertNotNull(retrieved);&lt;br /&gt;        Assert.assertEquals(GROUP_ID, retrieved.getId());&lt;br /&gt;        Assert.assertEquals(GROUP_NAME, retrieved.getName());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void testRetrieve() {&lt;br /&gt;&lt;br /&gt;        System.out.println("GroupDAOTest.testRetrieve()");&lt;br /&gt;&lt;br /&gt;        System.out.println("Saving groups");&lt;br /&gt;        for (int i = 1; i &lt;= 10; i++) {&lt;br /&gt;            Group group = new Group();&lt;br /&gt;            group.setId(GROUP_ID * 100 + i);&lt;br /&gt;            group.setName(GROUP_NAME + " " + i);&lt;br /&gt;            dao.insert(group);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        List&amp;lt;Group&amp;gt; list = dao.getRange("", "", 10);&lt;br /&gt;        System.out.println("Retrieving groups");&lt;br /&gt;        Assert.assertNotNull(list);&lt;br /&gt;        Assert.assertFalse(list.isEmpty());&lt;br /&gt;        Assert.assertTrue(list.size() &gt;= 10);&lt;br /&gt;&lt;br /&gt;        System.out.println("Retrieved list:");&lt;br /&gt;        for (Group group : list) {&lt;br /&gt;            System.out.println("- " + group);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void testRemove() {&lt;br /&gt;&lt;br /&gt;        System.out.println("GroupDAOTest.testRemove()");&lt;br /&gt;&lt;br /&gt;        Group group = new Group();&lt;br /&gt;        group.setId(GROUP_ID);&lt;br /&gt;        group.setName(GROUP_NAME);&lt;br /&gt;&lt;br /&gt;        System.out.println("Saving group: " + group);&lt;br /&gt;        dao.insert(group);&lt;br /&gt;&lt;br /&gt;        System.out.println("Removing group: " + group);&lt;br /&gt;        dao.delete(group);&lt;br /&gt;        Assert.assertTrue(true);&lt;br /&gt;&lt;br /&gt;        Group retrieved = dao.get(GROUP_ID.toString());&lt;br /&gt;        System.out.println("Retrieved group: " + retrieved);&lt;br /&gt;        Assert.assertNull(retrieved);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Checking the results&lt;/h2&gt;&lt;br /&gt;After properly executing the tests, you should check the keyspace contents inside Cassandra. In order to do that, you can use Cassandra's client by issuing the instructions described below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;cassandra&amp;gt; count ContactList.Groups['12305']    &lt;br /&gt;1 column&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get ContactList.Groups['12305']      &lt;br /&gt;=&gt; (column=name, value=Test Group 5, timestamp=1283287882927)&lt;br /&gt;Returned 1 result.&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get ContactList.Groups['12305']['name']&lt;br /&gt;=&gt; (column=name, value=Test Group 5, timestamp=1283287882927)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusions&lt;/h2&gt;&lt;br /&gt;Traditional relational databases took more than 20 years of evolution to reach the state they are now. Aside, object-oriented programming languages and techniques conquered companies and developers forcing the creation of persistence frameworks in order to link both worlds. Soon as Internet usage grew, RDBMSs were not able to efficiently scale, thus a new paradigm was conceived (or reborn): the key-value distributed database model!&lt;br /&gt;&lt;br /&gt;Cassandra, one of those distributed databases, is not trivial to talk to, from a developer perspective. In opposition to use a low-level interface API (i.e. Thrift), a lot of high-level clients were created by individual developers (thanks to open source initiatives!), and one of them was HelenaORM.&lt;br /&gt;&lt;br /&gt;Thus, in the present article we saw how to leverage and simplify our Java code which handles persistence in Cassandra with the aid of HelenaORM libraries. A lot of work was reduced, isn't it? :D&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;References&lt;/h2&gt;[1] &lt;a title="Talking to Cassandra using Java and DAO pattern" href="http://agajorte.blogspot.com/2010/09/talking-to-cassandra-using-java-and-dao.html" target="_blank"&gt;Talking to Cassandra using Java and DAO pattern&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="Apache Cassandra" href="http://cassandra.apache.org/" target="_blank"&gt;Apache Cassandra&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="Cassandra high level clients" href="http://wiki.apache.org/cassandra/ClientOptions06" target="_blank"&gt;Cassandra high level clients&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="HelenaORM" href="http://github.com/marcust/HelenaORM" target="_blank"&gt;HelenaORM&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-5232113855328913449?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/5232113855328913449/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/simplifying-cassandra-interactions-with.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/5232113855328913449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/5232113855328913449'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/simplifying-cassandra-interactions-with.html' title='Simplifying Cassandra interactions with Helena'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-304134191374117958</id><published>2010-09-01T11:54:00.000-07:00</published><updated>2010-09-01T12:59:41.111-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='cassandra'/><category scheme='http://www.blogger.com/atom/ns#' term='nosql'/><title type='text'>Talking to Cassandra using Java and DAO pattern</title><content type='html'>&lt;br/&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;br /&gt;It is definitely unavoidable and not just another hype this wave of &lt;b&gt;NoSQL&lt;/b&gt; - an alternative to rigid persistence models provided by RDBMS (Relational Database Management Systems). In a connected world that needs more and more data in a continuous growth and speed, it is proved by huge technology companies like Google that changes need to be done in order to accomodate this. One of these turns was indeed NoSQL databases, such as Bigtable, Hypertable, and &lt;b&gt;Cassandra&lt;/b&gt;. The latter will be the subject of this article.&lt;br /&gt;&lt;br /&gt;As described in its home page [1]:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model. Cassandra was open sourced by Facebook in 2008, and is now developed by Apache committers and contributors from many companies."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;So far, Cassandra is in use at Digg, Facebook, Twitter, Reddit, Rackspace, Cloudkick, Cisco, SimpleGeo, Ooyala, OpenX, and more companies that have large, active data sets. The largest production cluster has over 100 TB of data in over 150 machines!&lt;br /&gt;&lt;br /&gt;Therefore, let's take a walk-through on how can this new storing and programming model be achieved, particularly using a client on Java language.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Database keyspace setup&lt;/h2&gt;&lt;br /&gt;We are considering Cassandra's stable version on the time of this document: 0.6.5. Yet, we'll run the server in single mode for simplification purposes. Remember that JDK 1.6 (Java Development Kit) is needed to run Cassandra server.&lt;br /&gt;&lt;br /&gt;The first step on this study will be to include the keyspace "ContactList". In order to to this, add the following lines into &lt;b&gt;CASSANDRA_HOME/conf/storage-conf.xml&lt;/b&gt;, inside &amp;lt;Keyspaces&amp;gt; tag:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;Keyspace Name="ContactList"&amp;gt;&lt;br /&gt;  &amp;lt;ColumnFamily CompareWith="UTF8Type" Name="Groups"/&amp;gt;&lt;br /&gt;  &amp;lt;ColumnFamily CompareWith="UTF8Type" Name="Contacts"/&amp;gt;&lt;br /&gt;  &amp;lt;ReplicaPlacementStrategy&amp;gt;org.apache.cassandra.locator.RackUnawareStrategy&amp;lt;/ReplicaPlacementStrategy&amp;gt;&lt;br /&gt;  &amp;lt;ReplicationFactor&amp;gt;1&amp;lt;/ReplicationFactor&amp;gt;&lt;br /&gt;  &amp;lt;EndPointSnitch&amp;gt;org.apache.cassandra.locator.EndPointSnitch&amp;lt;/EndPointSnitch&amp;gt;&lt;br /&gt;&amp;lt;/Keyspace&amp;gt;&lt;/pre&gt;&lt;br /&gt;Start (or restart) your Cassandra server (by issuing &lt;b&gt;"CASSANDRA_HOME/bin/cassandra -f"&lt;/b&gt;) after editing that file. The proper data files and index structures should be created.&lt;br /&gt;&lt;br /&gt;Please consider reading &lt;b&gt;Cassandra's Getting Started guide&lt;/b&gt; [2] for further information on this process.&lt;br /&gt;&lt;br /&gt;Once the server is online, check the new keyspace availability by using the client application invoking the following command:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CASSANDRA_HOME/bin/cassandra-cli --host localhost --port 9160&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The resulting expected screen is shown below:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;Connected to: "Test Cluster" on localhost/9160&lt;br /&gt;Welcome to cassandra CLI.&lt;br /&gt;&lt;br /&gt;Type 'help' or '?' for help. Type 'quit' or 'exit' to quit.&lt;br /&gt;cassandra&amp;gt; &lt;/pre&gt;&lt;br /&gt;You could then try to show available keyspaces on the server, as illustrated:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;cassandra&amp;gt; show keyspaces&lt;br /&gt;ContactList&lt;br /&gt;Keyspace1&lt;br /&gt;system&lt;/pre&gt;&lt;br /&gt;Note that "ContactList" should be included. If not, you should review the previous steps.&lt;br /&gt;&lt;br /&gt;Now invoke the instruction below in order to explain detailed information on the new keyspace:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;cassandra&amp;gt; describe keyspace ContactList&lt;br /&gt;ContactList.Groups&lt;br /&gt;Column Family Type: Standard&lt;br /&gt;Columns Sorted By: org.apache.cassandra.db.marshal.UTF8Type@33b121&lt;br /&gt;&lt;br /&gt;Column Family Type: Standard&lt;br /&gt;Column Sorted By: org.apache.cassandra.db.marshal.UTF8Type&lt;br /&gt;flush period: null minutes&lt;br /&gt;------&lt;br /&gt;ContactList.Contacts&lt;br /&gt;Column Family Type: Standard&lt;br /&gt;Columns Sorted By: org.apache.cassandra.db.marshal.UTF8Type@1b22920&lt;br /&gt;&lt;br /&gt;Column Family Type: Standard&lt;br /&gt;Column Sorted By: org.apache.cassandra.db.marshal.UTF8Type&lt;br /&gt;flush period: null minutes&lt;br /&gt;------&lt;/pre&gt;&lt;br /&gt;OK, apparently our key-value storage is working well. It's time for coding! :D&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Starting the use case&lt;/h2&gt;&lt;br /&gt;We'll start by implementing a simple "group" entity, represented in Java by a POJO-based class named &lt;b&gt;Group&lt;/b&gt; with the content below:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class Group {&lt;br /&gt;&lt;br /&gt;  private Integer id;&lt;br /&gt;  private String name;&lt;br /&gt;&lt;br /&gt;  public Group() {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Group(Integer id, String name) {&lt;br /&gt;      this.id = id;&lt;br /&gt;      this.name = name;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Integer getId() {&lt;br /&gt;      return id;&lt;br /&gt;  }&lt;br /&gt;  public String getName() {&lt;br /&gt;      return name;&lt;br /&gt;  }&lt;br /&gt;  public void setId(Integer id) {&lt;br /&gt;      this.id = id;&lt;br /&gt;  }&lt;br /&gt;  public void setName(String name) {&lt;br /&gt;      this.name = name;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public String toString() {&lt;br /&gt;      return "Group [id=" + id + ", name=" + name + "]";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Concerns must be separated in different layers. In order to persist the "group" entity, it is highly recommended to have a DAO pattern-based interface. That interface, named &lt;b&gt;IGroupDAO&lt;/b&gt;, is destinated to exclusively handle operations on that entity. Here is its corresponding Java code:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IGroupDAO {&lt;br /&gt;&lt;br /&gt;  void startup();&lt;br /&gt;&lt;br /&gt;  void shutdown();&lt;br /&gt;&lt;br /&gt;  List&amp;lt;Group&amp;gt; findAll();&lt;br /&gt;&lt;br /&gt;  Group findById(Integer id);&lt;br /&gt;&lt;br /&gt;  void save(Group group);&lt;br /&gt;&lt;br /&gt;  void remove(Group group);&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Simply put, &lt;b&gt;save()&lt;/b&gt; and &lt;b&gt;remove()&lt;/b&gt; methods are enough to perform modifications on the data, whereas &lt;b&gt;findAll()&lt;/b&gt; and &lt;b&gt;findById()&lt;/b&gt; are reserved for retrieving purposes. You might then ask: "what da hell are startup() and shutdown() doing there"? Hold on, they are a necessary "gambiarra" to show stuff working and might not be inserted on a real application. :)&lt;br /&gt;&lt;br /&gt;Developers, developers, developers: do not forget to write tests before actual codes..! &lt;b&gt;Test Driven Development (TDD)&lt;/b&gt; is definitely important and worthful besides being so funny to use at coding time!&lt;br /&gt;&lt;br /&gt;As we are using Java, let's create unitary a test against that DAO interface using the &lt;b&gt;JUnit&lt;/b&gt; [3] testing framework. The resulting class, named &lt;b&gt;GroupDAOTest&lt;/b&gt; has the code shown below:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class GroupDAOTest {&lt;br /&gt;&lt;br /&gt;  private static IGroupDAO dao;&lt;br /&gt;&lt;br /&gt;  private static final Integer GROUP_ID = 123;&lt;br /&gt;  private static final String GROUP_NAME = "Test Group";&lt;br /&gt;&lt;br /&gt;  @BeforeClass&lt;br /&gt;  public static void setUpBeforeClass() throws Exception {&lt;br /&gt;      dao = new GroupDAO();&lt;br /&gt;      dao.startup();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @AfterClass&lt;br /&gt;  public static void tearDownAfterClass() throws Exception {&lt;br /&gt;      dao.shutdown();&lt;br /&gt;      dao = null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void testSave() {&lt;br /&gt;&lt;br /&gt;      System.out.println("GroupDAOTest.testSave()");&lt;br /&gt;&lt;br /&gt;      Group group = new Group();&lt;br /&gt;      group.setId(GROUP_ID);&lt;br /&gt;      group.setName(GROUP_NAME);&lt;br /&gt;&lt;br /&gt;      System.out.println("Saving group: " + group);&lt;br /&gt;      dao.save(group);&lt;br /&gt;      Assert.assertTrue(true);&lt;br /&gt;&lt;br /&gt;      Group retrieved = dao.findById(GROUP_ID);&lt;br /&gt;      System.out.println("Retrieved group: " + retrieved);&lt;br /&gt;      Assert.assertNotNull(retrieved);&lt;br /&gt;      Assert.assertEquals(GROUP_ID, retrieved.getId());&lt;br /&gt;      Assert.assertEquals(GROUP_NAME, retrieved.getName());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void testRetrieve() {&lt;br /&gt;&lt;br /&gt;      System.out.println("GroupDAOTest.testRetrieve()");&lt;br /&gt;&lt;br /&gt;      System.out.println("Saving groups");&lt;br /&gt;      for (int i = 1; i &amp;lt;= 10; i++) {&lt;br /&gt;          Group group = new Group();&lt;br /&gt;          group.setId(GROUP_ID * 100 + i);&lt;br /&gt;          group.setName(GROUP_NAME + " " + i);&lt;br /&gt;          dao.save(group);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      List&amp;lt;Group&amp;gt; list = dao.findAll();&lt;br /&gt;      System.out.println("Retrieving groups");&lt;br /&gt;      Assert.assertNotNull(list);&lt;br /&gt;      Assert.assertFalse(list.isEmpty());&lt;br /&gt;      Assert.assertTrue(list.size() &amp;gt;= 10);&lt;br /&gt;&lt;br /&gt;      System.out.println("Retrieved list:");&lt;br /&gt;      for (Group group : list) {&lt;br /&gt;          System.out.println("- " + group);&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void testRemove() {&lt;br /&gt;&lt;br /&gt;      System.out.println("GroupDAOTest.testRemove()");&lt;br /&gt;&lt;br /&gt;      Group group = new Group();&lt;br /&gt;      group.setId(GROUP_ID);&lt;br /&gt;      group.setName(GROUP_NAME);&lt;br /&gt;&lt;br /&gt;      System.out.println("Saving group: " + group);&lt;br /&gt;      dao.save(group);&lt;br /&gt;&lt;br /&gt;      System.out.println("Removing group: " + group);&lt;br /&gt;      dao.remove(group);&lt;br /&gt;      Assert.assertTrue(true);&lt;br /&gt;&lt;br /&gt;      Group retrieved = dao.findById(GROUP_ID);&lt;br /&gt;      System.out.println("Retrieved group: " + retrieved);&lt;br /&gt;      Assert.assertNull(retrieved);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The goal of this &lt;b&gt;GroupDAOTest&lt;/b&gt; test class is to invoke the methods belonging to &lt;b&gt;IGroupDAO&lt;/b&gt; interface. For each DAO functionality a method on &lt;b&gt;GroupDAOTest&lt;/b&gt; must be created and annotated with &lt;b&gt;@Test&lt;/b&gt;. The expected results might be tested using &lt;b&gt;Assert&lt;/b&gt; class.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Actual persistence&lt;/h2&gt;&lt;br /&gt;Base codes were built along with testing classes. However, persistence against Cassandra is not being made yet. Thus, how could we get access to a Cassandra database from a client perspective?&lt;br /&gt;&lt;br /&gt;Cassandra uses a more general API called &lt;b&gt;Thrift&lt;/b&gt; [4] for its external client-facing interactions. Cassandra's main API/RPC/Thrift port is 9160. Thrift supports a wide variety of languages so you can code your application to use Thrift directly (take a look at [5]), or use a high-level client where available.&lt;br /&gt;&lt;br /&gt;Of course we're gonna use the low-level Thrift interface. :)&lt;br /&gt;&lt;br /&gt;The first thing to do is to add several Java libraries related to Cassandra and Thrift to the project's classpath. They are released along with Cassandra binaries, especifically at &lt;b&gt;CASSANDRA_HOME/lib&lt;/b&gt; directory.&lt;br /&gt;&lt;br /&gt;And now we finally implement the &lt;b&gt;GroupDAO&lt;/b&gt; class, which must provide actual instructions assigned by &lt;b&gt;IGroupDAO&lt;/b&gt; interface.&lt;br /&gt;&lt;br /&gt;In this code, we'll need to manually handle the connection to Cassandra through its binary protocol on TCP port 9160. This is exactly where &lt;b&gt;startup()&lt;/b&gt; and &lt;b&gt;shutdown()&lt;/b&gt; get in.&lt;br /&gt;&lt;br /&gt;If you're still not familiar with terms used at key-value databases, such as keystore, column families, etc, don't worry. I suggest you further reading of some articles about &lt;b&gt;Cassandra's Data Model&lt;/b&gt; [6, 7]. For the moment, just know that Thrift interface for Java provides support classes like Cassandra.Client, ColumnParent, ColumnOrSuperColumn, KeyRange, SliceRange, and SlicePredicate.&lt;br /&gt;&lt;br /&gt;Take a look at the code below for &lt;b&gt;GroupDAO&lt;/b&gt; implementation class:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class GroupDAO implements IGroupDAO {&lt;br /&gt;&lt;br /&gt;  private static final String KEYSPACE = "ContactList";&lt;br /&gt;  private static final String COLUMN_FAMILY = "Groups";&lt;br /&gt;  private static final String ENCODING = "utf-8";&lt;br /&gt;&lt;br /&gt;  private static TTransport tr = null;&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Close the connection to the Cassandra Database.&lt;br /&gt;   */&lt;br /&gt;  private static void closeConnection() {&lt;br /&gt;      try {&lt;br /&gt;          tr.flush();&lt;br /&gt;          tr.close();&lt;br /&gt;      } catch (TTransportException exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Open up a new connection to the Cassandra Database.&lt;br /&gt;   *&lt;br /&gt;   * @return the Cassandra Client&lt;br /&gt;   */&lt;br /&gt;  private static Cassandra.Client setupConnection() {&lt;br /&gt;      try {&lt;br /&gt;          tr = new TSocket("localhost", 9160);&lt;br /&gt;          TProtocol proto = new TBinaryProtocol(tr);&lt;br /&gt;          Cassandra.Client client = new Cassandra.Client(proto);&lt;br /&gt;          tr.open();&lt;br /&gt;          return client;&lt;br /&gt;      } catch (TTransportException exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;      return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private Cassandra.Client client;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void startup() {&lt;br /&gt;      this.client = setupConnection();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void shutdown() {&lt;br /&gt;      closeConnection();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public List&amp;lt;Group&amp;gt; findAll() {&lt;br /&gt;      List&amp;lt;Group&amp;gt; list = new ArrayList&amp;lt;Group&amp;gt;();&lt;br /&gt;      try {&lt;br /&gt;          KeyRange keyRange = new KeyRange();&lt;br /&gt;          keyRange.setStart_key("");&lt;br /&gt;          keyRange.setEnd_key("");&lt;br /&gt;&lt;br /&gt;          SliceRange sliceRange = new SliceRange();&lt;br /&gt;          sliceRange.setStart(new byte[] {});&lt;br /&gt;          sliceRange.setFinish(new byte[] {});&lt;br /&gt;&lt;br /&gt;          SlicePredicate slicePredicate = new SlicePredicate();&lt;br /&gt;          slicePredicate.setSlice_range(sliceRange);&lt;br /&gt;&lt;br /&gt;          ColumnParent columnParent = new ColumnParent(COLUMN_FAMILY);&lt;br /&gt;          List&amp;lt;KeySlice&amp;gt; keySlices = client.get_range_slices(KEYSPACE,&lt;br /&gt;                  columnParent, slicePredicate, keyRange,&lt;br /&gt;                  ConsistencyLevel.ONE);&lt;br /&gt;&lt;br /&gt;          if (keySlices == null || keySlices.isEmpty())&lt;br /&gt;              return list;&lt;br /&gt;&lt;br /&gt;          for (KeySlice keySlice : keySlices) {&lt;br /&gt;&lt;br /&gt;              Group group = new Group();&lt;br /&gt;              group.setId(Integer.parseInt(keySlice.getKey()));&lt;br /&gt;&lt;br /&gt;              for (ColumnOrSuperColumn c : keySlice.getColumns()) {&lt;br /&gt;                  if (c.getColumn() != null) {&lt;br /&gt;                      String name = new String(c.getColumn().getName(),&lt;br /&gt;                              ENCODING);&lt;br /&gt;                      String value = new String(c.getColumn().getValue(),&lt;br /&gt;                              ENCODING);&lt;br /&gt;                      // long timestamp = c.getColumn().getTimestamp();&lt;br /&gt;                      if (name.equals("name")) {&lt;br /&gt;                          group.setName(value);&lt;br /&gt;                      }&lt;br /&gt;                  }&lt;br /&gt;              }&lt;br /&gt;&lt;br /&gt;              list.add(group);&lt;br /&gt;          }&lt;br /&gt;          return list;&lt;br /&gt;&lt;br /&gt;      } catch (Exception exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;      return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public Group findById(Integer id) {&lt;br /&gt;      try {&lt;br /&gt;          SlicePredicate slicePredicate = new SlicePredicate();&lt;br /&gt;          SliceRange sliceRange = new SliceRange();&lt;br /&gt;          sliceRange.setStart(new byte[] {});&lt;br /&gt;          sliceRange.setFinish(new byte[] {});&lt;br /&gt;          slicePredicate.setSlice_range(sliceRange);&lt;br /&gt;&lt;br /&gt;          ColumnParent columnParent = new ColumnParent(COLUMN_FAMILY);&lt;br /&gt;          List&amp;lt;ColumnOrSuperColumn&amp;gt; result = client.get_slice(KEYSPACE, id&lt;br /&gt;                  .toString(), columnParent, slicePredicate,&lt;br /&gt;                  ConsistencyLevel.ONE);&lt;br /&gt;&lt;br /&gt;          if (result == null || result.isEmpty())&lt;br /&gt;              return null;&lt;br /&gt;&lt;br /&gt;          Group group = new Group();&lt;br /&gt;          group.setId(id);&lt;br /&gt;&lt;br /&gt;          for (ColumnOrSuperColumn c : result) {&lt;br /&gt;              if (c.getColumn() != null) {&lt;br /&gt;                  String name = new String(c.getColumn().getName(), ENCODING);&lt;br /&gt;                  String value = new String(c.getColumn().getValue(), ENCODING);&lt;br /&gt;                  // long timestamp = c.getColumn().getTimestamp();&lt;br /&gt;                  if (name.equals("name")) {&lt;br /&gt;                      group.setName(value);&lt;br /&gt;                  }&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          return group;&lt;br /&gt;      } catch (Exception exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;      return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void save(Group group) {&lt;br /&gt;      try {&lt;br /&gt;          long timestamp = System.currentTimeMillis();&lt;br /&gt;          Map&amp;lt;String, List&amp;lt;ColumnOrSuperColumn&amp;gt;&amp;gt; job = new HashMap&amp;lt;String, List&amp;lt;ColumnOrSuperColumn&amp;gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;          List&amp;lt;ColumnOrSuperColumn&amp;gt; columns = new ArrayList&amp;lt;ColumnOrSuperColumn&amp;gt;();&lt;br /&gt;          Column column = new Column("name".getBytes(ENCODING), group&lt;br /&gt;                  .getName().getBytes(ENCODING), timestamp);&lt;br /&gt;          ColumnOrSuperColumn columnOrSuperColumn = new ColumnOrSuperColumn();&lt;br /&gt;          columnOrSuperColumn.setColumn(column);&lt;br /&gt;          columns.add(columnOrSuperColumn);&lt;br /&gt;&lt;br /&gt;          job.put(COLUMN_FAMILY, columns);&lt;br /&gt;&lt;br /&gt;          client.batch_insert(KEYSPACE, group.getId().toString(), job,&lt;br /&gt;                  ConsistencyLevel.ALL);&lt;br /&gt;      } catch (Exception exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void remove(Group group) {&lt;br /&gt;      try {&lt;br /&gt;          ColumnPath columnPath = new ColumnPath(COLUMN_FAMILY);&lt;br /&gt;          client.remove(KEYSPACE, group.getId().toString(), columnPath,&lt;br /&gt;                  System.currentTimeMillis(), ConsistencyLevel.ALL);&lt;br /&gt;      } catch (Exception exception) {&lt;br /&gt;          exception.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Now make sure you project is fully "buildable" and make the testing class run! Unless your Cassandra server is offline, the resulting on JUnit is "evergreen".&lt;br /&gt;&lt;br /&gt;Here are the tasks supposed to be performed by the given unitary test:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;instantiate a group identified by the key 123 and persist it, searching it and comparing to the expected object;&lt;/li&gt;&lt;li&gt;persist a group, remove it on the database and then try to search for its key expecting not to find it;&lt;/li&gt;&lt;li&gt;insert 10 instances of groups with keys numbered from 12301 to 12310 and test their retrieval.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;If you're so skeptical as me, you'll love to search for those persisted data by hands. In that case, prompt to the Cassandra's client and try sending some commands to retrieve groups and their columns recently stored. Here are some suggestions:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;cassandra&amp;gt; count ContactList.Groups['12301']&lt;br /&gt;1 columns&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get ContactList.Groups['12301']&lt;br /&gt;=&amp;gt; (column=name, value=Test Group 1, timestamp=1283287745613)&lt;br /&gt;Returned 1 results.&lt;br /&gt;&lt;br /&gt;cassandra&amp;gt; get ContactList.Groups['12301']['name']&lt;br /&gt;=&amp;gt; (column=name, value=Test Group 1, timestamp=1283287745613)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;br /&gt;We have reached the end of this study, at last! In this article some concepts about a NoSQL-based database called Cassandra were introduced. Besides, we implemented in Java a very simple example of persistence into a Cassandra keyspace using a low-level API named Thrift. In the end we just searched for the stored values in the database through Cassandra's client.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;References&lt;/h2&gt;&lt;br /&gt;[1] &lt;a title="Apache Cassandra" href="http://cassandra.apache.org/" target="_blank"&gt;Apache Cassandra&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="Getting Started with Cassandra" href="http://wiki.apache.org/cassandra/GettingStarted/" target="_blank"&gt;Getting Started with Cassandra&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="JUnit - Unit Testing Framework" href="http://www.junit.org/" target="_blank"&gt;JUnit - Unit Testing Framework&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="Apache Thrift" href="http://incubator.apache.org/thrift/" target="_blank"&gt;Apache Thrift&lt;/a&gt;&lt;br /&gt;[5] &lt;a title="Cassandra Wiki - Thrift Examples" href="http://wiki.apache.org/cassandra/ThriftExamples/" target="_blank"&gt;Cassandra Wiki - Thrift Examples&lt;/a&gt;&lt;br /&gt;[6] &lt;a title="Cassandra Wiki - Data Model" href="http://wiki.apache.org/cassandra/DataModel/" target="_blank"&gt;Cassandra Wiki - Data Model&lt;/a&gt;&lt;br /&gt;[7] &lt;a title="A Quick Introduction to the Cassandra Data Model" href="http://maxgrinev.com/2010/07/09/a-quick-introduction-to-the-cassandra-data-model/" target="_blank"&gt;A Quick Introduction to the Cassandra Data Model&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-304134191374117958?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/304134191374117958/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/09/talking-to-cassandra-using-java-and-dao.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/304134191374117958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/304134191374117958'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/09/talking-to-cassandra-using-java-and-dao.html' title='Talking to Cassandra using Java and DAO pattern'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4811678731061980584</id><published>2010-02-10T07:55:00.000-08:00</published><updated>2010-02-10T08:22:39.381-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Configurando Bash Completion no Debian</title><content type='html'>&lt;br/&gt;&lt;br /&gt;O &lt;span style="font-weight: bold;"&gt;bash completion&lt;/span&gt; é uma poderosa ferramenta para administradores Linux que utilizam o shell para realizar suas tarefas, permitindo com que comandos, caminhos de arquivos e mesmo parâmetros específicos sejam autocompletados. Em geral essa feature é habilitada por padrão no Linux, porém em algumas distribuições, tal como no Debian, é preciso configurá-la manualmente. Este é justamente o tema do artigo em questão.&lt;br /&gt;&lt;br /&gt;Antes de qualquer coisa, certifique-se de que o pacote &lt;span style="font-weight: bold;"&gt;bash-completion&lt;/span&gt; esteja instalado, executando a instrução a seguir:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# apt-get install bash-completion&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Em seguida, é preciso indicar a utilização do &lt;span style="font-weight:bold;"&gt;bash-completion&lt;/span&gt; no perfil do bash. Isso pode ser feito individualmente para cada usuário, através do arquivo &lt;span style="font-weight:bold;"&gt;~/.bash_profile&lt;/span&gt;, ou para todo o sistema. Para essa segunda opção, modifique o arquivo &lt;span style="font-weight:bold;"&gt;/etc/bash.bashrc&lt;/span&gt;, usando um editor qualquer:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# vi /etc/bash.bashrc&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Verifique se as seguintes linhas estão incluídas no arquivo de configurações. Inicialmente elas já existem, porém estão comentadas (i.e. iniciadas com o caracter "#"):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# enable bash completion in interactive shells&lt;br /&gt;if [ -f /etc/bash_completion ] &amp;amp;&amp;amp; ! shopt -oq posix; then&lt;br /&gt;  . /etc/bash_completion&lt;br /&gt;fi&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A última etapa consiste em testar se o mecanismo de autocomplemento está funcionando. Para isso, é preciso sair da sessão (i.e. fazer um log out do terminal) e iniciar um novo login. Feito isso, tente digitar a inicial de algum comando (ex: service) e em seguida pressionar a tecla TAB uma vez:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# serv&amp;lt;TAB&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Agora que o comando "service" foi autocompletado, pressione a tecla TAB mais duas vezes para que a respectiva lista de seus possíveis parâmetros seja exibida na tela:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# service &amp;lt;TAB&amp;gt;&lt;br /&gt;hwclock               networking            skeleton              udevtrigger&lt;br /&gt;apache2               hwclock-save          ondemand              umountfs&lt;br /&gt;bootlogd              keyboard-setup        postfix               rsyslog&lt;br /&gt;console-setup         procps                udev                  umountroot&lt;br /&gt;dmesg                 rc                    sendsigs              urandom&lt;br /&gt;halt                  nagios3               rc.local              single&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Caso o comando possua múltiplos argumentos, como é o caso do "service", podemos utilizar o TAB mais uma vez, o que fará com que apenas instruções que façam sentido sejam listadas:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# service nagios3 &amp;lt;TAB&amp;gt;&lt;br /&gt;force-reload  reload        restart       start         status        stop        &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Agora é só digitar a inicial do argumento, pressionar TAB mais uma vez e executar de vez a instrução completa:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# service nagios3 status&lt;br /&gt;* checking /usr/sbin/nagios3...                                      [OK]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pronto! Bem fácil, né?&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4811678731061980584?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4811678731061980584/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/02/configurando-bash-completion-no-debian.html#comment-form' title='5 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4811678731061980584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4811678731061980584'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/02/configurando-bash-completion-no-debian.html' title='Configurando Bash Completion no Debian'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6083208363736011846</id><published>2010-02-05T05:25:00.000-08:00</published><updated>2010-02-05T06:10:54.741-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Reading stdin on scripts for handling SNMP traps</title><content type='html'>&lt;br/&gt;&lt;br /&gt;In a shell, sometimes data are read through standard input (i.e STDIN) rather than arguments, which are most commonly used. For that reading purpose there is an instruction named "&lt;span style="font-weight: bold;"&gt;read&lt;/span&gt;", whose syntax is exemplified below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ read var&lt;br /&gt;123&lt;br /&gt;&lt;br /&gt;$ echo "var: $var"&lt;br /&gt;var: 123&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Today I was wondering how could I retrieve all values passed to a given Shell script considering that one does not know how many items are available. There are a lot of script samples of reading regular files, line by line, using "while" loop along with "read" command. But what if one needs to read the standard input?&lt;br /&gt;&lt;br /&gt;Fortunately, there is a special device on Linux called &lt;span style="font-weight: bold;"&gt;/dev/stdin&lt;/span&gt;, which promised to give the expected outcome. And here's a testing script based on that assertion:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;while read s&lt;br /&gt;do&lt;br /&gt;    echo "s = $s"&lt;br /&gt;done &amp;lt; /dev/stdin&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And it works perfectly! Well, but.. is there any real application for such trick?&lt;br /&gt;&lt;br /&gt;Yes, indeed! My real motivation was to debug and understand why the integration between &lt;span style="font-weight: bold;"&gt;Net-SNMP&lt;/span&gt; (i.e. snmptrapd service) and &lt;span style="font-weight: bold;"&gt;ZABBIX&lt;/span&gt; was not working when &lt;span style="font-weight: bold;"&gt;SNMP traps&lt;/span&gt; were received by the server. Those traps were supposed to be forwarded by snmptrapd to a Shell script called &lt;span style="font-weight: bold;"&gt;snmptrap.sh&lt;/span&gt;, which invoked&lt;span style="font-weight: bold;"&gt; zabbix_sender&lt;/span&gt; along with the received arguments.&lt;br /&gt;&lt;br /&gt;Thus, in order to fine-grained debbuging, I created another script, named &lt;span style="font-weight: bold;"&gt;snmptrapdebug.sh&lt;/span&gt; with the contents below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;echo "Request received: $0"&lt;br /&gt;echo "--------------------------------------------------"&lt;br /&gt;&lt;br /&gt;while read param&lt;br /&gt;do&lt;br /&gt;    echo -e "$param "&lt;br /&gt;done &amp;lt; /dev/stdin&lt;br /&gt;&lt;br /&gt;echo "--------------------------------------------------"&lt;br /&gt;echo&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On the configuration file &lt;span style="font-weight: bold;"&gt;snmptrapd.conf&lt;/span&gt; the following line was appended:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;traphandle default /bin/bash /home/zabbix/snmptrapdebug.sh&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to send a simple SNMP trap the following command was issued:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ snmptrap -v 1 -c public localhost .1.3.6.1.4.1.24.0 localhost 6 12345678 8 .1.3.6.1.4.1.24.12.10.22.64 s "2010-02-04 17:03:18,352,DEBUG,main,SimpleTest,This is a Debug Message"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, here are the LOG results after receiving a SNMP trap by the server:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2010-02-05 11:48:32 localhost [127.0.0.1] (via UDP: [127.0.0.1]:40338) TRAP, SNMP v1, community public&lt;br /&gt;SNMPv2-SMI::enterprises.24.0 Enterprise Specific Trap (12345678) Uptime: 0:00:00.08&lt;br /&gt;SNMPv2-SMI::enterprises.24.12.10.22.64 = STRING: "2010-02-04 17:03:18,352,DEBUG,main,SimpleTest,This is a Debug Message"&lt;br /&gt;Request received: /home/zabbix/snmptrapdebug.sh&lt;br /&gt;--------------------------------------------------&lt;br /&gt;localhost&lt;br /&gt;UDP: [127.0.0.1]:40338&lt;br /&gt;DISMAN-EVENT-MIB::sysUpTimeInstance 0:0:00:00.08&lt;br /&gt;SNMPv2-MIB::snmpTrapOID.0 SNMPv2-SMI::enterprises.24.0.0.12345678&lt;br /&gt;SNMPv2-SMI::enterprises.24.12.10.22.64 "2010-02-04 17:03:18,352,DEBUG,main,SimpleTest,This is a Debug Message"&lt;br /&gt;SNMP-COMMUNITY-MIB::snmpTrapAddress.0 127.0.0.1&lt;br /&gt;SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 "public"&lt;br /&gt;SNMPv2-MIB::snmpTrapEnterprise.0 SNMPv2-SMI::enterprises.24.0&lt;br /&gt;--------------------------------------------------&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it! I hope that tip is worthful for someone else. :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.net-snmp.org/wiki/index.php/TUT:snmptrap" target="_new"&gt;Tutorial on SNMP traps - Net-SNMP Wiki&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://net-snmp.sourceforge.net/FAQ.html#How_do_I_handle_traps_and_notifications_" target="_new"&gt;"How do I handle traps and notifications?" - Net_SNMP FAQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docstore.mik.ua/orelly/networking_2ndEd/snmp/ch10_03.htm" target="_new"&gt;"Sending Traps" - Essential SNMP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://aurelio.net/shell/canivete.html" target="_new"&gt;Canivete Suíço do Shell (Bash)&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6083208363736011846?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6083208363736011846/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2010/02/reading-stdin-on-scripts-for-handling.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6083208363736011846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6083208363736011846'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2010/02/reading-stdin-on-scripts-for-handling.html' title='Reading stdin on scripts for handling SNMP traps'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2824490567383394733</id><published>2010-01-31T23:34:00.000-08:00</published><updated>2010-01-31T17:34:13.895-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gastronomia'/><title type='text'>Pastis: orgulho do sul da França</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/Sts7iAOV5UI/AAAAAAAAAJY/s2AyHWMothE/s1600-h/220px-Pastis_Ricard_Bottle.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 118px; height: 320px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/Sts7iAOV5UI/AAAAAAAAAJY/s2AyHWMothE/s320/220px-Pastis_Ricard_Bottle.jpg" alt="" id="BLOGGER_PHOTO_ID_5393970434068047170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para abrir o apetite ou simplesmente para degustar, nada como um bom &lt;span style="font-weight: bold;"&gt;pastis&lt;/span&gt;, uma das bebidas mais apreciadas na França, especialmente no sul do país. Trata-se de um licor a base de &lt;span style="font-weight: bold;"&gt;anis&lt;/span&gt;, de coloração clara e que se torna cáqui com a adição de água.&lt;br /&gt;&lt;br /&gt;O pastis foi criado na cidade de Marselha como um &lt;span style="font-weight: bold;"&gt;substituto para o absinto&lt;/span&gt;, o qual havia sido banido pelo governo francês em 1915. O absinto era uma bebida popular na época, e a sua proibição levou as pessoas a experimentarem diferentes combinações de ervas e álcool em um esforço para produzir uma bebida que não levava o seu ingrediente banido, o funcho (anis-doce). Mais anis e açúcar foram adicionados a uma menor concentração de álcool e assim surgiu o pastis. Um desse destiladores de fundo de quintal foi &lt;span style="font-weight: bold;"&gt;Paul Ricard&lt;/span&gt;. Ele levava suas misturas a bares ao redor da cidade pedindo para as pessoas a experimentarem a fim de que a sua respectiva fórmula pudesse ser aperfeiçoada. Ele iniciou a produção comercial do Ricard em 1932, conhecido sobretudo pelo slogan &lt;span style="font-style: italic;"&gt;"Le Vrai Pastis de Marseille"&lt;/span&gt; (o Verdadeiro Pastis de Marselha).&lt;br /&gt;&lt;br /&gt;Em geral devemos colocar cinco partes de água para cada parte de pastis, não esquecendo do gelo. Devo lembrar que uma bebida semelhante ao pastis supostamente embriagou van Gogh quando ele cortou a orelha...&lt;br /&gt;&lt;br /&gt;O pastis permanece como um dos mais populares aperitivos na França, além de acompanhar muito bem pratos como peixes, frutos do mar, porco e frango.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pastis 51&lt;/span&gt; (número ironicamente igual à nossa "caninha" de Pirassununga) é a marca líder na França, porém &lt;span style="font-weight: bold;"&gt;Ricard&lt;/span&gt; e &lt;span style="font-weight: bold;"&gt;Pernod&lt;/span&gt; são provavelmente as marcas mais conhecidas fora do país. Ao pedir um pastis em um bar ou restaurante, simplesmente diga &lt;span style="font-style:italic;"&gt;"Du Ricard, s.v.p !"&lt;/span&gt;. Ou faça como Serge Gainsbourg e peça um "102" (i.e. um 51 duplo).. :D&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Referências:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://fr.wikipedia.org/wiki/Pastis"&gt;http://fr.wikipedia.org/wiki/Pastis&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2824490567383394733?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2824490567383394733/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/10/pastis-orgulho-do-sul-da-franca.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2824490567383394733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2824490567383394733'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/10/pastis-orgulho-do-sul-da-franca.html' title='Pastis: orgulho do sul da França'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YGilJHLjrrI/Sts7iAOV5UI/AAAAAAAAAJY/s2AyHWMothE/s72-c/220px-Pastis_Ricard_Bottle.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4024197949835529667</id><published>2009-12-07T11:39:00.000-08:00</published><updated>2009-12-08T05:12:39.588-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='zabbix'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>PostgreSQL monitoring on ZABBIX</title><content type='html'>&lt;br/&gt;&lt;br /&gt;I've recently started to get to know &lt;b&gt;ZABBIX&lt;/b&gt; [1] a little deeper, especially regarding &lt;b&gt;PostgreSQL&lt;/b&gt; database servers monitoring. At first sight I thought it an incredible monitoring and notification system as it fulfills most of the requirements I wondered to have in &lt;b&gt;Cedrus&lt;/b&gt; [2].&lt;br /&gt;&lt;br /&gt;After setting up some basic OS-related items to be monitored, I was searching for PostgreSQL specific configurations and then I found a wiki [3] on &lt;b&gt;ZABBIX UserParameters&lt;/b&gt;. It is indeed very simple! You just need to create SQL statements and then invoke them with psql. If successful, you could append the corresponding lines into ZABBIX agent configuration file and restart it. Then, in the front-end application, what is left to do is to properly set these PostgreSQL parameters to a given host.&lt;br /&gt;&lt;br /&gt;I've created some additional parameters I always use in PostgreSQL instances in order to monitor the server health. In this case, I previously created a user called "zabbix" and a database with same name on PostgreSQL.&lt;br /&gt;&lt;br /&gt;Here are the included lines on &lt;b&gt;/etc/zabbix/zabbix_agentd.conf&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# PostgreSQL custom parameters&lt;br /&gt;&lt;br /&gt;# instance version&lt;br /&gt;UserParameter=pgsql.version,psql -U zabbix zabbix -Atc 'select version()'&lt;br /&gt;&lt;br /&gt;# instance databases summary&lt;br /&gt;UserParameter=pgsql.db.summary,psql -c "select a.datname, pg_size_pretty(pg_database_size(a.datid)) as size, cast(blks_hit/(blks_read+blks_hit+0.000001)*100.0 as numeric(5,2)) as cache, cast(xact_commit/(xact_rollback+xact_commit+0.000001)*100.0 as numeric(5,2)) as success from pg_stat_database a order by a.datname"&lt;br /&gt;&lt;br /&gt;# total databases size&lt;br /&gt;UserParameter=pgsql.db.totalsize,psql -Atc "select sum(pg_database_size(datid)) as total_size from pg_stat_database"&lt;br /&gt;&lt;br /&gt;# specific database size (in bytes)&lt;br /&gt;UserParameter=pgsql.db.size[*],psql -Atc "select pg_database_size('$1') as size"&lt;br /&gt;&lt;br /&gt;# database cache hit ratio (percentage)&lt;br /&gt;UserParameter=pgsql.db.cache[*],psql -Atc "select cast(blks_hit/(blks_read+blks_hit+0.000001)*100.0 as numeric(5,2)) as cache from pg_stat_database where datname = '$1'"&lt;br /&gt;&lt;br /&gt;# database success rate (percentage)&lt;br /&gt;UserParameter=pgsql.db.success[*],psql -Atc "select cast(xact_commit/(xact_rollback+xact_commit+0.000001)*100.0 as numeric(5,2)) as success from pg_stat_database where datname = '$1'"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After restarting &lt;b&gt;ZABBIX Agent&lt;/b&gt;, you can check whether the added parameters are valid by issuing &lt;b&gt;zabbix_get&lt;/b&gt; command in a shell. For instance, to &lt;b&gt;query PostgreSQL instance version&lt;/b&gt;, type this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.version&lt;br /&gt;PostgreSQL 8.3.3 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This other script returns an &lt;b&gt;overview of existing databases in the instance&lt;/b&gt;, highlighting their names, size in disk, cache hit ratio and percentage of successful transactions:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.db.summary&lt;br /&gt;   datname   |  size   | cache | success &lt;br /&gt;-------------+---------+-------+---------&lt;br /&gt; auction5    | 4400 kB |  0.00 |    0.00&lt;br /&gt; auditing    | 4512 kB |  0.00 |    0.00&lt;br /&gt; escola      | 4656 kB |  0.00 |    0.00&lt;br /&gt; postgres    | 4223 kB | 99.81 |  100.00&lt;br /&gt; rodrigo     | 4144 kB |  0.00 |    0.00&lt;br /&gt; template0   | 4144 kB |  0.00 |    0.00&lt;br /&gt; template1   | 4144 kB |  0.00 |    0.00&lt;br /&gt; zabbix      | 10 MB   | 99.99 |  100.00&lt;br /&gt; zahle       | 86 MB   |  0.00 |    0.00&lt;br /&gt;(9 registros)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to measure &lt;b&gt;total space in disk occupied by the entire instance&lt;/b&gt;, this script should be used:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.db.totalsize&lt;br /&gt;1507326452&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On the other hand, to retrieve the &lt;b&gt;space (in bytes) occupied by a single database&lt;/b&gt;, you just need to specify its name in the parameter key, as exemplified below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.db.size[auction5] &lt;br /&gt;4505604&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Likewise, to recover &lt;b&gt;cache hit ratio (in percentage) of a single database&lt;/b&gt;, use this key:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.db.cache[zabbix]&lt;br /&gt;99.99&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;b&gt;percentage of successful transactions&lt;/b&gt; in relation to all attempts is given by this parameter:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;$ zabbix_get -s localhost -k pgsql.db.success[postgres]&lt;br /&gt;100.00&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After testing these parameters, it is time to set them up onto &lt;b&gt;ZABBIX Frontend&lt;/b&gt; as illustrated below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/Sx5Mqmi5CZI/AAAAAAAAAKo/6YJZPgImYpE/s1600-h/zabbix-pgsql.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/Sx5Mqmi5CZI/AAAAAAAAAKo/6YJZPgImYpE/s320/zabbix-pgsql.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5412848096931023250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It is very interesting to further add some &lt;b&gt;traps&lt;/b&gt; and &lt;b&gt;actions&lt;/b&gt; based on the configured items. For example, to send an email to the DBA every time a given database grows up faster than expected or whether its cache ratio starts to lower significantly.&lt;br /&gt;&lt;br /&gt;At Joe Uhl's blog there is a post [4] concerning using ZABBIX to monitor PostgreSQL TPS (Transactions per Second). It is an interesting source as it explains how to configure deltas and graphs in ZABBIX.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;References:&lt;/h2&gt;&lt;br /&gt;[1] &lt;a href="http://www.zabbix.com/" target="nova"&gt;ZABBIX Monitoring Solution&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://sourceforge.net/projects/cedrus/" target="nova"&gt;Cedrus: PostgreSQL Manager&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://www.zabbix.com/wiki/howto/monitor/db/postgresql" target="nova"&gt;ZABBIX Wiki - PostgreSQL UserParameters&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://blog.gtuhl.com/2009/02/21/monitoring-postgresql-tps-with-zabbix/" target="nova"&gt;Monitoring PostgreSQL TPS with Zabbix&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4024197949835529667?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4024197949835529667/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/12/postgresql-monitoring-on-zabbix.html#comment-form' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4024197949835529667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4024197949835529667'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/12/postgresql-monitoring-on-zabbix.html' title='PostgreSQL monitoring on ZABBIX'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YGilJHLjrrI/Sx5Mqmi5CZI/AAAAAAAAAKo/6YJZPgImYpE/s72-c/zabbix-pgsql.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8609529892322354172</id><published>2009-12-01T04:51:00.000-08:00</published><updated>2010-04-26T19:40:17.760-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jpa'/><category scheme='http://www.blogger.com/atom/ns#' term='persistence'/><category scheme='http://www.blogger.com/atom/ns#' term='demoiselle'/><title type='text'>Creating Demoiselle JPA-compliant DAOs</title><content type='html'>&lt;br/&gt;&lt;br /&gt;This article aims at providing a walk through on building &lt;b&gt;Data Access Object (DAO)&lt;/b&gt; [1] components using &lt;b&gt;Java Persistence API (JPA 1.0)&lt;/b&gt; [2], since the latter is now fully supported in the 1.1 release of &lt;b&gt;Demoiselle Framework&lt;/b&gt; [3].&lt;br /&gt;&lt;br /&gt;The reference source codes used in the following sections were retrieved from &lt;b&gt;Auction5&lt;/b&gt; [4], a sample web application specifically designed to exemplify JPA usage along with Demoiselle.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;i. Introducing support elements&lt;/h2&gt;&lt;br /&gt;The main characters on the new Demoiselle persistence handling mechanism are &lt;b&gt;IDAO&lt;/b&gt; [5] and &lt;b&gt;JPAGenericDAO&lt;/b&gt; [6].&lt;br /&gt;&lt;br /&gt;&lt;b&gt;IDAO&lt;/b&gt; is a simple interface containing data manipulation and retrieval methods. It is, above all, a markup interface intended to be implement by whoever class playing a DAO role. Therefore, no matter whether the final class will handle objects from a DBMS or an XML file, using pure JDBC, Hibernate or JPA, it must necessarily implement IDAO.&lt;br /&gt;&lt;br /&gt;On the other hand, &lt;b&gt;JPAGenericDAO&lt;/b&gt; is an abstract class intented to leverage productivity by providing the derived class with a bunch of persistence-related ready-to-use methods such as: findById(), findByJPQL(), insert(), update(), and remove().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;ii. Defining entities&lt;/h2&gt;&lt;br /&gt;&lt;b&gt;Entity classes&lt;/b&gt; are usually the first elements to be created on a Java application powered by JPA persistence.&lt;br /&gt;&lt;br /&gt;In the class diagram below the whole application entities considered in the examples are depicted.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://demoiselle.sourceforge.net/sample/auction5/1.0.1/images/auction5-entities.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 831px; height: 551px;" src="http://demoiselle.sourceforge.net/sample/auction5/1.0.1/images/auction5-entities.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;iii. Designing interfaces&lt;/h2&gt;&lt;br /&gt;In order to build DAO artifacts on Demoiselle, one needs to previously create their respective &lt;b&gt;interfaces&lt;/b&gt;. Besides, these interfaces must extend IDAO by providing the targeted entity class in the generics brackets (e.g. &amp;lt;Auction&amp;gt;).&lt;br /&gt;&lt;br /&gt;The signatures of additional needed methods must be indicated on each interface, remembering that all methods provided by IDAO are already implicitly included.&lt;br /&gt;&lt;br /&gt;For instance, for the Auction entity, there must be created IAuctionDAO interface by extending IDAO and declaring additional listing methods. Its final code is shown below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IAuctionDAO extends IDAO&amp;lt;Auction&amp;gt; {&lt;br /&gt;    public Auction findById(Long id);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listOpenAuctionsByCategory(Category category);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listNewestAuctions(int quantity);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listMostOfferedAuctions(int quantity);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listEndingSoonAuctions(int seconds, int quantity);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listCheapestPriceAuctions(int quantity);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listOpenAuctionsByItem(Item item);&lt;br /&gt;    public List&amp;lt;Auction&amp;gt; listOpenEndedAuctions(Date timestamp);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Likewise, interfaces for Bid, Category, Item, and Order entities suggest the structures below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IBidDAO extends IDAO&amp;lt;Bid&amp;gt; {&lt;br /&gt;    public List&amp;lt;Bid&amp;gt; listLastBidsForAuction(Auction auction, int quantity);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface ICategoryDAO extends IDAO&amp;lt;Category&amp;gt; {&lt;br /&gt;    public Category findById(Short id);&lt;br /&gt;    public List&amp;lt;Category&amp;gt; listAvailableCategories();&lt;br /&gt;    public List&amp;lt;Category&amp;gt; listAllCategories();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IItemDAO extends IDAO&amp;lt;Item&amp;gt; {&lt;br /&gt;    public Item findById(Integer id);&lt;br /&gt;    public List&amp;lt;Item&amp;gt; listByCategory(Category category);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IOrderDAO extends IDAO&amp;lt;Order&amp;gt; {&lt;br /&gt;    public Order findById(Long id);&lt;br /&gt;    public List&amp;lt;Order&amp;gt; listOrdersByLogin(String login);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On an application powered by Demoiselle all those interfaces are usually placed on a subpackage named "persistence.dao" inside the main package tree (e.g. "br.gov.demoiselle.sample.auction5.persistence.dao").&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;iv. Designing implementation classes&lt;/h2&gt;&lt;br /&gt;After creating the DAO interfaces, the next step is to build their respective &lt;b&gt;implementation classes&lt;/b&gt;. For each interface, there must be created a concrete class declared with a reference to that interface.&lt;br /&gt;&lt;br /&gt;In addition, in order to boost development time and yet help the developer with several coding facilities, these new classes should extend JPAGenericDAO superclass described previously.&lt;br /&gt;&lt;br /&gt;Thus, DAO implementation classes should contain the declarations below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class AuctionDAO extends JPAGenericDAO&amp;lt;Auction&amp;gt; implements IAuctionDAO { ... }&lt;br /&gt;&lt;br /&gt;public class BidDAO extends JPAGenericDAO&amp;lt;Bid&amp;gt; implements IBidDAO { ... }&lt;br /&gt;&lt;br /&gt;public class CategoryDAO extends JPAGenericDAO&amp;lt;Category&amp;gt; implements ICategoryDAO { ... }&lt;br /&gt;&lt;br /&gt;public class ItemDAO extends JPAGenericDAO&amp;lt;Item&amp;gt; implements IItemDAO { ... }&lt;br /&gt;&lt;br /&gt;public class OrderDAO extends JPAGenericDAO&amp;lt;Order&amp;gt; implements IOrderDAO { ... }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As a result of "implements", every method declared in an interface must be implemented and fulfilled with actual code by the developer in the class. However, there are exceptions: methods belonging to IDAO are already implemented in JPAGenericDAO, and therefore do not need to be reimplemented.&lt;br /&gt;&lt;br /&gt;Demoiselle Framework suggests hosting these classes onto a subpackage named "implementation" right inside the subpackage containing the interfaces (e.g. "br.gov.demoiselle.sample.auction5.persistence.dao.implementation").&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;v. Implementing classes methods&lt;/h2&gt;&lt;br /&gt;In the next sections there will be explored several ways of implementing the methods declared in the interfaces, by using existing code, by issuing JPQL queries and even through SQL native queries.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1. Superclass methods&lt;/h3&gt;&lt;br /&gt;The first alternative on building persistence methods in the DAO is the simplest one: to directly invoke existing methods of JPAGenericDAO superclass.&lt;br /&gt;&lt;br /&gt;For example, a listAllCategories() method designed to bring all categories could be coded in CategoryDAO using the following contents:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Category&amp;gt; listAllCategories() {&lt;br /&gt;    return findAll();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If the method name is to be kept, one should use the "super" reference variable to prevent infinite loops, as illustrated below in findById() method for CategoryDAO:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public Category findById(Short id) {&lt;br /&gt;    return super.findById(id);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2. JPQL fixed string&lt;/h3&gt;&lt;br /&gt;As an evolution to &lt;b&gt;EJB QL&lt;/b&gt;, JPA 1.0 introduces a query language called &lt;b&gt;JPQL (Java Persistence Query Language)&lt;/b&gt;. This language's synthax is similar to Hibernate's HQL and offers the same purpose: to send instructions to the DBMS by using a language closer to object-oriented world.&lt;br /&gt;&lt;br /&gt;It is made available to the &lt;b&gt;JPAGenericDAO&lt;/b&gt; class a method called &lt;b&gt;findByJPQL()&lt;/b&gt;, which internally creates a JPQL query according to a given string, executes the query, builds a list of entities and finally returns the latter in a type-safe fashion.&lt;br /&gt;&lt;br /&gt;When coding a DAO method on Demoiselle, we could use fixed JPQL queries whenever there is no need to give parameters to them. The CategoryDAO implementation class exhibits the usage of fixed string JPQL queries through findByJPQL():&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;category&amp;gt; listAvailableCategories() {&lt;br /&gt;    return findByJPQL("select c from Category c where c.active = true order by c.name");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;3. JPQL with positional parameters&lt;/h3&gt;&lt;br /&gt;As most of our real-world queries involve passing parameters to them, JPQL also offers the possibility of doing this. Actually, there are two ways of passing parameters to a query: using positional (numbered) or named parameters.&lt;br /&gt;&lt;br /&gt;Positional parameters will be explored in the current section. They are expressed in the JPQL string with the "?" character followed by an integer number starting from 1.&lt;br /&gt;&lt;br /&gt;On &lt;b&gt;JPAGenericDAO&lt;/b&gt; the method &lt;b&gt;findByJPQL()&lt;/b&gt; is overloaded so that it can handle positional parameters as well. The AuctionDAO implementation class exhibits the usage of JPQL queries with positional parameters on listAllAuctionsByItem() method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listAllAuctionsByItem(Item item) {&lt;br /&gt; &lt;br /&gt;    String jpql = "select a from Auction a where a.item = ?1";&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByJPQL(jpql, item);&lt;br /&gt; &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Demoiselle Framework introduces pagination mechanisms through &lt;b&gt;Page&lt;/b&gt; and &lt;b&gt;PagedResult&lt;/b&gt; classes. In order to use them, one needs to invoke an other overloaded version of &lt;b&gt;findByJPQL()&lt;/b&gt;, which accepts a Page object as the second argument. The BidDAO implementation class comes with listLastBidsForAuction() method, which exemplifies pagination of results using the classes described and yet accepts a positional parameter:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Bid&amp;gt; listLastBidsForAuction(Auction auction, int qty) {&lt;br /&gt;  &lt;br /&gt;    Page page = new Page(qty);&lt;br /&gt;  &lt;br /&gt;    String jpql = "select b from Bid b where b.auction.id = ?1 order by b.timestamp desc";&lt;br /&gt;    PagedResult&amp;lt;Bid&amp;gt; pr = findByJPQL(jpql, page, auction.getId());&lt;br /&gt;  &lt;br /&gt;    return (List&amp;lt;Bid&amp;gt;) pr.getResults();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;4. JPQL with named parameters&lt;/h3&gt;&lt;br /&gt;There are some situations where numbered parameters in a query might be a confusing or not preferred alternative. In order to handle it, JPA specification foresees named parameters on JPQL queries.&lt;br /&gt;&lt;br /&gt;According to JPA, a named parameter in JPQL is indicated with the ":" character followed by an unique string which specifies it.&lt;br /&gt;&lt;br /&gt;Inside Demoiselle, using named parameters consists of a map instantiation and the execution of another overloaded &lt;b&gt;findByJPQL()&lt;/b&gt;, this time receiving in addition a Map object as argument. The AuctionDAO implementation class exhibits the usage of JPQL queries with bound named parameters:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listOpenAuctionsByCategory(Category category) {&lt;br /&gt; &lt;br /&gt;    String jpql =&lt;br /&gt;        "select a from Auction a " +&lt;br /&gt;        "where a.status = :status " +&lt;br /&gt;        "  and a.deadline &gt; :deadline " +&lt;br /&gt;        "  and a.item.category = :category " +&lt;br /&gt;        "order by a.item.description";&lt;br /&gt; &lt;br /&gt;    Map&amp;lt;String, Object&amp;gt; params = new HashMap&amp;lt;String, Object&amp;lt;();&lt;br /&gt;    params.put("status", Status.OPEN);&lt;br /&gt;    params.put("deadline", new Date());&lt;br /&gt;    params.put("category", category);&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByJPQL(jpql, params);&lt;br /&gt; &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;5. Named JPQL query&lt;/h3&gt;&lt;br /&gt;As an alternative introduced by Hibernate, JPA brings a feature called named queries, which aims at writing complex JPQL statements inside entity classes in the form of annotations. These so-called annotated queries are then referenced back when issuing JPQL queries.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JPAGenericDAO&lt;/b&gt; comes handy once again by providing another method: &lt;b&gt;findByNamedQuery()&lt;/b&gt;. This method receives a string containing the name of a JPQL query whose statement is already on an entity. For instance, let the Item entity with a &lt;b&gt;@NamedQuery&lt;/b&gt; annotation right above its class declaration:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;@NamedQuery(&lt;br /&gt;    name = "itemsByCategory",&lt;br /&gt;    query = "select i from Item i where i.category.id = ?1 order by i.description"&lt;br /&gt;)&lt;br /&gt;public class Item implements IPojoExtension { ... }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, the respective ItemDAO implementation class should make use of JPAGenericDAO's findByNamedQuery() as shown in the code belonging to listByCategory() method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Item&amp;gt; listByCategory(Category category) {&lt;br /&gt;    return findByNamedQuery("itemsByCategory", category.getId());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that in the previous example a positional parameter was placed. But what if we need named parameters alongside named queries? The answer is: an overloaded version of findByNamedQuery() might take place! For example, the Auction entity presents a @NamedQuery according to the code below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;@NamedQuery(&lt;br /&gt;    name = "openAuctionsByItem",&lt;br /&gt;    query = "select a from Auction a where a.status = :status and a.deadline &gt; :deadline and a.item = :item"&lt;br /&gt;)&lt;br /&gt;public class Auction implements IPojoExtension { ... }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Observe that named parameters on a named JPQL query are indicated in the annotation as if they were to be used by findByJPQL() method. And then, in the same manner, we need to create a map object in order to invoke the method, which this time is findByNamedQuery(). Take a look at the contents of AuctionDAO, particularly the listOpenAuctionsByItem() method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;gt;Auction&amp;lt; listOpenAuctionsByItem(Item item) {&lt;br /&gt; &lt;br /&gt;    Map&amp;lt;String, Object&amp;gt; params = new HashMap&amp;lt;String, Object&amp;lt;();&lt;br /&gt;    params.put("status", Status.OPEN);&lt;br /&gt;    params.put("deadline", new Date());&lt;br /&gt;    params.put("item", item);&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByNamedQuery("openAuctionsByItem", params);&lt;br /&gt; &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;6. Native SQL query&lt;/h3&gt;&lt;br /&gt;So, are we constrained to JPQL statements and object-oriented queries when adopting JPA persistence mechanism on a Java application? Not at all!&lt;br /&gt;&lt;br /&gt;There are some cases where performance matters most of everything and the only possibility of achieving it is by executing native SQL instructions, usually made through JDBC in the Java world. This particular approach can boost up SQL execution time, especially for those who prefer to create their own database stored procedures or functions.&lt;br /&gt;&lt;br /&gt;Despite this development behavior can lead to a given DBMS dependency and thus compromising application portability, the architect still might choose to create native SQL queries. JPA specification was developed with a rich set of components (i.e. interfaces and annotations) concerning the invocation of native SQL instructions.&lt;br /&gt;&lt;br /&gt;In Demoiselle, once again, &lt;b&gt;JPAGenericDAO&lt;/b&gt; can help the developer with a pre-built method: &lt;b&gt;findByNativeQuery()&lt;/b&gt;. Take the example of the listMostOfferedAuctions() method inside AuctionDAO, which contains SQL directed to PostgreSQL DBMS:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listMostOfferedAuctions(int quantity) {&lt;br /&gt; &lt;br /&gt;    String sql =&lt;br /&gt;        "select d.* from ( " +&lt;br /&gt;        "  select b.auction_id, count(b.id) " +&lt;br /&gt;        "  from bids b " +&lt;br /&gt;        "  inner join auctions a on (a.id = b.auction_id) " +&lt;br /&gt;        "  where a.status = ?1 and a.mode &lt;&gt; ?2 " +&lt;br /&gt;        "  group by b.auction_id " +&lt;br /&gt;        "  order by count(b.id) desc " +&lt;br /&gt;        "  limit ?3) c " +&lt;br /&gt;        "join auctions d on (d.id = c.auction_id) " +&lt;br /&gt;        "where d.bestbid_id is not null " +&lt;br /&gt;        "order by c.count desc";&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByNativeQuery(sql,&lt;br /&gt;         Status.OPEN.ordinal(), Mode.SELLING.ordinal(), quantity);&lt;br /&gt;&lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Another method of AuctionDAO, listEndingSoonAuctions(), makes use of native SQL query and positional parameters:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listEndingSoonAuctions(int seconds, int quantity) {&lt;br /&gt; &lt;br /&gt;    String sql =&lt;br /&gt;        "select * " +&lt;br /&gt;        "from auctions " +&lt;br /&gt;        "where status = ?1 " +&lt;br /&gt;        "  and deadline - current_timestamp between '0 s' and cast(?2 as interval) " +&lt;br /&gt;        "order by deadline " +&lt;br /&gt;        "limit ?3";&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByNativeQuery(sql,&lt;br /&gt;         Status.OPEN.ordinal(), seconds + " s", quantity);&lt;br /&gt;&lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But now another issue is raised: what if we need native SQL query along with named parameters? The answer might be simple: just merge both techniques into one, right? Well, partially.&lt;br /&gt;&lt;br /&gt;According to JPA 1.0 specification, a named parameter is an identifier that is prefixed by the ":" symbol, and its use applies just to JPQL, therefore not being defined for native queries. Thus, only positional parameter binding may be portably used for native queries.&lt;br /&gt;&lt;br /&gt;Despite that lack of portability, JPA implementations usually offer named parameters on native queries. Unfortunately there is no common sense yet, so that implementations consider "?" or ":" symbols when defining named parameters in a native SQL string. This is better illustrated in the code below, taken from AuctionDAO's listCheapestPriceAuctions() method, which is prepared to run on &lt;b&gt;Hibernate EntityManager&lt;/b&gt; JPA implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listCheapestPriceAuctions(int quantity) {&lt;br /&gt; &lt;br /&gt;    // WARNING: prepared for Hibernate - use "?" instead of ":" for TopLink or EclipseLink&lt;br /&gt;    String sql =&lt;br /&gt;        "select d.* from (" +&lt;br /&gt;        "  select a.id, coalesce(b.amount, a.startingprice, a.sellingprice) as price " +&lt;br /&gt;        "  from auctions a left join bids b on (b.id = a.bestbid_id) " +&lt;br /&gt;        "  where a.status = :status " +&lt;br /&gt;        "  order by 2 asc " +&lt;br /&gt;        "  limit :quantity) c " +&lt;br /&gt;        "join auctions d on c.id = d.id " +&lt;br /&gt;        "order by c.price";&lt;br /&gt; &lt;br /&gt;    Map&amp;lt;String, Object&amp;gt; params = new HashMap&amp;lt;String, Object&amp;lt;();&lt;br /&gt;    params.put("status", Status.OPEN.ordinal());&lt;br /&gt;    params.put("quantity", quantity);&lt;br /&gt; &lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByNativeQuery(sql, params);&lt;br /&gt; &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thus, portability is compromised in the previous example, as we need to take special precautions when switching to another JPA implementation, say &lt;b&gt;EclipseLink&lt;/b&gt; or &lt;b&gt;Apache OpenJPA&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;7. Named native SQL query&lt;/h3&gt;&lt;br /&gt;As with JPQL, it is possible to store the entire native query statement onto an entity class and then reference it as needed. In order to do that, JPA defines another annotation, &lt;b&gt;@NamedNativeQuery&lt;/b&gt;, which has the same purpose of @NamedQuery. After setting the named native query, one could invoke &lt;b&gt;findByNamedQuery()&lt;/b&gt; method to execute it and possibly bring back the results. Note that this very same method fits for both JPQL and native SQL queries.&lt;br /&gt;&lt;br /&gt;So, consider the named native query "newestAuctions", which is defined on Auction entity file. There, in the @NamedNativeQuery annotation three parameters must be passed: the query unique identifier, the statement itself, and a class indicating the result type. The referenced code is shown below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;@NamedNativeQuery(&lt;br /&gt;    name = "newestAuctions",&lt;br /&gt;    query = "select * from auctions where status = ?1 order by creation desc limit ?2",&lt;br /&gt;    resultClass = Auction.class&lt;br /&gt;)&lt;br /&gt;public class Auction implements IPojoExtension { ... }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;At DAO implementation class AuctionDAO this named native query is called inside listNewestAuctions() method, as illustrated in the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Auction&amp;gt; listNewestAuctions(int quantity) {&lt;br /&gt;    List&amp;lt;Auction&amp;gt; result = findByNamedQuery("newestAuctions",&lt;br /&gt;         Status.OPEN.ordinal(), quantity);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;8. LIQUidFORM tool&lt;/h3&gt;&lt;br /&gt;JPA 1.0 specification does not provide a &lt;b&gt;Criteria API&lt;/b&gt; [7], a feature introduced by &lt;b&gt;Hibernate&lt;/b&gt; designed to help developers on building HQL queries. With that we avoid string concatenation and rather we declaratively define the statement, thus reducing the risk of errors in its synthax.&lt;br /&gt;&lt;br /&gt;Fortunately JPA 2.0 was conceived with a Criteria API, thus soon JPA implementations will run after that. Meanwhile, a lot of alternatives were developed to fill in such requirement in JPA. Amongst them, one particular tool was employed in the sample code: &lt;b&gt;LIQUidFORM&lt;/b&gt; [8].&lt;br /&gt;&lt;br /&gt;LIQUidFORM is actually a set of classes and interfaces designed to compose JPQL statements in a type-safe and refactoring proof style. It might be strange at first sight, as it contains methods called select(), from(), and where(), but it is indeed a very interesting idea.&lt;br /&gt;&lt;br /&gt;The key to LIQUidFORM is to make use of static imports in the class header, namely the lines below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import static com.google.code.liquidform.LiquidForm.*;&lt;br /&gt;import static com.google.code.liquidform.Parameters.*;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OrderDAO implementation class exhibits the usage of LIQUidFORM tool for creating a JPQL query inside listOrdersByLogin() method, as shown below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public List&amp;lt;Order&amp;gt; listOrdersByLogin(String login) {&lt;br /&gt;&lt;br /&gt;    Order o = alias(Order.class, "o");&lt;br /&gt;&lt;br /&gt;    String jpql =&lt;br /&gt;        select(o).&lt;br /&gt;        from(Order.class).as(o).&lt;br /&gt;        where(eq(o.getLogin(), param(1, String.class))&lt;br /&gt;    ).toString();&lt;br /&gt;&lt;br /&gt;    return findByJPQL(jpql, login);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;vi. Conclusion&lt;/h2&gt;&lt;br /&gt;In this article we have explored some benefits of building the persistence layer of a Java application by adopting Java Persistence API (JPA 1.0) inside an architecture composed by DAO-based interfaces and implementation classes.&lt;br /&gt;&lt;br /&gt;In addition, we have seen the usage of Demoiselle Framework structural IDAO interface and JPAGenericDAO support class when building methods designed to manipulate data through JPA. Those methods also served to exemplify the existing JPA approaches by introducing JPQL and native SQL queries, positional and named parameters, JPQL and SQL named queries, and LIQUidFORM tool.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;vii. References&lt;/h2&gt;&lt;br /&gt;[1] &lt;a title="Core J2EE Patterns - Data Access Object" href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" target="_blank"&gt;Core J2EE Patterns - Data Access Object&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="JPA 1.0 (JSR 220)" href="http://jcp.org/en/jsr/summary?id=220" target="_blank"&gt;JPA 1.0 (JSR 220)&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="Demoiselle Framework" href="http://demoiselle.sourceforge.net/" target="_blank"&gt;Demoiselle Framework&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="Auction5 Application Sample" href="http://demoiselle-samp.sourceforge.net/auction5/" target="_blank"&gt;Auction5 Application Sample&lt;/a&gt;&lt;br /&gt;[5] &lt;a title="IDAO interface" href="http://demoiselle.sourceforge.net/demoiselle-core/xref/br/gov/framework/demoiselle/core/layer/IDAO.html" target="_blank"&gt;IDAO interface&lt;/a&gt;&lt;br /&gt;[6] &lt;a title="JPAGenericDAO class" href="http://demoiselle.sourceforge.net/demoiselle-persistence/xref/br/gov/framework/demoiselle/persistence/JPAGenericDAO.html" target="_blank"&gt;JPAGenericDAO class&lt;/a&gt;&lt;br /&gt;[7] &lt;a title="Criteria API" href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Criteria.html" target="_blank"&gt;Criteria API&lt;/a&gt;&lt;br /&gt;[8] &lt;a title="LIQUidFORM" href="http://code.google.com/p/liquidform/" target="_blank"&gt;LIQUidFORM&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8609529892322354172?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8609529892322354172/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/12/creating-demoiselle-jpa-compliant-daos.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8609529892322354172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8609529892322354172'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/12/creating-demoiselle-jpa-compliant-daos.html' title='Creating Demoiselle JPA-compliant DAOs'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8844638858279125579</id><published>2009-11-26T08:35:00.000-08:00</published><updated>2009-11-26T08:46:42.802-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flight'/><title type='text'>Roteiro de voo CWB-CGH</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/Sw6uh3Lp0iI/AAAAAAAAAKY/ZmOfMMpUaWQ/s1600/mapa-cwb-cgh.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/Sw6uh3Lp0iI/AAAAAAAAAKY/ZmOfMMpUaWQ/s320/mapa-cwb-cgh.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5408452099290288674" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Depois que viciei no M$ Flight Simulator, comecei a prestar atenção nos comandos efetuados pelos pilotos em voos comerciais. A seguir um roteiro de eventos que registrei a partir da janelinha de um A319 de Curitiba (CWB) a São Paulo (CGH)... :) Mapa da rota ao lado.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;tempo     evento&lt;br /&gt;--------  ----------------------&lt;br /&gt;19:25:00  entrada (gate 2 CWB)&lt;br /&gt;19:40:15  portas auto&lt;br /&gt;     +30" pushback&lt;br /&gt;19:44:15  throttle up&lt;br /&gt;   45:45  flaps down&lt;br /&gt;     +45" taxi&lt;br /&gt;   55:50  entrada pista 15C&lt;br /&gt;          strobes on&lt;br /&gt;   58:00  alinhamento&lt;br /&gt;      +1' speed up&lt;br /&gt;      +1' pitch up&lt;br /&gt;     +15" gears up&lt;br /&gt;      +1' flaps up 100%&lt;br /&gt;20:02:45  pitch down slowly&lt;br /&gt;   04:15  bank left&lt;br /&gt;     +30" stabilize (NE)&lt;br /&gt;   22:45  início descida&lt;br /&gt;   25:00  avistado litoral SP&lt;br /&gt;   29:30  bank left (N)&lt;br /&gt;   30:00  landing lights on&lt;br /&gt;   31:10  flaps down +1&lt;br /&gt;   37:45  bank right&lt;br /&gt;     +15" stabilize&lt;br /&gt;     +15" flaps down +1&lt;br /&gt;   40:15  bank right&lt;br /&gt;     +20" stabilize&lt;br /&gt;   40:30  bank right&lt;br /&gt;     +20" stabilize&lt;br /&gt;   42:40  bank right&lt;br /&gt;     +20" stabilize&lt;br /&gt;   45:00  throttle down&lt;br /&gt;     +45" slats down&lt;br /&gt;     +10" flaps down +1&lt;br /&gt;     +10" flaps down +1&lt;br /&gt;      +5" pouso autorizado&lt;br /&gt;   47:35  avistado Tietê&lt;br /&gt;   49:45  avistada Av. Bandeirantes&lt;br /&gt;   50:15  tocada pista 17R CGH&lt;br /&gt;      +5" spoilers/reversos acionados&lt;br /&gt;     +30" saída pista principal&lt;br /&gt;     +10" taxi&lt;br /&gt;     +20" flaps/spoilers recolhidos&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;PS: Sim, não há registro do abaixamento do trem de pouso. Simplesmente porque não percebi quando ele ocorreu... :(&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8844638858279125579?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8844638858279125579/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/11/roteiro-de-voo-cwb-cgh.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8844638858279125579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8844638858279125579'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/11/roteiro-de-voo-cwb-cgh.html' title='Roteiro de voo CWB-CGH'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/Sw6uh3Lp0iI/AAAAAAAAAKY/ZmOfMMpUaWQ/s72-c/mapa-cwb-cgh.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2316235404740966502</id><published>2009-11-18T18:45:00.000-08:00</published><updated>2009-11-18T19:11:16.269-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flight'/><title type='text'>Seattle-Vancouver on TAM's A319</title><content type='html'>&lt;br/&gt;&lt;br /&gt;From &lt;b&gt;Seattle-Tacoma International Airport&lt;/b&gt; [1] to &lt;b&gt;Vancouver International Airport&lt;/b&gt; [2] on a &lt;b&gt;TAM Airlines&lt;/b&gt; [3] &lt;b&gt;Airbus A319&lt;/b&gt; [4] aircraft... :D&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/SwSx4FiyjaI/AAAAAAAAAJw/kbEtdK8Hv2M/s1600/pouso-seattle-vancouver.JPG"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:left;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/SwSx4FiyjaI/AAAAAAAAAJw/kbEtdK8Hv2M/s320/pouso-seattle-vancouver.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5405641029870325154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/SwSx4fmmQKI/AAAAAAAAAJ4/dmDaIIsi7eg/s1600/taxi-seattle-vancouver.JPG"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:right;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/SwSx4fmmQKI/AAAAAAAAAJ4/dmDaIIsi7eg/s320/taxi-seattle-vancouver.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5405641036865618082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/SwSx4ven6pI/AAAAAAAAAKA/UCcG9yawKhE/s1600/chegada-seattle-vancouver.JPG"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/SwSx4ven6pI/AAAAAAAAAKA/UCcG9yawKhE/s320/chegada-seattle-vancouver.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5405641041127139986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/SwSx4x6IoqI/AAAAAAAAAKI/J0byC1Qo0VE/s1600/desembarque-seattle-vancouver.JPG"&gt;&lt;img style="display:block; margin:0px auto 0px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/SwSx4x6IoqI/AAAAAAAAAKI/J0byC1Qo0VE/s320/desembarque-seattle-vancouver.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5405641041779401378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References:&lt;/b&gt;&lt;br /&gt;[1] http://en.wikipedia.org/wiki/Seattle-Tacoma_International_Airport&lt;br /&gt;[2] http://en.wikipedia.org/wiki/Vancouver_International_Airport&lt;br /&gt;[3] http://en.wikipedia.org/wiki/TAM_Airlines&lt;br /&gt;[4] http://en.wikipedia.org/wiki/Airbus_A319#A319&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2316235404740966502?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2316235404740966502/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/11/seattle-vancouver-on-tams-a319.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2316235404740966502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2316235404740966502'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/11/seattle-vancouver-on-tams-a319.html' title='Seattle-Vancouver on TAM&apos;s A319'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/SwSx4FiyjaI/AAAAAAAAAJw/kbEtdK8Hv2M/s72-c/pouso-seattle-vancouver.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2760126814299732584</id><published>2009-11-16T12:41:00.000-08:00</published><updated>2009-11-16T12:47:23.297-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Unicode to Java string literal converter</title><content type='html'>&lt;br/&gt;&lt;br /&gt;I was having some headaches writing properties files valid across several platforms due to encoding issues. However, by googling around today I found this very interesting JavaScript-based conversion tool:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.snible.org/java2/uni2java.html" target="_new"&gt;http://www.snible.org/java2/uni2java.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thanks to Ed Snible!&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2760126814299732584?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2760126814299732584/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/11/unicode-to-java-string-literal.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2760126814299732584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2760126814299732584'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/11/unicode-to-java-string-literal.html' title='Unicode to Java string literal converter'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-1615316536536229131</id><published>2009-11-10T05:52:00.000-08:00</published><updated>2009-11-10T07:31:11.121-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j2ee'/><title type='text'>Resumos das palestras do TDC 2009</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Seguem resumos das palestras dos keynotes no &lt;b&gt;The Developer's Conference 2009 - Floripa&lt;/b&gt; [1] ministradas no dia 9 de novembro.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Tendências em Java EE: Como serão os próximos 5 anos - Rod Johnson&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;O criador do &lt;b&gt;Spring&lt;/b&gt; [2], um dos mais populares frameworks em Java, apresentou nesta palestra suas previsões para o futuro da tecnologia da informação como um todo. Nessa linha, afirmou que &lt;i&gt;"estamos a ponto de presenciar a maior ruptura em TI desde o declínio do mainframe"&lt;/i&gt;, impulsionada por forças como Cloud Computing, Lei de Moore e o fato de os custos estarem se voltando para as pessoas em contraposição ao hardware.&lt;br /&gt;&lt;br /&gt;Disse também que sistemas gerenciadores de bancos de dados relacionais (SGBDRs) não irão embora, e ao invés disso haverá grande ascensão da chamada "persistência poliglota", onde haverão diferentes meios de se armazenar os dados. (Aqui entra a JPA!)&lt;br /&gt;&lt;br /&gt;Sobre a &lt;b&gt;computação em nuvem&lt;/b&gt;, afirmou que ela está mais próxima que SOA e que possui as seguintes vantagens características: ser abstrata, integrada e opinativa, dinamicamente escalável e consumida como um serviço, além de inevitável devido a questões econômico-ambientais. E com isso, disse que nós desenvolvedores nos tornaremos mais poderosos! :) Precisaremos fornecer APIs direcionadas para a nuvem...&lt;br /&gt;&lt;br /&gt;Com relação aos frameworks, iniciou com a frase &lt;i&gt;"Frameworks can't be too disruptive!"&lt;/i&gt;, alegando que o código aberto possibilitou a criação de excelentes soluções de software, mas por outro lado fez do Java uma plataforma confusa para os iniciantes.&lt;br /&gt;&lt;br /&gt;Finalizou dizendo que nessa era de desordem a abstração será mais importante do que nunca, citando como possíveis gerenciadoras para esse caos no software as seguintes soluções: Grails, Spring, Roo e Rails, além de especificações como a JPA.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Java EE 6 - Uma grande evolução - Mike Keith&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;O Mike é o líder de importantes especificações do Java, tal como EJB 3 e JPA, e iniciou esta palestra apresentando os objetivos e destaques para a esperada versão 6 do Java EE [3], especialmente &lt;b&gt;JSF 2.0&lt;/b&gt;, &lt;b&gt;Servlet 3.0&lt;/b&gt;, &lt;b&gt;EJB 3.1&lt;/b&gt; e &lt;b&gt;JPA 2.0&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Em seguida resumiu cada uma das novas funcionalidades: Java Profiles, JNDI Namespaces, Data Source Definition, novas anotações para Web (ex: @WebServlet, @ServletFilter, @WebServletContextListener), Web Fragments, Async Processing (mesmo para session beans!). Além disso, para o EJB 3.1 teremos: interfaces opcionais, singleton, concorrência, timer estilo cron, EJB lite, contêiner embutido e novas regras de empacotamento.&lt;br /&gt;&lt;br /&gt;A JPA 2.0 terá cache compartilhado, melhorias na JPQL e a inclusão de uma API de Criteria. Os Managed Beans substituirão os MBs atuais do JSF e haverão anotações para injeção comuns a JSE e JEE, além do início de sua padronização. Os WebBeans serão contemplados pela CDI 1.0, a qual basicamente visará gerenciar objetos injetáveis ligados a contextos do ciclo de vida, possuindo anotações como @Inject, @Qualifier, @Scope, @Named e @Singleton.&lt;br /&gt;&lt;br /&gt;Outra questão importante refere-se ao processo de limpeza, em que determinadas tecnologias tornaram-se obsoletas e entrarão no estágio de poda (pruning stage). Entre elas citou JAX-RPC, EJB Entity Beans, JAXR e JSR-88 Deployment. Os fornecedores não serão obrigados a implementá-las em releases futuras.&lt;br /&gt;&lt;br /&gt;Por fim, a notícia que mais aguardávamos, a data do lançamento. Mike disse que os grupos de experts das JSR praticamente já concluíram seus trabalhos e que a &lt;b&gt;Java EE 6 será liberada no dia 10 de dezembro&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;JSF 2.0: Uma Abordagem Completa - Ed Burns&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/SvmFxnOwMOI/AAAAAAAAAJo/Wl4YbyGFav0/s1600-h/tdc2009-edburns.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/SvmFxnOwMOI/AAAAAAAAAJo/Wl4YbyGFav0/s320/tdc2009-edburns.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5402496315398566114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ed iniciou a palestra fazendo uma pequena introdução sobre a tecnologia &lt;b&gt;JavaServer Faces&lt;/b&gt; a fim de balizar o conhecimento do público. Apresentou o ciclo de vida no processamento de requisições do JSF e as funcionalidades desejadas (conversão e validação de dados, fluxo de páginas, integração com banco de dados, desempenho, segurança, etc).&lt;br /&gt;&lt;br /&gt;Enfatizando os 4 pilares do JSF 2.0 (visão, interação com o modelo, navegação e ciclo de vida), destacou que as visões passarão a ser páginas Facelets, haverá a anotação @ManagedBean, e que o JSP será depreciado.&lt;br /&gt;&lt;br /&gt;A Expression Language será mais poderosa, e na navegação de páginas o uso de XMLs será opcional, devido à nova navegação implícita, altamente dinâmica e especialmente útil com os novos objetos do tipo "flash". Com relação ao ciclo de vida, haverá um excelente suporte para o uso de Ajax, além do advento dos System Events, finos ouvintes dos eventos do ciclo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Spring Roo - Rod Johnson&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Em substituição ao Chris Schalk da Google, Rod fez uma palestra prática totalmente sem slides apresentando uma nova solução da SpringSource: o &lt;b&gt;Spring Roo&lt;/b&gt; [5].&lt;br /&gt;&lt;br /&gt;Trata-se de um &lt;b&gt;gerador de código em Java&lt;/b&gt; que como qualquer do gênero visa impulsionar a produtividade do desenvolvimento. Achei muito semelhante ao &lt;b&gt;Ruby on Rails&lt;/b&gt;: um prompt de comando (shell) que executa diversas tarefas, especialmente a criação automática de inúmeros arquivos e o fornecimento de um servidor Web simples para os testes. Funciona até auto-completion no estilo bash!&lt;br /&gt;&lt;br /&gt;A instalação do Roo é extremamente simples, mas ele exige que tenhamos o seguinte ambiente: Eclipse IDE com plugins WTP e AJDT. Isso mesmo, o &lt;b&gt;Spring Roo usa extensivamente o AspectJ&lt;/b&gt;! São criados arquivos ".aj" a fim de incluir funcionalidade as novas classes.&lt;br /&gt;&lt;br /&gt;Outras características importantes foram a criação automática de testes unitários, o fato de o projeto ser gerenciado pelo &lt;b&gt;Maven&lt;/b&gt; (são criados diversos arquivos "pom.xml") e a persistência ser manipulada através de &lt;b&gt;JPA&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;A mágica do Roo acontece durante o gerenciamento das entidades. Por exemplo, os métodos persist() e findAll() são inseridos em cada entidade através de injeção de aspectos! Achei um tanto bizarro, mas não deixa de ser uma possibilidade interessante. As entidades não precisam declarar métodos getters e setters e nem toString() customizado, pois, novamente, aspectos fazem isso..!&lt;br /&gt;&lt;br /&gt;Eis um exemplo de classe criada no Roo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Entity&lt;br /&gt;@RooJavaBean&lt;br /&gt;@RooToString&lt;br /&gt;@RooEntity&lt;br /&gt;public class Restaurant {&lt;br /&gt;&lt;br /&gt;   private String name;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Tal como no Rails, podemos criar com uma agilidade e rapidez descomunal uma aplicação completa incluindo scaffold (i.e. o CRUD), testes unitários, páginas web para apresentação (em JSF!) e toda a configuração da persistência.&lt;br /&gt;&lt;br /&gt;Atualmente o Spring Roo está na release candidate 2 e tem previsão de ser liberado no final desse ano. Infelizmente ainda não tem suporte para o NetBeans, devido ao fato de depender do Eclipse AJDT.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Referências:&lt;/b&gt;&lt;br /&gt;[1] &lt;a title="TDC 2009 Floripa" href="http://www.thedevelopersconference.com.br/tdc/2009/floripa/" target="_blank"&gt;TDC 2009 Floripa&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="Spring Framework" href="http://www.springsource.org/about" target="_blank"&gt;Spring Framework&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="Java EE 6 Technologies" href="http://java.sun.com/javaee/technologies/javaee6.jsp" target="_blank"&gt;Java EE 6 Technologies&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="JavaServer Faces Technology" href="http://java.sun.com/javaee/javaserverfaces/" target="_blank"&gt;JavaServer Faces Technology&lt;/a&gt;&lt;br /&gt;[5] &lt;a title="Spring Roo" href="http://www.springsource.org/roo" target="_blank"&gt;Spring Roo&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-1615316536536229131?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/1615316536536229131/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/11/resumos-das-palestras-do-tdc-2009.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1615316536536229131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1615316536536229131'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/11/resumos-das-palestras-do-tdc-2009.html' title='Resumos das palestras do TDC 2009'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YGilJHLjrrI/SvmFxnOwMOI/AAAAAAAAAJo/Wl4YbyGFav0/s72-c/tdc2009-edburns.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-3585110683176028852</id><published>2009-11-07T17:25:00.000-08:00</published><updated>2009-11-07T17:52:02.285-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j2ee'/><category scheme='http://www.blogger.com/atom/ns#' term='demoiselle'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><category scheme='http://www.blogger.com/atom/ns#' term='jboss'/><title type='text'>Auction5 sample web application released</title><content type='html'>&lt;br/&gt;&lt;br /&gt;I'm very proud to announce that &lt;b&gt;Auction5&lt;/b&gt;, a sample web application built under &lt;b&gt;Demoiselle Framework&lt;/b&gt; [1] has just been released to the public. Its complete documentation including source codes retrieval and deployment instructions can be found here: [2].&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Auction5&lt;/b&gt; is a MVC-structured application that exemplifies an &lt;i&gt;online auction system&lt;/i&gt; using Demoiselle Framework and related technologies. Its main goal is to provide a complete transactional application based on &lt;b&gt;JavaServer Faces&lt;/b&gt; (&lt;b&gt;JSF 1.2&lt;/b&gt; [3]) and &lt;b&gt;Java Persistence API&lt;/b&gt; (&lt;b&gt;JPA 1.0&lt;/b&gt; [4]) specifications.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/SvYjFzBZ-NI/AAAAAAAAAJg/DEQNZj7jBDg/s1600-h/auction5-home-r.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 203px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/SvYjFzBZ-NI/AAAAAAAAAJg/DEQNZj7jBDg/s400/auction5-home-r.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5401543385579911378" /&gt;&lt;/a&gt;&lt;br /&gt;Moreover, the sample assembles several top computing technologies such as Java EE, Maven, JBoss Application Server, Apache Tomcat, and PostgreSQL DBMS.&lt;br /&gt;&lt;br /&gt;Please send me your comments and or suggestions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References:&lt;/b&gt;&lt;br /&gt;[1] &lt;a title="Demoiselle Framework" href="http://sourceforge.net/projects/demoiselle/" target="_blank"&gt;Demoiselle Framework&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="Auction5 Application Sample" href="http://demoiselle-samp.sourceforge.net/auction5/" target="_blank"&gt;Auction5 Application Sample&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="JavaServer Faces" href="http://jcp.org/en/jsr/detail?id=127" target="_blank"&gt;JavaServer Faces 1.2&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="Java Persistence API" href="http://jcp.org/en/jsr/detail?id=220" target="_blank"&gt;Java Persistence API 1.0&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-3585110683176028852?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/3585110683176028852/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/11/auction5-sample-web-application.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3585110683176028852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3585110683176028852'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/11/auction5-sample-web-application.html' title='Auction5 sample web application released'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/SvYjFzBZ-NI/AAAAAAAAAJg/DEQNZj7jBDg/s72-c/auction5-home-r.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-731419083715652663</id><published>2009-10-28T06:07:00.001-07:00</published><updated>2009-10-28T09:51:20.024-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Script em Shell para monitoração de resultado de concurso</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Eis um script em Shell simples para automatizar o acompanhamento de resultados de concurso pela Internet.&lt;br /&gt;&lt;br /&gt;É só configurar a URL desejada e o intervalo entre as verificações (atualmente 15 minutos) e em seguida botar esse negócio para rodar em um terminal. No momento que aparecer alguma novidade o Firefox irá "popar"!&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;URL="http://www.cops.uel.br/?content=concursos/81_celepar/index.html"&lt;br /&gt;&lt;br /&gt;while true&lt;br /&gt;do&lt;br /&gt; echo "Recuperando página..."&lt;br /&gt; wget $URL -O res.html&lt;br /&gt; if [ $? -ne 0 ]; then continue; fi&lt;br /&gt;&lt;br /&gt; echo "Comparando arquivos..."&lt;br /&gt; if [ -f ult.html ]&lt;br /&gt; then&lt;br /&gt;  diff res.html ult.html &amp;gt; /dev/null&lt;br /&gt;  dif=$?&lt;br /&gt; else&lt;br /&gt;  dif=0&lt;br /&gt; fi&lt;br /&gt;&lt;br /&gt; mv res.html ult.html&lt;br /&gt;&lt;br /&gt; if [ $dif -ne 0 ]&lt;br /&gt; then&lt;br /&gt;  echo 'Saiu o resultado!'&lt;br /&gt;  firefox $URL&lt;br /&gt;  break&lt;br /&gt; fi&lt;br /&gt;&lt;br /&gt; echo "Aguardando..."&lt;br /&gt; sleep 900 # 15 min&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;exit 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Use-o com moderação. :D&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-731419083715652663?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/731419083715652663/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/10/script-em-shell-para-monitoracao-de.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/731419083715652663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/731419083715652663'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/10/script-em-shell-para-monitoracao-de.html' title='Script em Shell para monitoração de resultado de concurso'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-110337242098772183</id><published>2009-10-07T10:57:00.000-07:00</published><updated>2009-10-07T11:26:48.271-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>PGCon Brasil 2009</title><content type='html'>&lt;/br&gt;&lt;br /&gt;Pessoal, faltam só alguns dias para o &lt;span style="font-weight: bold;"&gt;PGCon Brasil 2009&lt;/span&gt;, o maior evento de &lt;span style="font-weight: bold;"&gt;PostgreSQL&lt;/span&gt; da América Latina!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/SszWw8PCW6I/AAAAAAAAAJA/b7nM0bQis4Q/s1600-h/topo-pgconbr.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 105px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/SszWw8PCW6I/AAAAAAAAAJA/b7nM0bQis4Q/s400/topo-pgconbr.jpg" alt="" id="BLOGGER_PHOTO_ID_5389918990346902434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Confira maiores informações no site do evento:&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://pgcon.postgresql.org.br/2009/"&gt;http://pgcon.postgresql.org.br/2009/&lt;/a&gt;&lt;br /&gt;&lt;/br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-110337242098772183?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/110337242098772183/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/10/pgcon-brasil-2009.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/110337242098772183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/110337242098772183'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/10/pgcon-brasil-2009.html' title='PGCon Brasil 2009'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YGilJHLjrrI/SszWw8PCW6I/AAAAAAAAAJA/b7nM0bQis4Q/s72-c/topo-pgconbr.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-1622512830808616383</id><published>2009-10-02T04:59:00.000-07:00</published><updated>2009-10-02T05:05:02.900-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='junk'/><title type='text'>Poster Motivacional: Fiat Lux!</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;a href='http://www.icanhasmotivation.com/page/13/' target="_new"&gt;&lt;img src='http://www.icanhasmotivation.com/wp-content/uploads/2009/06/science.jpg' alt='science'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-1622512830808616383?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/1622512830808616383/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/10/poster-motivacional-fiat-lux.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1622512830808616383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1622512830808616383'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/10/poster-motivacional-fiat-lux.html' title='Poster Motivacional: Fiat Lux!'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-5089442187824003823</id><published>2009-09-24T11:23:00.000-07:00</published><updated>2009-10-17T14:10:26.390-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j2ee'/><category scheme='http://www.blogger.com/atom/ns#' term='demoiselle'/><title type='text'>Demoiselle JPA in a Nutshell</title><content type='html'>&lt;br/&gt;&lt;br /&gt;One of the greatest new features coming to 1.1 release of &lt;b&gt;Demoiselle Framework&lt;/b&gt; [1] is the ability of using &lt;b&gt;JPA&lt;/b&gt; [2] (Java Persistence API) in a straightforward manner. JPA specification [3] is a trend in Java development and is often recommended to be used in new applications.&lt;br /&gt;&lt;br /&gt;In this article we'll explore the technical steps involved on developing the simplest &lt;b&gt;DAO&lt;/b&gt; [4] (Data Access Object) implementation classes with the new JPA support components.&lt;br /&gt;&lt;br /&gt;So, what's new in Demoiselle concerning JPA? First of all, there is a new injection aspect towards &lt;b&gt;IDAO&lt;/b&gt; [5] interfaces. Basic classes implementing IDAO interface should now simply have an attribute of type &lt;b&gt;EntityManager&lt;/b&gt; [6] annotated by &lt;b&gt;@Injection&lt;/b&gt; and then with the aid of AspectJ engine and some proxy classes the magic happens!&lt;br /&gt;&lt;br /&gt;For instance, consider the following &lt;b&gt;IDepartmentDAO&lt;/b&gt; interface in order to manage a &lt;b&gt;Department&lt;/b&gt; entity:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public interface IDepartmentDAO extends IDAO&amp;lt;Department&amp;gt; {&lt;br /&gt;&lt;br /&gt;    public Department findById(Short id);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The respective implementation class &lt;b&gt;DepartmentDAO&lt;/b&gt; should have the structure below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class DepartmentDAO implements IDepartmentDAO {&lt;br /&gt;&lt;br /&gt;    @Injection&lt;br /&gt;    private EntityManager em;&lt;br /&gt;&lt;br /&gt;    public Department findById(Short id) {&lt;br /&gt;        return em.find(Department.class, id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public boolean exists(Department pojo) {&lt;br /&gt;        return em.contains(pojo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Object insert(Department pojo) {&lt;br /&gt;        em.persist(pojo);&lt;br /&gt;        return pojo;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void update(Department pojo) {&lt;br /&gt;        em.merge(pojo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void remove(Department pojo) {&lt;br /&gt;        em.remove(pojo);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simple, isn't it?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EntityManager&lt;/b&gt; is the interface used to interact with the persistence context in JPA. A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed. This interface defines the methods that are used to interact with the persistence context. The EntityManager API is used to create and remove persistent entity instances, to find entities by their primary key, and to query over entities.&lt;br /&gt;&lt;br /&gt;Within a given unit of work, such as an HTTP request in web applications, a single instance of EntityManager is created and automatically injected on every DAO class that is referenced on that thread. That EntityManager is then closed as the transaction is finished.&lt;br /&gt;&lt;br /&gt;Moreover, even outside a complete and robust Java EE application, i.e. without an EJB [3] container, the developer could make easy use of JPA in Demoiselle!&lt;br /&gt;&lt;br /&gt;In order to turn it even simpler for the developer, the DAO implementation could still make use of the new &lt;b&gt;JPAGenericDAO&lt;/b&gt; [7] support class. Thus, &lt;b&gt;DepartmentDAO&lt;/b&gt; could have the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class DepartmentDAO extends JPAGenericDAO&amp;lt;Department&amp;gt;&lt;br /&gt;    implements IDepartmentDAO {&lt;br /&gt;&lt;br /&gt;    public Department findById(Short id) {&lt;br /&gt;        return super.findById(id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In other words, there is no need anymore of storing an EntityManager field and to implement all IDAO methods. That is, there will be almost nothing left to do but customized business rules methods!&lt;br /&gt;&lt;br /&gt;If you want to know more about the framework technical details, there will be another article explaining the whole architecture behind the scenes. :D&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References:&lt;/b&gt;&lt;br /&gt;[1] &lt;a title="Demoiselle Framework" href="http://sourceforge.net/projects/demoiselle/" target="_blank"&gt;Demoiselle Framework&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="The Java Persistence API" href="http://java.sun.com/developer/technicalArticles/J2EE/jpa/" target="_blank"&gt;The Java Persistence API&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="EJB 3.0 JPA Specification" href="http://jcp.org/aboutJava/communityprocess/final/jsr220/" target="_blank"&gt;EJB 3.0 JPA Specification&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="Data Access Object" href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html" target="_blank"&gt;Data Access Object&lt;/a&gt;&lt;br /&gt;[5] &lt;a title="IDAO interface" href="http://demoiselle.svn.sourceforge.net/viewvc/demoiselle/trunk/demoiselle/demoiselle-core/src/main/java/br/gov/framework/demoiselle/core/layer/IDAO.java?view=markup" target="_blank"&gt;IDAO interface&lt;/a&gt;&lt;br /&gt;[6] &lt;a title="EntityManager interface" href="http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html" target="_blank"&gt;EntityManager interface&lt;/a&gt;&lt;br /&gt;[7] &lt;a title="JPAGenericDAO class" href="http://demoiselle.svn.sourceforge.net/viewvc/demoiselle/trunk/demoiselle/demoiselle-persistence/src/main/java/br/gov/framework/demoiselle/persistence/JPAGenericDAO.java?view=markup" target="_blank"&gt;JPAGenericDAO class&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;!--&lt;br /&gt;One of the greatest new features coming to 1.1 release of Demoiselle Framework is the ability of using JPA in a straightforward manner. JPA specification is a trend in Java development and is often recommended to be used in new applications.&lt;br /&gt;&lt;br /&gt;In this article we’ll explore the technical steps involved on developing the simplest DAO implementation classes with the new JPA support components.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/apps/wordpress/demoiselle/2009/09/24/demoiselle-jpa-in-a-nutshell/"&gt;http://sourceforge.net/apps/wordpress/demoiselle/2009/09/24/demoiselle-jpa-in-a-nutshell/&lt;/a&gt;&lt;br /&gt;--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-5089442187824003823?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/5089442187824003823/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/09/demoiselle-jpa-in-nutshell.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/5089442187824003823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/5089442187824003823'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/09/demoiselle-jpa-in-nutshell.html' title='Demoiselle JPA in a Nutshell'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6697240777811043597</id><published>2009-09-08T19:42:00.000-07:00</published><updated>2009-09-08T19:48:02.460-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Tips on PostgreSQL tuning</title><content type='html'>&lt;br/&gt;&lt;br /&gt;At last I found something more concise towards PostgreSQL DBMS fine tuning. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server" target="new"&gt;http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6697240777811043597?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6697240777811043597/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/09/tips-on-postgresql-tuning.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6697240777811043597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6697240777811043597'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/09/tips-on-postgresql-tuning.html' title='Tips on PostgreSQL tuning'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6263505748124237059</id><published>2009-09-08T17:38:00.001-07:00</published><updated>2009-09-08T19:47:42.250-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Cedrus PostgreSQL Management versão 2.0</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/Sqb5LZeegcI/AAAAAAAAAI4/ObmVVButxws/s1600-h/cedrus_p.png"&gt;&lt;img style="float:left; margin:0px 20px 20px 0px;cursor:pointer; cursor:hand;width: 300px; height: 101px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/Sqb5LZeegcI/AAAAAAAAAI4/ObmVVButxws/s400/cedrus_p.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5379260779153228226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Pessoal, estou organizando esforços para o desenvolvimento da segunda geração do &lt;b&gt;Cedrus&lt;/b&gt; [1], um gerenciador para o &lt;b&gt;SGBD PostgreSQL&lt;/b&gt; criado em 2006 na CELEPAR e apresentado ao público no CONISLI [4] naquele mesmo ano em São Paulo.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Dessa vez será adotada a plataforma &lt;b&gt;Launchpad&lt;/b&gt; para o gerenciamento do projeto. Se você tiver interesse em participar de qualquer das seguintes etapas (requisitos, projeto, desenvolvimento ou testes) ou se desejar somente dar sugestões, mesmo se você só tiver experiência com administração de outros SGBDs, sinta-se livre em conhecer o projeto [2] ou em fazer parte da equipe [3]!&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Referências:&lt;/h3&gt;&lt;br /&gt;[1] &lt;a href="http://sourceforge.net/projects/cedrus" target="new"&gt;Cedrus 1.0 no SourceForge&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="https://launchpad.net/cedrus" target="new"&gt;Cedrus 2.0 no Launchpad&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="https://launchpad.net/~cedrus" target="new"&gt;Equipe do Cedrus no Launchpad&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://pt.wikipedia.org/wiki/Conisli" target="new"&gt;CONISLI - Congresso Internacional de Software Livre&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6263505748124237059?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6263505748124237059/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/09/cedrus-20.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6263505748124237059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6263505748124237059'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/09/cedrus-20.html' title='Cedrus PostgreSQL Management versão 2.0'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YGilJHLjrrI/Sqb5LZeegcI/AAAAAAAAAI4/ObmVVButxws/s72-c/cedrus_p.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2396680425560429543</id><published>2009-08-18T07:18:00.000-07:00</published><updated>2009-08-18T07:32:55.018-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='maven'/><title type='text'>Plugins essenciais para o Eclipse...</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Eis alguns plugins interessantes e às vezes indispensáveis para a &lt;span style="font-weight: bold;"&gt;IDE Eclipse&lt;/span&gt; [1]:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;m2eclipse&lt;/span&gt; [2]: integração do Maven 2 com o Eclipse&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;JBoss Tools&lt;/span&gt; [3]: utilitários para desenvolvimento de projetos Web&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;AJDT&lt;/span&gt; [4]: ferramentas de desenvolvimento com AspectJ (AJ)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Subclipse&lt;/span&gt; [5]: suporte ao controle de versionamento Subversion (SVN)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/Soq5y0buCqI/AAAAAAAAAIw/_dRZO2c7xOI/s1600-h/About+Eclipse.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 192px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/Soq5y0buCqI/AAAAAAAAAIw/_dRZO2c7xOI/s400/About+Eclipse.png" alt="" id="BLOGGER_PHOTO_ID_5371309788312242850" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lembre-se de que o ideal é sempre instalar os plugins via &lt;span style="font-style: italic;"&gt;Update Site&lt;/span&gt;...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Referências:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;[1] http://www.eclipse.org/&lt;br /&gt;[2] http://m2eclipse.sonatype.org/&lt;br /&gt;[3] http://www.jboss.org/tools/&lt;br /&gt;[4] http://www.eclipse.org/ajdt/&lt;br /&gt;[5] http://subclipse.tigris.org/&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2396680425560429543?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2396680425560429543/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/08/plugins-essenciais-para-o-eclipse.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2396680425560429543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2396680425560429543'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/08/plugins-essenciais-para-o-eclipse.html' title='Plugins essenciais para o Eclipse...'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YGilJHLjrrI/Soq5y0buCqI/AAAAAAAAAIw/_dRZO2c7xOI/s72-c/About+Eclipse.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6401082094898094621</id><published>2009-08-04T10:43:00.000-07:00</published><updated>2009-08-04T11:40:23.429-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>findjar.com: Encontre o jarro perdido!</title><content type='html'>&lt;br&gt;&lt;br /&gt;&lt;h3&gt;O problema: java.lang.ClassNotFoundException&lt;/h3&gt;&lt;br /&gt;Como desenvolvedor Java, você com certeza passou por isso alguma vez...&lt;br /&gt;Eis um exemplo de &lt;i&gt;stack trace&lt;/i&gt; em que ocorre este tipo de exceção:&lt;br /&gt;&lt;span style="color:red;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory&lt;br /&gt; at java.net.URLClassLoader$1.run(URLClassLoader.java:200)&lt;br /&gt; at java.security.AccessController.doPrivileged(Native Method)&lt;br /&gt; at java.net.URLClassLoader.findClass(URLClassLoader.java:188)&lt;br /&gt; at java.lang.ClassLoader.loadClass(ClassLoader.java:307)&lt;br /&gt; at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)&lt;br /&gt; at java.lang.ClassLoader.loadClass(ClassLoader.java:252)&lt;br /&gt; at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)&lt;br /&gt; ... 21 more&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Para resolver isso, é preciso encontrar o arquivo JAR em que a classe referenciada se encontra e colocá-lo no &lt;i&gt;classpath&lt;/i&gt; da aplicação que está sendo executada. Mas e se não soubermos onde fica essa classe...?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;A solução 1: grep&lt;/h3&gt;&lt;br /&gt;Se estiver com sorte, você já possui a biblioteca que contém essa classe. Neste caso, no Linux basta executar um &lt;i&gt;rgrep&lt;/i&gt; ou um &lt;i&gt;grep -r&lt;/i&gt; e copiar o arquivo da biblioteca.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;A solução 2: findjar.com&lt;/h3&gt;&lt;br /&gt;Caso você ainda não possua a biblioteca localmente, é preciso saber o nome do arquivo JAR e onde encontrá-lo na Internet...&lt;br /&gt;&lt;br /&gt;Para a primeira pergunta, o site &lt;b&gt;findJAR.com&lt;/b&gt;[1] é um grande auxílio. Trata-se de um motor de busca que nos ajuda a encontrar arquivos do tipo JAR que contêm as classes Java requeridas. Basta digitar o nome (simples ou qualificado) da classe que você precisa e iniciar a busca!&lt;br /&gt;&lt;br /&gt;findJAR.com é uma mão na roda para resolver com facilidade problemas do tipo &lt;b&gt;NoClassDefFoundError&lt;/b&gt; e &lt;b&gt;ClassNotFoundException&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Referências:&lt;/h3&gt;&lt;br /&gt;[1] &lt;a href="http://www.findjar.com"&gt;http://www.findjar.com&lt;/a&gt;&lt;br /&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6401082094898094621?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6401082094898094621/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/08/findjarcom-encontre-o-jarro-perdido.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6401082094898094621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6401082094898094621'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/08/findjarcom-encontre-o-jarro-perdido.html' title='findjar.com: Encontre o jarro perdido!'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-7878812023024509978</id><published>2009-08-02T15:40:00.000-07:00</published><updated>2009-10-18T16:07:50.979-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j2ee'/><category scheme='http://www.blogger.com/atom/ns#' term='tomcat'/><title type='text'>Encoding UTF-8 no Tomcat 6.0</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Ao utilizar o servidor &lt;b&gt;Apache Tomcat 6.0&lt;/b&gt; [1] para o deploy de aplicações Web em Java utilizando o encoding &lt;b&gt;Unicode&lt;/b&gt; (UTF-8) [2] podemos enfrentar pequenos problemas quando existe entrada de dados pelo usuário.&lt;br /&gt;&lt;br /&gt;Por exemplo, considere a aplicação a seguir que faz uso de um formulário para o cadastro de categorias de produtos:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/Sn5F-XOkS4I/AAAAAAAAAFo/BQNV9DrpTjU/s1600-h/tela5.png"&gt;&lt;img style="cursor: pointer; width: 200px; height: 150px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/Sn5F-XOkS4I/AAAAAAAAAFo/BQNV9DrpTjU/s200/tela5.png" alt="" id="BLOGGER_PHOTO_ID_5367804743561530242" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A anomalia ocorre durante o processo de envio da requisição HTTP do tipo &lt;b&gt;POST&lt;/b&gt; [3]. Veja na imagem a seguir o problema na acentuação resultante do formulário:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/Sn5F-nQaMsI/AAAAAAAAAFw/NNJaBYx_gxI/s1600-h/tela6.png"&gt;&lt;img style="cursor: pointer; width: 200px; height: 150px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/Sn5F-nQaMsI/AAAAAAAAAFw/NNJaBYx_gxI/s200/tela6.png" alt="" id="BLOGGER_PHOTO_ID_5367804747864224450" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Uma possível solução para este problema consiste na criação de um filtro, ou &lt;b&gt;Filter&lt;/b&gt; [4], um padrão de projeto da especificação Java EE. A função deste filtro é de interceptar as requisições HTTP e forçar a codificação de caracteres para a que for parametrizada (no exemplo, a UTF-8).&lt;br /&gt;&lt;br /&gt;A primeira etapa envolve a criação de uma nova classe na aplicação, cujo nome será &lt;b&gt;EncodingFilter&lt;/b&gt; e a qual deverá implementar a &lt;b&gt;interface Filter&lt;/b&gt; [5] da especificação Java Servlet. Desta forma, o arquivo &lt;b&gt;EncodingFilter.java&lt;/b&gt; terá o seguinte conteúdo:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package com.hsiconsultoria.zabumba.filter;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import javax.servlet.Filter;&lt;br /&gt;import javax.servlet.FilterChain;&lt;br /&gt;import javax.servlet.FilterConfig;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;import javax.servlet.ServletRequest;&lt;br /&gt;import javax.servlet.ServletResponse;&lt;br /&gt;&lt;br /&gt;public class EncodingFilter implements Filter {&lt;br /&gt;&lt;br /&gt;  private String encoding;&lt;br /&gt;&lt;br /&gt;  public void init(FilterConfig config) throws ServletException {&lt;br /&gt;      this.encoding = config.getInitParameter("encoding");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void destroy() {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void doFilter(ServletRequest request,&lt;br /&gt;          ServletResponse response, FilterChain chain)&lt;br /&gt;      throws IOException, ServletException {&lt;br /&gt;   &lt;br /&gt;      request.setCharacterEncoding(encoding);&lt;br /&gt;   &lt;br /&gt;      chain.doFilter(request, response);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Em seguida é preciso indicar a existência desse novo filtro no arquivo &lt;b&gt;WEB-INF/web.xml&lt;/b&gt;, também conhecido como &lt;b&gt;Deployment Descriptor&lt;/b&gt; [6]. É neste arquivo que o filtro será devidamente configurado para interceptar as requisições HTTP na aplicação Web.&lt;br /&gt;&lt;br /&gt;Sendo assim, basta incluir as linhas seguintes no arquivo &lt;b&gt;web.xml&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;  &lt;filter&gt;&lt;br /&gt;      &lt;display-name&gt;EncodingFilter&lt;/display-name&gt;&lt;br /&gt;      &lt;filter-name&gt;EncodingFilter&lt;/filter-name&gt;&lt;br /&gt;      &lt;filter-class&gt;&lt;br /&gt;          com.hsiconsultoria.zabumba.filter.EncodingFilter&lt;br /&gt;      &lt;/filter-class&gt;&lt;br /&gt;      &lt;init-param&gt;&lt;br /&gt;          &lt;description&gt;filtro para codificação dos caracteres&lt;/description&gt;&lt;br /&gt;          &lt;param-name&gt;encoding&lt;/param-name&gt;&lt;br /&gt;          &lt;param-value&gt;UTF-8&lt;/param-value&gt;&lt;br /&gt;      &lt;/init-param&gt;&lt;br /&gt;  &lt;/filter&gt;&lt;br /&gt;  &lt;filter-mapping&gt;&lt;br /&gt;      &lt;filter-name&gt;EncodingFilter&lt;/filter-name&gt;&lt;br /&gt;      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;&lt;br /&gt;  &lt;/filter-mapping&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para finalizar, é só salvar tudo e reinicializar o Tomcat. Veja na tela abaixo o resultado dessa alteração na aplicação:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/Sn5F-9EaToI/AAAAAAAAAF4/izD4ac3keTg/s1600-h/tela7.png"&gt;&lt;img style="cursor: pointer; width: 200px; height: 150px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/Sn5F-9EaToI/AAAAAAAAAF4/izD4ac3keTg/s200/tela7.png" alt="" id="BLOGGER_PHOTO_ID_5367804753719479938" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Referências:&lt;/b&gt;&lt;br /&gt;[1] &lt;a title="Apache Tomcat 6.0" href="http://tomcat.apache.org/" target="_blank"&gt;Apache Tomcat 6.0&lt;/a&gt;&lt;br /&gt;[2] &lt;a title="Formato UTF-8" href="http://pt.wikipedia.org/wiki/UTF-8" target="_blank"&gt;Formato UTF-8&lt;/a&gt;&lt;br /&gt;[3] &lt;a title="HTTP/1.1 Method Definitions" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html" target="_blank"&gt;HTTP/1.1 Method Definitions&lt;/a&gt;&lt;br /&gt;[4] &lt;a title="Intercepting Filter Pattern" href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html" target="_blank"&gt;Intercepting Filter Pattern&lt;/a&gt;&lt;br /&gt;[5] &lt;a title="Interface Filter" href="http://java.sun.com/products/servlet/2.5/docs/servlet-2_5-mr2/javax/servlet/Filter.html" target="_blank"&gt;Interface Filter&lt;/a&gt;&lt;br /&gt;[6] &lt;a title="Java EE Deployment Descriptors" href="http://java.sun.com/xml/ns/javaee/index.html" target="_blank"&gt;Java EE Deployment Descriptors&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-7878812023024509978?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/7878812023024509978/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/08/encoding-utf-8-no-tomcat-60.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/7878812023024509978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/7878812023024509978'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/08/encoding-utf-8-no-tomcat-60.html' title='Encoding UTF-8 no Tomcat 6.0'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YGilJHLjrrI/Sn5F-XOkS4I/AAAAAAAAAFo/BQNV9DrpTjU/s72-c/tela5.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-1245607729809555808</id><published>2009-06-25T11:08:00.000-07:00</published><updated>2009-08-04T11:32:31.457-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>C'est où le son dans Firefox en Ubuntu ?</title><content type='html'>&lt;br/&gt;&lt;br /&gt;&lt;p&gt;Même avec la présence du &lt;span style="font-weight: bold;"&gt;plugin VLC&lt;/span&gt; [1] pour &lt;span style="font-weight: bold;"&gt;Firefox&lt;/span&gt; sur &lt;span style="font-weight: bold;" title="" hptip="Faute d'orthographe potentielle - suggestions : L'inox, Lynx, Links, L'inouï, Lin, Lux, Linéaux, Inox, Lino, L'indu, L'insu, Liner, Linos, Minus, Sinus, L'immun, L'influx, L'infus, L'index, L'indue, L'input, L'inule, L'anus, L'inné" class="spellver"&gt;Linux&lt;/span&gt;, le son ne marche pas tout simplement...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;À travers l'adresse secret &lt;a href="about:config" target="nova"&gt;"about: config"&lt;/a&gt; Firefox, nous avons la liste des plugins installés dans le navigateur, notamment le plugin VLC (qui permet des extensions de fichiers tels que .OGG) :&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/SkPB_CC_CLI/AAAAAAAAAFY/7cSFXPIWXw4/s1600-h/firefox-vlc.png" target="nova"&gt;&lt;img style="cursor: pointer; width: 320px; height: 234px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/SkPB_CC_CLI/AAAAAAAAAFY/7cSFXPIWXw4/s320/firefox-vlc.png" alt="" id="BLOGGER_PHOTO_ID_5351334070871591090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Néanmois, il nous reste mettre en place le wrapper &lt;span style="font-weight: bold;"&gt;ALSA&lt;/span&gt; [2] pour des applications &lt;span style="font-weight: bold;"&gt;OSS&lt;/span&gt; [3].&lt;br /&gt;&lt;br /&gt;Au Linux il existe le paquet "alsa-oss" qui fournisse précisément cette fonctionnalité ! Ainsi, il faut lancer l'instruction suivante en tant que "root" :&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 0, 153);font-family:courier new;" &gt;# apt-get install alsa-oss&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Il vous suffit ensuite de redémarrer Firefox pour que le son passe à marcher !&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YGilJHLjrrI/SkPCTaUMN_I/AAAAAAAAAFg/oR-Je3Wq-_U/s1600-h/fisl10-peter.png" target="nova"&gt;&lt;img style="cursor: pointer; width: 320px; height: 250px;" src="http://3.bp.blogspot.com/_YGilJHLjrrI/SkPCTaUMN_I/AAAAAAAAAFg/oR-Je3Wq-_U/s320/fisl10-peter.png" alt="" id="BLOGGER_PHOTO_ID_5351334420983592946" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Je remercie Paulo de Tarso [4] pour ce conseil !&lt;/p&gt;&lt;p style="font-weight: bold;"&gt;Références :&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[1] &lt;a href="http://www.videolan.org/vlc/" target="nova"&gt;VLC open-source multimedia framework, player and server&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[2] &lt;a href="http://alsa.sourceforge.net/" target="nova"&gt;ALSA: the Advanced Linux Sound Architecture&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[3] &lt;a href="http://www.opensound.com/oss.html" target="nova"&gt;OSS is the free version of the Open Sound System&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[4] &lt;a href="http://pools.wordpress.com/" target="nova"&gt;70015: A vida com Linux, Mac, Windows e Iphone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-1245607729809555808?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/1245607729809555808/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/06/cest-ou-le-son-dans-firefox-en-ubuntu.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1245607729809555808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1245607729809555808'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/06/cest-ou-le-son-dans-firefox-en-ubuntu.html' title='C&apos;est où le son dans Firefox en Ubuntu ?'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/SkPB_CC_CLI/AAAAAAAAAFY/7cSFXPIWXw4/s72-c/firefox-vlc.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8760603194757670032</id><published>2009-06-19T11:57:00.000-07:00</published><updated>2009-08-04T11:34:31.669-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Testando HTTP sem usar um navegador</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Um servidor WEB funciona utilizando o protocolo HTTP [1], e responde a requisições tais como "HTTP GET" vindas de um cliente (o browser).&lt;br /&gt;&lt;br /&gt;Geralmente não vemos o que está sendo transmitido entre as duas partes: cliente (navegador) e servidor WEB. Entretanto, podemos facilmente inspecionar esse tráfego de dados através da ferramenta &lt;span style="font-weight: bold;"&gt;telnet&lt;/span&gt; [2], disponível em praticamente qualquer plataforma.&lt;br /&gt;&lt;br /&gt;Para fazer o teste, primeiro abra um terminal no Linux ou um prompt de comando no Windows. Você vai precisar então digitar o comando com a seguinte sintaxe:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(102, 102, 102); font-style: italic;font-family:courier new;" &gt;telnet [servidor] [porta]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Por exemplo, para acessar a página do &lt;span style="font-weight: bold;"&gt;Grupo de Usuários PostgreSQL do Brasil&lt;/span&gt; [3], execute o seguinte:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-family:courier new;" &gt;telnet postgresql.org.br 80&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Com isso você estará conectado ao servidor WEB especificado e poderá desta forma executar qualquer comando do &lt;span style="font-weight: bold;"&gt;protocolo HTTP&lt;/span&gt; [4] desejado, tal como GET, HEAD ou POST.&lt;br /&gt;&lt;br /&gt;Em seguida, para efetuar uma requisição HTTP do tipo GET ao servidor, você precisará executar um comando no seguinte formato:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 51); font-style: italic; font-weight: bold;font-family:courier new;" &gt;GET [página] &lt;página&gt; HTTP/1.0&lt;/página&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Para exemplificar, faça uma simulação à &lt;a href="http://postgresql.org.br/node/61"&gt;esta&lt;/a&gt; página, digitando o texto a seguir no telnet:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-family:courier new;" &gt;GET /node/61 HTTP/1.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Atenção: pressione ENTER duas vezes. Se a página existir no servidor, você terá como resultado algo como ilustrado na figura abaixo.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/Sj2YNj9HwOI/AAAAAAAAAFQ/st_8Mbz6C9Q/s1600-h/telnet3.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 218px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/Sj2YNj9HwOI/AAAAAAAAAFQ/st_8Mbz6C9Q/s320/telnet3.png" alt="" id="BLOGGER_PHOTO_ID_5349599291143340258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Preste atenção no cabeçalho (&lt;span style="font-style: italic;"&gt;header&lt;/span&gt;) HTTP enviado pelo servidor após a execução. São justamente estes dados que o browser interpreta automaticamente e o usuário não vê.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;Date: Sun, 21 Jun 2009 02:08:33 GMT&lt;br /&gt;Server: Apache/2.2.9 (Debian) PHP/5.2.0-8+etch15 mod_ssl/2.2.9 OpenSSL/0.9.8g&lt;br /&gt;X-Powered-By: PHP/5.2.0-8+etch15&lt;br /&gt;Set-Cookie: SESSd41d8cd98f00b204e9800998ecf8427e=baefb8cb6bc0a5ed29340ec05aa6ff38; expires=Tue, 14 Jul 2009 05:41:54 GMT; path=/&lt;br /&gt;Expires: Sun, 19 Nov 1978 05:00:00 GMT&lt;br /&gt;Last-Modified: Sun, 21 Jun 2009 02:08:34 GMT&lt;br /&gt;Cache-Control: store, no-cache, must-revalidate&lt;br /&gt;Cache-Control: post-check=0, pre-check=0&lt;br /&gt;Connection: close&lt;br /&gt;Content-Type: text/html; charset=utf-8&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A primeira linha é uma das mais importantes do cabeçalho, pois ela indica se houve sucesso ou erro durante o atendimento da requisição HTTP. O código &lt;span style="font-weight: bold;"&gt;200&lt;/span&gt; no exemplo significa que a página HTML foi recuperada com sucesso.&lt;br /&gt;&lt;br /&gt;Você pode ainda receber um código de status &lt;span style="font-weight: bold;"&gt;404&lt;/span&gt; caso a página não seja encontrada (ou seja, o famoso "Erro 404"), o código &lt;span style="font-weight: bold;"&gt;301&lt;/span&gt; se a página tiver sido movida permanentemente ou 401 caso você não tenha autorização para acessá-la.&lt;br /&gt;&lt;br /&gt;A lista completa dos códigos de status do protocolo HTTP pode ser consultada aqui [5]. Se você é um administrador de sistemas ou desenvolvedor de aplicações WEB possivelmente esta abordagem lhe será útil. :D&lt;br /&gt;&lt;br /&gt;O conteúdo HTML que será renderizado pelo browser vem logo após o cabeçalho.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Referências:&lt;/span&gt;&lt;br /&gt;[1] &lt;a href="http://pt.wikipedia.org/wiki/Http"&gt;http://pt.wikipedia.org/wiki/Http&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://pt.wikipedia.org/wiki/Telnet"&gt;http://pt.wikipedia.org/wiki/Telnet&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://postgresql.org.br/"&gt;http://postgresql.org.br&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="ftp://ftp.rfc-editor.org/in-notes/rfc1945.txt"&gt;Hypertext Transfer Protocol -- HTTP/1.0&lt;/a&gt;&lt;br /&gt;[5] &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;RFC 2616 - Status Code Definitions&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8760603194757670032?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8760603194757670032/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/06/testando-http-sem-usar-um-navegador.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8760603194757670032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8760603194757670032'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/06/testando-http-sem-usar-um-navegador.html' title='Testando HTTP sem usar um navegador'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/Sj2YNj9HwOI/AAAAAAAAAFQ/st_8Mbz6C9Q/s72-c/telnet3.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-1857267827599144188</id><published>2009-06-14T00:12:00.000-07:00</published><updated>2009-08-04T11:34:55.800-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='msdos'/><title type='text'>Sessão nostalgia: Microsoft Windows 3.1</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Ano: 1993. O sistema operacional geralmente encontrado em computadores pessoais aqui era o &lt;span style="font-weight: bold;"&gt;MS-DOS&lt;/span&gt; (versão 5.0, no máximo 6.22!). O &lt;span style="font-weight: bold;"&gt;Microsoft Windows 3.1&lt;/span&gt;, que era opcional na época, não passava de um gerenciador de aplicativos, o "Program Manager". O Linux? Esse não devia ter 2 anos ainda e ninguém fora do meio acadêmico ou talvez longe da Escandinávia tinha conhecimento dele...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;O tempo passou e aquele simples agregador de janelinhas foi tomando espaço e quem passou a ser esquecido foi o pobre do MS-DOS, que nos dias atuais não passa de um "Prompt de comando". Ninguém mais ouviu falar de AUTOEXEC.BAT, HIMEM.SYS, GORILLA.BAS, MEMMAKER, QEMM, DOS4GW...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;E eis que essa semana vejo um artigo na Internet em que um polonês maluco havia instalado o Microsoft Windows 3.1 no Symbian [1]...! Resolvi seguir o tutorial e fazer o mesmo, só por brincadeira, e funcionou mesmo! Aliás, não serve para nada além disso, pois fica lento, ruim de visualizar na tela, e sem teclado alfanumérico...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mesmo assim, empolgado pura e simplesmente pelo fator nostálgico, resolvi testar tal inutilidade janélica também no Linux! No caso do N95, o pseudo sistema operacional (AKA Win3.1) estava rodando em cima de um ambiente controlado pelo do DOSBox [2]. Na realidade o maior trabalho nessa façanha foi o porte do DOSBox para o Symbian pelo tal "kolijoco".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;No Linux, basta instalar o pacote &lt;span style="font-weight: bold;"&gt;dosbox&lt;/span&gt;. Em distros Debian-like, podemos fazer isso através do comando:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 0);font-family:courier new;" &gt;# apt-get install dosbox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Os discos de instalação do Windows 3.1 (na realidade 7 disquetes de 1,44 MB) podemos baixar de fontes extra-oficiais, como sites 4shared ou torrents. Acho que ninguém vai se importar de piratearmos um software que já está debutando, né?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Abra um terminal, dirija-se ao diretório em que o Windows 3.1 será instalado e execute o DOSBox:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 0);"&gt;$ cd /opt/win31&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 0);"&gt;$ dosbox&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Em seguida, já dentro do DOSBox, execute alguns comandos para montar o disco rígido e o primeiro disquete de instalação:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;mount c .&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;mount a /tmp/win31setup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Neste exemplo, os drives serão mapeados no DOS conforme o esquema a seguir:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;C: diretório /opt/win31 no Linux;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A: diretório /tmp/win31setup no Linux.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Execute a instalação do Windows através do comando a seguir:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;a:\setup.exe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Então basta seguir um clássico "Next, Next, Finish" e ao final executar:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;c:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;cd \windows&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;win&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;No final, eis o resultado: o &lt;span style="font-weight: bold;"&gt;Microsoft Windows 3.1&lt;/span&gt; sendo executado em uma janelinha de 640x480 pixels no Linux!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/SjSuN0C-3XI/AAAAAAAAAEo/upnkUPry_dQ/s1600-h/win31.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/SjSuN0C-3XI/AAAAAAAAAEo/upnkUPry_dQ/s320/win31.png" alt="" id="BLOGGER_PHOTO_ID_5347090209928306034" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para ter uma idéia do que está acontecendo, veja a tela inteira do Ubuntu Linux, rodando o Gnome como gerenciador de desktop e o DOSBOX ali no canto, totalmente sob controle...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/SjSvOp1gyEI/AAAAAAAAAEw/ChTMxOVxOjQ/s1600-h/win31-desktop.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/SjSvOp1gyEI/AAAAAAAAAEw/ChTMxOVxOjQ/s320/win31-desktop.png" alt="" id="BLOGGER_PHOTO_ID_5347091323878950978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Para facilitar as execuções posteriores, crie um arquivo com o nome "dosbox.conf" dentro do diretório do Windows 3.1 com o seguinte conteúdo:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;[sdl]&lt;br /&gt;# sem isso as setas do teclado não funcionam...&lt;br /&gt;usescancodes=false&lt;br /&gt;&lt;br /&gt;[autoexec]&lt;br /&gt;# meu teclado é layout alemão, substitua "gr" por "br"&lt;br /&gt;keyb gr&lt;br /&gt;# o resto aqui é para executar o windows ao iniciar&lt;br /&gt;mount c .&lt;br /&gt;c:&lt;br /&gt;cd windows&lt;br /&gt;win&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Agora, isso pode parecer piada nos tempos atuais: o Windows 3.1 recém-instalado não chegava a ocupar 12 MB de espaço em disco! Quem imaginaria que um dia o Windows iria exigir 10 GB de HD, hein!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/SjSw2nCtW3I/AAAAAAAAAE4/xSY3jEn3Vrc/s1600-h/win31-size.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 267px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/SjSw2nCtW3I/AAAAAAAAAE4/xSY3jEn3Vrc/s320/win31-size.png" alt="" id="BLOGGER_PHOTO_ID_5347093109835389810" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;O mais surpreendente é pensar que conseguíamos ser felizes com informática mesmo sem a World Wide Web... Agora vou procurar outras relíquias computacionais... Será que acho o Wolfenstein 3D ou Microsoft Word 6..? :D&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Referências:&lt;/span&gt;&lt;br /&gt;[1] &lt;a href="http://gizmodo.com/5159221/windows-31-runs-on-a-nokia-n95-creating-dangerous-ripple-in-space+time"&gt;Windows 3.1 Runs On a Nokia N95, Creating Dangerous Ripple in Space-Time&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://www.dosbox.com/"&gt;DOSBox: a x86 emulator with DOS&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-1857267827599144188?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/1857267827599144188/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/06/sessao-nostalgia-microsoft-windows-31.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1857267827599144188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/1857267827599144188'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/06/sessao-nostalgia-microsoft-windows-31.html' title='Sessão nostalgia: Microsoft Windows 3.1'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YGilJHLjrrI/SjSuN0C-3XI/AAAAAAAAAEo/upnkUPry_dQ/s72-c/win31.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-2797364738069918375</id><published>2009-05-20T10:07:00.001-07:00</published><updated>2009-10-18T19:40:39.114-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Echoing hidden psql statements</title><content type='html'>&lt;br/&gt;&lt;br /&gt;One of the greatest advantages of a Database Management System is its embedded &lt;b&gt;data dictionary&lt;/b&gt;, also called &lt;b&gt;metadata&lt;/b&gt; or &lt;b&gt;system catalog&lt;/b&gt; [1]. On PostgreSQL DBMS it is not different, and its metadata are widely used by database handling tools.&lt;br /&gt;&lt;br /&gt;A great and yet simple tool available to this relational database is &lt;b&gt;psql&lt;/b&gt; [2], a command-line, bash-enabled application that permits issuing SQL instructions to PostgreSQL server instances.&lt;br /&gt;&lt;br /&gt;Even when sending a simple command such as "\d" on psql, there might be one or several SQL instructions sent internally to that given instance. Knowing exactly what is being sent could help a database administrator or even a simple developer on common and ordinary daily tasks.&lt;br /&gt;&lt;br /&gt;So, how could we know those SQL instructions? Simpler than expected!&lt;br /&gt;&lt;br /&gt;There is an environment variable on psql called &lt;b&gt;ECHO_HIDDEN&lt;/b&gt;, which once set echoes all hidden instructions, as its own name says. In order to enable that, simply execute the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# \set ECHO_HIDDEN&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, try to issue some internal commands like "\l" (typing "\?" shows the entire list of options). Here is the output after enabling ECHO_HIDDEN:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# \l&lt;br /&gt;********* QUERY **********&lt;br /&gt;SELECT d.datname as "Name",&lt;br /&gt;       r.rolname as "Owner",&lt;br /&gt;       pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding"&lt;br /&gt;FROM pg_catalog.pg_database d&lt;br /&gt;  JOIN pg_catalog.pg_roles r ON d.datdba = r.oid&lt;br /&gt;ORDER BY 1;&lt;br /&gt;**************************&lt;br /&gt;&lt;br /&gt;            List of databases&lt;br /&gt;    Name     |     Owner      | Encoding &lt;br /&gt;-------------+----------------+----------&lt;br /&gt; auction5    | sa_auction5    | UTF8&lt;br /&gt; postgres    | postgres       | UTF8&lt;br /&gt; rodrigo     | rodrigo        | UTF8&lt;br /&gt; template0   | postgres       | UTF8&lt;br /&gt; template1   | postgres       | UTF8&lt;br /&gt;(5 rows)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note the contents enclosed by "QUERY" and "***". Here are the internal SQL instructions respectively performed.&lt;br /&gt;&lt;br /&gt;When you're done, you could deactivate this variable by executing the command below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;# \unset ECHO_HIDDEN&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it! :D&lt;br /&gt;&lt;br /&gt;&lt;b&gt;References:&lt;/b&gt;&lt;br /&gt;[1] &lt;a href="http://www.postgresql.org/docs/8.3/static/catalogs.html" target="nova"&gt;PostgreSQL 8.3.8 Documentation - System Catalogs&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://www.postgresql.org/docs/8.3/static/app-psql.html" target="nova"&gt;psql - PostgreSQL interactive terminal&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-2797364738069918375?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/2797364738069918375/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/05/echoing-hidden-psql-statements.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2797364738069918375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/2797364738069918375'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/05/echoing-hidden-psql-statements.html' title='Echoing hidden psql statements'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-6300162458509005851</id><published>2009-03-25T18:53:00.000-07:00</published><updated>2009-03-25T19:33:21.528-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Meu PostgreSQL não conecta!</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Começando do início...&lt;/h2&gt;&lt;br /&gt;Observação: Apesar de os testes terem sido feitos em ambiente Linux, os comandos (&lt;b&gt;ping, telnet, psql&lt;/b&gt;) e arquivos de configuração (&lt;b&gt;postgresql.conf, pg_hba.conf&lt;/b&gt;) existem e funcionam também no &lt;b&gt;Windows&lt;/b&gt;, &lt;b&gt;Macintosh&lt;/b&gt; ou &lt;b&gt;FreeBSD&lt;/b&gt;, no respectivo terminal.&lt;br /&gt;&lt;p&gt; Antes de tudo, façamos alguns testes que respondem à algumas perguntas.&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;A máquina está no ar e é enxergada na rede pelo cliente?&lt;/h2&gt;&lt;br /&gt;Um simples "ping" pode nos ajudar:&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);" class="code"&gt;$ ping 10.15.23.15&lt;/pre&gt;Se estiver tudo correto, aparecerá o texto abaixo:&lt;br /&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;rodrigo@asgard:~$ ping 10.15.23.15&lt;br /&gt;PING 10.15.23.15 (10.15.23.15) 56(84) bytes of data.&lt;br /&gt;64 bytes from 10.15.23.15: icmp_seq=1 ttl=64 time=0.044 ms&lt;br /&gt;64 bytes from 10.15.23.15: icmp_seq=2 ttl=64 time=0.034 ms&lt;br /&gt;64 bytes from 10.15.23.15: icmp_seq=3 ttl=64 time=0.034 ms&lt;br /&gt;&lt;br /&gt;--- 10.15.23.15 ping statistics ---&lt;br /&gt;3 packets transmitted, 3 received, 0% packet loss, time 1999ms&lt;br /&gt;rtt min/avg/max/mdev = 0.034/0.037/0.044/0.006 ms&lt;/pre&gt;Caso contrário, será exibido algo como:&lt;br /&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;rodrigo@asgard:~$ ping 10.15.23.150&lt;br /&gt;PING 10.15.23.150 (10.15.23.150) 56(84) bytes of data.&lt;br /&gt;From 10.15.23.15 icmp_seq=1 Destination Host Unreachable&lt;br /&gt;From 10.15.23.15 icmp_seq=2 Destination Host Unreachable&lt;br /&gt;From 10.15.23.15 icmp_seq=3 Destination Host Unreachable&lt;br /&gt;&lt;br /&gt;--- 10.15.23.150 ping statistics ---&lt;br /&gt;6 packets transmitted, 0 received, +3 errors,&lt;br /&gt;100% packet loss, time 5008ms, pipe 3&lt;/pre&gt;Se este for o caso, resolva este problema de conexão e configuração de rede antes de continuar.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;O servidor está respondendo ao serviço na porta do PostgreSQL?&lt;/h2&gt;&lt;br /&gt;Se não estiver, qualquer acesso externo ao &lt;b&gt;PostgreSQL&lt;/b&gt; é barrado, e a seguinte mensagem será exibida:&lt;br /&gt;&lt;pre style="color: rgb(204, 0, 0);" class="code"&gt;psql: could not connect to server: Conexão recusada&lt;br /&gt;  Is the server running on host "10.15.23.15" and accepting&lt;br /&gt;  TCP/IP connections on port 5432?&lt;/pre&gt;Para comprovar isso, podemos fazer um simples teste com o "telnet":&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);" class="code"&gt;$ telnet 10.15.23.15 5432&lt;/pre&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;rodrigo@asgard:~$ telnet 10.15.23.15 5432&lt;br /&gt;Trying 10.15.23.15...&lt;br /&gt;telnet: Unable to connect to remote host: Connection refused&lt;/pre&gt;Este é um problema que ocorre com 5 de cada 4 iniciantes neste banco de dados: a conexão não-local!&lt;br /&gt;Bom, o fato é que a configuração padrão do &lt;b&gt;PostgreSQL&lt;/b&gt; faz com que apenas conexões locais (via &lt;i&gt;soquete UNIX&lt;/i&gt;) sejam permitidas. O primeiro passo é alterar uma opção no arquivo de configurações &lt;b&gt;postgresql.conf&lt;/b&gt;:&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;th&gt;Versão&lt;/th&gt;&lt;br /&gt;&lt;th&gt;Original&lt;/th&gt;&lt;br /&gt;&lt;th&gt;Mudar para&lt;/th&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;7.X e anteriores&lt;/td&gt;&lt;br /&gt;&lt;td&gt;tcpip_socket = false&lt;/td&gt;&lt;br /&gt;&lt;td&gt;tcpip_socket = true&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt; &lt;tr&gt;&lt;br /&gt;&lt;td&gt;8.X em diante&lt;/td&gt;&lt;br /&gt;&lt;td&gt;listen_addresses = 'localhost'&lt;/td&gt;&lt;br /&gt;&lt;td&gt;listen_addresses = '*'&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Após salvar o arquivo, será preciso reiniciar o &lt;i&gt;SGBD &lt;/i&gt;(não basta apenas fazer um "reload").&lt;br /&gt;&lt;br /&gt;Agora refaça o teste do "telnet". Terá que aceitar a conexão e aparecer este texto:&lt;br /&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;rodrigo@asgard:~$ telnet 10.15.23.15 5432&lt;br /&gt;Trying 10.15.23.15...&lt;br /&gt;Connected to 10.15.23.15.&lt;br /&gt;Escape character is '^]'.&lt;/pre&gt;Dê um &lt;i&gt;CTRL+C&lt;/i&gt; para sair. Se ainda não funcionar, será preciso verificar se firewalls não estão impedindo a conexão entre o cliente e o servidor, na porta do &lt;b&gt;PostgreSQL&lt;/b&gt; (padrão: 5432). Resolva essa questão antes de continuar a leitura...&lt;br /&gt;&lt;br /&gt;Opa! Metade do serviço está concluída! Agora, outro problema que atormenta quem está começando, este erro ao tentar se conectar:&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);" class="code"&gt;$ psql -h 10.15.23.15 correios rodrigo&lt;/pre&gt;&lt;pre style="color: rgb(204, 0, 0);" class="code"&gt;psql: FATAL:  nenhuma entrada no pg_hba.conf para máquina "10.15.22.32",&lt;br /&gt;usuário "rodrigo", banco de dados "correios", SSL desabilitado&lt;/pre&gt;Sigamos a dica que o &lt;b&gt;PostgreSQL&lt;/b&gt; nos dá! Abra o seguinte arquivo de configuração: &lt;b&gt;pg_hba.conf&lt;/b&gt;.&lt;br /&gt;&lt;p&gt;Este arquivo controla: quais hosts têm permissão de conexão, como os clientes se autenticam, quais usuários do &lt;b&gt;PostgreSQL&lt;/b&gt; podem ser usados e que bancos de dados eles podem acessar. Os registros podem ter uma das seguintes formas:&lt;br /&gt;&lt;/p&gt;&lt;i&gt;&lt;pre&gt;local      DATABASE  USER  METHOD  [OPTION]&lt;br /&gt;host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]&lt;br /&gt;hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]&lt;br /&gt;hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]&lt;/pre&gt;&lt;/i&gt;Sendo assim, nestas entradas de permissões de acesso ao &lt;b&gt;PostgreSQL&lt;/b&gt;, podemos alterar:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;tipo de conexão ("local", "host")&lt;/li&gt;  &lt;li&gt;banco de dados ("all": todos)&lt;/li&gt;  &lt;li&gt;usuário ("all": todos)&lt;/li&gt;  &lt;li&gt;endereço IP e máscara (estilo &lt;i&gt;CIDR&lt;/i&gt;)&lt;/li&gt;  &lt;li&gt;método ("reject", "trust", "password", "md5", "ident same user")&lt;/li&gt; &lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;span style="font-weight: bold;"&gt;Importante: o arquivo é lido de cima para baixo, e a primeira entrada &lt;/span&gt;&lt;b style="font-weight: bold;"&gt;que esteja de acordo com a requisição é considerada.&lt;/b&gt; Isso é um fato que às vezes confunde os administradores. Os campos podem ser separados por espaços ou tabulações - tanto faz, funcionará de ambas as formas.&lt;br /&gt;&lt;p&gt; Bom, para resolver o problema em questão, precisamos incluir a seguinte linha:&lt;br /&gt;&lt;/p&gt;&lt;pre style="color: rgb(0, 102, 0);" class="code"&gt;host    correios    rodrigo        10.15.22.32/32        md5&lt;/pre&gt;Desta vez, não será preciso reiniciar o &lt;b&gt;PostgreSQL&lt;/b&gt;. No &lt;b&gt;Linux&lt;/b&gt;, podemos enviar um sinal do tipo &lt;i&gt;HUP&lt;/i&gt; das seguintes maneiras:&lt;br /&gt;&lt;pre style="color: rgb(51, 51, 255);" class="code"&gt;$ /etc/init.d/postgresql-8.1 reload&lt;/pre&gt;&lt;pre style="color: rgb(51, 51, 255);" class="code"&gt;$ killall -HUP postmaster&lt;/pre&gt;No &lt;b&gt;Windows&lt;/b&gt; eu vou ficar devendo, mas deve ser algo como "recarregar o serviço".&lt;br /&gt;&lt;br /&gt;Pronto! Simples, não?&lt;br /&gt;&lt;p&gt; Se você quiser, pode fazer com que o &lt;b&gt;PostgreSQL&lt;/b&gt; funcione de modo promíscuo, adicionando a seguinte linha:&lt;br /&gt;&lt;/p&gt;&lt;pre style="color: rgb(0, 102, 0);" class="code"&gt;host    all    all        0.0.0.0/0        trust&lt;/pre&gt;Isso faz com que qualquer usuário, de qualquer IP acesse qualquer banco de dados, e sem necessidade de senha!&lt;br /&gt;&lt;p&gt;Se, ao invés de "trust" for usado "reject", todo acesso será fechado.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Lembre-se que, pelo padrão &lt;b&gt;CIDR&lt;/b&gt; de endereçamento, diversos IPs podem ser&lt;br /&gt;configurados com uma só linha! Por exemplo, ambas as linhas abaixo fazem&lt;br /&gt;com que toda a subrede do IP 10.15.22.32/22 tenha acesso, por senha, ao&lt;br /&gt;banco "correios":&lt;br /&gt;&lt;/p&gt;&lt;pre style="color: rgb(0, 102, 0);" class="code"&gt;host    correios    all        10.15.20.0/22        password&lt;br /&gt;host    correios    all        10.15.22.32    255.255.252.0    password&lt;/pre&gt;&lt;p&gt;Uma coisa interessante é restringir o acesso ao usuário "postgres", &lt;i&gt;Senhor de Todo o Cluster&lt;/i&gt;, com a inclusão da seguinte linha:&lt;br /&gt;&lt;/p&gt;&lt;pre style="color: rgb(0, 102, 0);" class="code"&gt;local   all         postgres                          ident sameuser&lt;/pre&gt;Com isso, somente acesso local (via "ssh" e instrução "su - postgres") poderá ser feita com este super usuário, que tem permissão para fazer o que quiser em qualquer banco de dados.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-6300162458509005851?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/6300162458509005851/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/03/meu-postgresql-nao-conecta.html#comment-form' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6300162458509005851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/6300162458509005851'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/03/meu-postgresql-nao-conecta.html' title='Meu PostgreSQL não conecta!'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4377974545905890784</id><published>2009-03-07T18:09:00.000-08:00</published><updated>2009-10-17T13:00:33.541-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='admin'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Setting up Hamachi on Debian GNU/Linux</title><content type='html'>&lt;span style="font-style: italic;"&gt;&lt;br /&gt;"LogMeIn &lt;span style="font-weight: bold;"&gt;Hamachi&lt;/span&gt; [1] is a &lt;span style="font-weight: bold;"&gt;VPN service&lt;/span&gt; that easily sets up in 10 minutes, and enables secure remote access to your business network, anywhere there's an Internet connection."&lt;/span&gt;&lt;p&gt;Hamachi is indeed a great tool for easily setting up VPNs! It creates a virtual network interface and all its configurations are made up with almost no need of user intervention.&lt;/p&gt;&lt;p&gt;For Windows users, a &lt;span style="font-style: italic;"&gt;"Next-Next-Finish"&lt;/span&gt;-like setup executable is provided. Unix/Linux users, however, have no such facilities and should burn some neurons before putting it to work.&lt;/p&gt;&lt;p&gt;In this article I'll show some tips on how to build up the whole scenario on &lt;span style="font-weight: bold;"&gt;Debian GNU/Linux&lt;/span&gt; operating system, including installing Hamachi binaries, setting up required libraries, and deploying automatic initialization scripts.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;First of all, you should download &lt;span style="font-weight: bold;"&gt;Hamachi binaries for Linux&lt;/span&gt; [2]. In the given URL, retrieve the most suitable binary for your processor (i.e. choose between an Intel Pentium or "others"). At the time of writing this very document, the current Hamachi release was 0.9.9.9-20.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YGilJHLjrrI/SbMt7iSNM4I/AAAAAAAAACU/9Za4nX8AhSE/s1600-h/hamachi-1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 209px;" src="http://1.bp.blogspot.com/_YGilJHLjrrI/SbMt7iSNM4I/AAAAAAAAACU/9Za4nX8AhSE/s320/hamachi-1.png" alt="" id="BLOGGER_PHOTO_ID_5310638886438646658" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;For instance, I downloaded &lt;span style="font-weight: bold;"&gt;hamachi-0.9.9.9-20-lnx.tar.gz&lt;/span&gt; as my CPU was an AMD Sempron. I'll use this file name as the example from now on. Save the file on a proper Linux directory, say &lt;span style="font-weight: bold;"&gt;/usr/src&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Then, get into that destiny directory and extract all the zipped file contents using the following commands:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;$ cd /usr/src&lt;br /&gt;$ tar xvzf hamachi-0.9.9.9-20-lnx.tar.gz&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: italic;"&gt;Convention: Please observe that in the given notation the prefix "$" means a normal user prompt is needed, whereas a "#" prefix needs a root or superuser terminal to input the commands. Also, texts colored in &lt;span style="color: rgb(255, 0, 0);"&gt;red&lt;/span&gt; are user inputs. Its corresponding outputs are styled in &lt;span style="color: rgb(0, 0, 153);"&gt; blue&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You should note there is now a sub-directory called &lt;span style="font-weight: bold;"&gt;hamachi-0.9.9.9-20-lnx&lt;/span&gt;. Get into it and then switch to a super user account (i.e. "root" or any supercow-powered user).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;$ cd hamachi-0.9.9.9-20-lnx&lt;br /&gt;$ su&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Although Hamachi can be set per user, in this case I'll set it up for the entire system, I mean, any user can make use of its networking services, and it will be configured for the "hamachi" account (to be created).&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# make install&lt;/p&gt;&lt;p&gt;You should expect some output like this:&lt;/p&gt;&lt;p style="font-style: italic; color: rgb(0, 0, 153);"&gt;Copying hamachi into /usr/bin ..&lt;br /&gt;Creating hamachi-init symlink ..&lt;br /&gt;Compiling tuncfg ..&lt;br /&gt;Copying tuncfg into /sbin ..&lt;br /&gt;&lt;br /&gt;Hamachi is installed. See README for what to do next.&lt;/p&gt;&lt;p&gt;Perhaps you get stuck into &lt;span style="font-weight: bold;"&gt;dependencies&lt;/span&gt;, like OpenSSH or OpenSSL. If that is the case, install the required packages (e.g. by calling "apt-get install openssl") before proceeding and then try installing hamachi again. A nice try is to use &lt;span style="font-weight: bold;"&gt;ldd&lt;/span&gt; command onto "hamachi" or "tuncfg" binaries in order to have a clue of what file or package needs to be resolved.&lt;/p&gt;&lt;p&gt;Next, run the &lt;span style="font-weight: bold;"&gt;TUN/TAP device driver&lt;/span&gt; [3] configurator:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# ./tuncfg/tuncfg&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This time if nothing comes out everything is alright. :)&lt;/p&gt;&lt;p&gt;The next step consists in generating the user crypto identity:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi-init&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You will see the following output in the terminal:&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Initializing Hamachi configuration (/root/.hamachi).&lt;br /&gt;Please wait ..&lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;  generating 2048-bit RSA keypair .. ok&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;&lt;br /&gt;making /root/.hamachi directory .. ok&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;&lt;br /&gt;saving /root/.hamachi/client.pub .. ok&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;&lt;br /&gt;saving /root/.hamachi/client.pri .. ok&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;&lt;br /&gt;saving /root/.hamachi/state .. ok&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Authentication information has been created.&lt;br /&gt;&lt;br /&gt;Hamachi can now be started with&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;'hamachi start' command and then brought online with 'hamachi login'.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Voilà, all the required security keys (private and public) have just been generated on a hidden directory called &lt;span style="font-weight: bold;"&gt;.hamachi&lt;/span&gt; inside the user's home. Note that it is a highly encrypted &lt;span style="font-weight: bold;"&gt;2048-bit RSA keypair&lt;/span&gt;!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Initialize manually the service by calling the instruction below:&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# hamachi start&lt;/p&gt;&lt;p&gt;This single line should appear:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Starting Hamachi hamachi-lnx-0.9.9.9-20 .. ok&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Next, it is desirable for you to set a Hamachi nick for the current client by typing:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# hamachi set-nick zangaro&lt;/p&gt;&lt;p&gt;In your case, replace "zangaro" by, say, the identification you usually give your computer.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Now you should put the daemon online and create an account by running this command:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi login&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This simple message is expected:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;Logging in ......... ok&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If you have no network yet to join, you will need to create yours by typing:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi create Agajorte&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Replace "Agajorte" by the name you will give your new network. A password will be prompted and then the network will be created.&lt;/p&gt;&lt;p&gt;If you are going to join an existing network, just type:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi join Agajorte&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;Then, to appear to other users, type this command:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi go-online Agajorte&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now, to list other members in the network and their respective status, type:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi list&lt;/span&gt;&lt;/p&gt;&lt;p&gt;By default peers' nicknames are not shown in the listing. In order to enable it, you will need to run this command:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi get-nicks&lt;/span&gt;&lt;/p&gt; &lt;p&gt;If you type "hamachi" without any arguments, the outcome is something like this:&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Hamachi, a zero-config virtual private networking utility, ver 0.9.9.9-20&lt;br /&gt;&lt;br /&gt;version  : hamachi-lnx-0.9.9.9-20&lt;br /&gt;pid      : 5063&lt;br /&gt;status   : logged in&lt;br /&gt;nickname : zangaro&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Also, you could have Hamachi usage tips shown by running this command:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi help&lt;/span&gt;  &lt;/p&gt;&lt;p&gt;If you successfully came so far, congratulations! We're half way to conclude the process...&lt;/p&gt;&lt;p&gt;You will now need to stop the daemon. Run this command:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# hamachi stop&lt;/span&gt;  &lt;/p&gt;&lt;p&gt;As every secondary service in the UNIX world, Hamachi daemon could not be initialized using the superuser root account for security reasons. A so-called system user for this service will be created for Hamachi administration tasks. Type the following instruction to add an user called &lt;span style="font-weight: bold;"&gt;"hamachi"&lt;/span&gt; to /etc/passwd.&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# adduser --system --disabled-password --no-create-home hamachi&lt;/p&gt;&lt;p style="color: rgb(0, 0, 153); font-style: italic;"&gt; Adding system user `hamachi' (UID 108) ...&lt;br /&gt;Adding new user `hamachi' (UID 108) with group `nogroup' ...&lt;br /&gt;Not creating home directory `/home/hamachi'.&lt;br /&gt;zangaro:/home/rodrigo# id hamachi&lt;br /&gt;uid=108(hamachi) gid=65534(nogroup) grupos=65534(nogroup)&lt;/p&gt;&lt;p&gt;Note that this user has no home directory. He won't need it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Then, move the Hamachi first initialized configuration directory to /etc/hamachi. In order to let the superuser to still execute Hamachi operations, a symbolic link will be created. Finally, change /etc/hamachi directory and respective ownership to the newly added "hamachi" account. Here are the referenced commands:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# mv /root/.hamachi /etc/hamachi&lt;/span&gt;&lt;br /&gt;# ln -s &lt;span style="color: rgb(255, 0, 0);"&gt;/etc/hamachi &lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;/root/.hamachi&lt;/span&gt;&lt;br /&gt;# chown hamachi.hamachi /etc/hamachi/ -R&lt;br /&gt;&lt;/p&gt; &lt;p&gt;The next step is to develop a &lt;span style="font-weight: bold;"&gt;Shell Script to start and stop Hamachi daemon&lt;/span&gt;. Run this command:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# vi /etc/init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Then type the instructions below:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;#&lt;br /&gt;# hamachi       This shell script takes care of starting and stopping hamachi.&lt;br /&gt;# author: Rodrigo HJORT (http://agajorte.blogspot.com)&lt;br /&gt;#&lt;br /&gt;# chkconfig: 345 99 9&lt;br /&gt;# description: hamachi is a zero-configuration VPN&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;PATH=/sbin:/bin:/usr/bin&lt;br /&gt;&lt;br /&gt;HAMUSR=hamachi&lt;br /&gt;HAMDIR=/etc/hamachi&lt;br /&gt;HAMBIN=/usr/bin/hamachi&lt;br /&gt;&lt;br /&gt;. /lib/lsb/init-functions&lt;br /&gt;&lt;br /&gt;[ -f $HAMDIR/client.pri ] || exit 2&lt;br /&gt;[ -f $HAMDIR/client.pub ] || exit 3&lt;br /&gt;&lt;br /&gt;[ -f $HAMBIN ] || exit 4&lt;br /&gt;&lt;br /&gt;do_start () {&lt;br /&gt;        echo "Starting hamachi..."&lt;br /&gt;        /sbin/tuncfg&lt;br /&gt;        call_daemon start&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;do_status () {&lt;br /&gt;        call_daemon&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;do_stop () {&lt;br /&gt;        echo "Stopping hamachi..."&lt;br /&gt;        killall tuncfg&lt;br /&gt;        call_daemon stop&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;call_daemon () {&lt;br /&gt;        su $HAMUSR -c "$HAMBIN -c $HAMDIR $1"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;  start)&lt;br /&gt;        do_start&lt;br /&gt;        ;;&lt;br /&gt;  stop)&lt;br /&gt;        do_stop&lt;br /&gt;        ;;&lt;br /&gt;  restart)&lt;br /&gt;        do_stop&lt;br /&gt;        sleep 1&lt;br /&gt;        do_start&lt;br /&gt;        ;;&lt;br /&gt;  status)&lt;br /&gt;        do_status&lt;br /&gt;        ;;&lt;br /&gt;  *)&lt;br /&gt;        echo "Usage: hamachi {start|stop|restart|status}" &gt;&amp;2&lt;br /&gt;        exit 1&lt;br /&gt;        ;;&lt;br /&gt;esac&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Give proper execution permissions to the script file by running the following command:&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;# chmod +x /etc/init.d/hamachi&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now you could perform a simple test by calling:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# /etc/init.d/hamachi&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: italic; color: rgb(0, 0, 153);"&gt;Usage: hamachi {start|stop|restart|status}&lt;/p&gt;&lt;p&gt;Then start the daemon:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# /etc/init.d/hamachi start&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: italic; color: rgb(0, 0, 153);"&gt;Starting hamachi...&lt;br /&gt;Starting Hamachi hamachi-lnx-0.9.9.9-20 .. ok&lt;/p&gt;&lt;p&gt;And then retrieve the service status:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# /etc/init.d/hamachi status&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: italic; color: rgb(0, 0, 153);"&gt;Hamachi, a zero-config virtual private networking utility, ver 0.9.9.9-20&lt;br /&gt;&lt;br /&gt;version  : hamachi-lnx-0.9.9.9-20&lt;br /&gt;pid      : 4997&lt;br /&gt;status   : logged in&lt;br /&gt;nickname : zangaro-lin&lt;/p&gt;&lt;p&gt;The most important fact to observe now is that &lt;span style="font-weight: bold;"&gt;Hamachi service is no longer bound to "root"&lt;/span&gt; superuser, but to its proper account: the "hamachi" system user.&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# ps aux | grep ^hamachi&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: italic; color: rgb(0, 0, 153);"&gt;hamachi   5063  0.1  0.0   3104   804 ?        S    01:42   0:00 /usr/bin/hamachi -c /etc/hamachi start&lt;/p&gt;&lt;p&gt;You could also restart the service by invoking this command:&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(255, 0, 0);"&gt;# /etc/init.d/hamachi restart&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Stopping hamachi...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Shutting down .. ok&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Starting hamachi...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Starting Hamachi hamachi-lnx-0.9.9.9-20 .. ok&lt;/span&gt;&lt;/p&gt;&lt;p&gt;At last, you could stop the service by calling this:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# /etc/init.d/hamachi stop&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Stopping hamachi...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;Shutting down .. ok&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Hold on, there is only one detail left to do!&lt;/p&gt;&lt;p&gt;It will be very interesting to have the service &lt;span style="font-weight: bold;"&gt;initialized automatically as the system starts&lt;/span&gt;, i.e. on Linux boot time. This is a responsibility for System-V, but usually its configuration is distribution-dependent. You should check out your Linux distro on how to do it.&lt;/p&gt;&lt;p&gt;As Debian environment was chosen for the tests, System-V style init script links were installed through &lt;span style="font-weight: bold;"&gt;update-rc.d&lt;/span&gt; command, as shown below:&lt;br /&gt;&lt;/p&gt;&lt;p style="color: rgb(255, 0, 0);"&gt;# update-rc.d hamachi defaults 09 99&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt; Adding system startup for /etc/init.d/hamachi ...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc0.d/K99hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc1.d/K99hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc6.d/K99hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc2.d/S09hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc3.d/S09hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc4.d/S09hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-style: italic;"&gt;   /etc/rc5.d/S09hamachi -&gt; ../init.d/hamachi&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Well, unless you care about your uptime or if you are sure about the configuration you made on Sytem-V, you might reboot your Linux to find out whether the entire effort was worthy. Bon courage !&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Even if you have another kind of Linux, I hope most of information detailed in the present document are valuable for you. Please don't hesitate in scratching up some comments. :D&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold;"&gt;References:&lt;/p&gt;&lt;p&gt;[1] Hamachi Official Site, https://secure.logmein.com/products/hamachi/vpn.asp&lt;br /&gt;[2] Hamachi for Linux Binaries, http://files.hamachi.cc/linux/&lt;br /&gt;[3] TUN/TAP device driver, http://hamachi.cc/tuntap&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4377974545905890784?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4377974545905890784/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/03/setting-up-hamachi-on-debian-gnulinux.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4377974545905890784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4377974545905890784'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/03/setting-up-hamachi-on-debian-gnulinux.html' title='Setting up Hamachi on Debian GNU/Linux'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YGilJHLjrrI/SbMt7iSNM4I/AAAAAAAAACU/9Za4nX8AhSE/s72-c/hamachi-1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-3247099182949692000</id><published>2009-02-24T18:42:00.000-08:00</published><updated>2009-08-04T11:37:07.308-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='backup'/><category scheme='http://www.blogger.com/atom/ns#' term='msdos'/><title type='text'>Laço FOR em Backup no MS-DOS</title><content type='html'>&lt;br/&gt;&lt;br /&gt;Após um bom tempo acostumado com Shell Script, ter que automatizar processos no Windows (inevitavelmente fazendo uso do MS-DOS...) parece um tanto traumatizante.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Felizmente esse tão esquecido prompt de comando tem sua pseudo linguagem de controle!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fiz um script de lote, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;backup-workspace.bat&lt;/span&gt;, para realizar o backup de determinados diretórios de trabalho do Eclipse:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;@echo off&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;set ZIP=C:\Arquiv~1\7-Zip\7z.exe&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;set WKS=%1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;echo Backing up workspace %WKS%...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 102);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;%ZIP% a -r -x@backup-ignore-list.txt -mx=9 %WKS%.zip %WKS%&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A tarefa dele é através do &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;7-ZIP&lt;/span&gt; [1] fazer o backup dos arquivos contidos no diretório especificado como argumento no script. Um arquivo com a extensão ZIP e mesmo nome do diretório será criado.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Os padrões especificados neste arquivo de texto, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;backup-ignore-list.txt&lt;/span&gt;, farão com que determinados arquivos e diretórios sejam ignorados:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;bin&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;Thumbs.db&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;*.log&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;*.class&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;org.eclipse.core.resources\.history&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;org.eclipse.jdt.core&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;org.eclipse.epp.usagedata.recording&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;org.eclipse.wst.server.core\tmp0&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;A última etapa, a criação de um único script para executar os diversos diretórios desejados, precisava ser feita. O novo script, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;backup-all.bat&lt;/span&gt;, poderia ter o seguinte conteúdo:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;@echo off&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;backup-workspace ApressEJB3&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;backup-workspace Concorde&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;backup-workspace HiberStruts&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;backup-workspace PacktEJB3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Achei esse código meio feio, então resolvi dar uma investigada em como deixá-lo menos lusitano...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E eis que encontro o famigerado &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;laço FOR no MS-DOS&lt;/span&gt; [2]...!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src="http://2.bp.blogspot.com/_YGilJHLjrrI/SaS2fFPPxMI/AAAAAAAAACE/39-fiLnpeAU/s320/for-msdos.PNG" style="cursor:pointer; cursor:hand;width: 320px; height: 185px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5306566906047612098" /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Agora sim, com umas leves modificações o script ficou assim:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;@echo off&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=""&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;set WKS=ApressEJB3, Concorde, HiberStruts, PacktEJB3&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 51, 51);"&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;for %%w in (%WKS%) do backup-workspace %%w&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;É, aparentemente ele fez tudo certinho após a execução..!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YGilJHLjrrI/SaS5GX4G-iI/AAAAAAAAACM/7Dp3Lnx0VmY/s1600-h/script-backup.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 154px;" src="http://2.bp.blogspot.com/_YGilJHLjrrI/SaS5GX4G-iI/AAAAAAAAACM/7Dp3Lnx0VmY/s320/script-backup.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5306569780088994338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Referências:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[1] &lt;a href="http://www.7-zip.org/"&gt;http://www.7-zip.org/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[2] &lt;a href="http://home.att.net/~gobruen/progs/dos_batch/dos_batch.html"&gt;http://home.att.net/~gobruen/progs/dos_batch/dos_batch.html&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-3247099182949692000?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/3247099182949692000/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/02/laco-for-em-backup-no-ms-dos.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3247099182949692000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/3247099182949692000'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/02/laco-for-em-backup-no-ms-dos.html' title='Laço FOR em Backup no MS-DOS'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YGilJHLjrrI/SaS2fFPPxMI/AAAAAAAAACE/39-fiLnpeAU/s72-c/for-msdos.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-698828617844172668</id><published>2009-02-21T17:52:00.000-08:00</published><updated>2009-02-22T13:54:42.683-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sqlmagazine'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Artigo na SQL Magazine: "Otimizações com índices reversos"</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_YGilJHLjrrI/SaHJUwWtu4I/AAAAAAAAAB8/9DtUsVPplbk/s1600-h/capaSQL61_M.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 125px; height: 170px;" src="http://4.bp.blogspot.com/_YGilJHLjrrI/SaHJUwWtu4I/AAAAAAAAAB8/9DtUsVPplbk/s320/capaSQL61_M.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5305743194433895298" /&gt;&lt;/a&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;"Otimizações com índices reversos"&lt;/span&gt;, este é o título do artigo que escrevi para a revista &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;SQL Magazine&lt;/span&gt; que saiu este mês [1].&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nele descrevo o uso de índices reversos como instrumento para se otimizar consultas SQL em bancos de dados relacionais. No estudo em questão utilizo o SGBD PostgreSQL, comparando o desempenho entre as diversas linguagens procedurais disponíveis na criação de uma função do tipo &lt;span class="Apple-style-span" style="font-style: italic;"&gt;reverse()&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[1] &lt;a href="http://www.devmedia.com.br/resumo/default.asp?ed=61&amp;amp;site=2" target="nova"&gt;http://www.devmedia.com.br/resumo/default.asp?ed=61&amp;amp;site=2&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-698828617844172668?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/698828617844172668/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/02/artigo-na-sql-magazine-otimizacoes-com.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/698828617844172668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/698828617844172668'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/02/artigo-na-sql-magazine-otimizacoes-com.html' title='Artigo na SQL Magazine: &quot;Otimizações com índices reversos&quot;'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YGilJHLjrrI/SaHJUwWtu4I/AAAAAAAAAB8/9DtUsVPplbk/s72-c/capaSQL61_M.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-8794355243479156727</id><published>2009-02-21T17:43:00.000-08:00</published><updated>2009-02-21T17:48:12.732-08:00</updated><title type='text'>Le début...</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Voilà, j'ai lancé mon blog enfin !&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Cette fois, un enregistrement en français...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-8794355243479156727?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/8794355243479156727/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/02/le-debut.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8794355243479156727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/8794355243479156727'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/02/le-debut.html' title='Le début...'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-578610887231886448.post-4449737467894629840</id><published>2009-02-21T14:16:00.000-08:00</published><updated>2009-02-22T08:43:26.255-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='j2ee'/><category scheme='http://www.blogger.com/atom/ns#' term='glassfish'/><title type='text'>EJB 3 Developer Guide: Errata on Web Security Sample</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I was just working on the lab 4 / chapter 12 of this book [1] and then I got stuck into an issue...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The environment used on the tests was &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;GlassFish Application Server v2&lt;/span&gt; and the sample code concerns &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Web Container Security&lt;/span&gt;. It just didn't work as expected...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;"&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;lab4:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;to run program enter  &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;http://localhost:8080/BankService/index.html&lt;/span&gt; in browser.  http://localhost:8080 is url for web applications as shown by Glassfish on startup. If Glassfish provides port other than 8080 then modify url accordingly.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;then enter scott/xyz username/password in login form.  servlet menu for adding customer to database is then displayed.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;enter ramon/abc username/password in login form.   error page is then displayed."&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The problem is that the page was never displayed despite using the proper user (i.e. "scott") because security always failed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After googling for a while, I could realize some missing points in the book packaged sample [2].&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yet I made some small modifications in order to test the application with both users: "scott" (belonging to "bankemployee" group) and "ramon" (belonging to "bankcustomer" group).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, the idea behind it was to forbid access to a specific servlet ("/addCustomer" address) whenever the user did not belong to "bankemployee" role. Also, to restrict access to "/findCustomer" servlet to both roles.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First of all, I modified the WEB descriptor file, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;"WEB-INF/web.xml"&lt;/span&gt;, by adding "/findCustomer" servlet mapping, specifying "/addCustomer" URL pattern in the security constraint and an optional welcome file. Here's the entire code:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xsi:schemaLocation="http://java.sun.com/xml/ns/javaee&lt;br /&gt;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-name&amp;gt;AddCustomerServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-class&amp;gt;ch12lab4.AddCustomerServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-name&amp;gt;FindCustomerServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-class&amp;gt;ch12lab4.FindCustomerServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-name&amp;gt;AddCustomerServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/addCustomer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;servlet-name&amp;gt;FindCustomerServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/findCustomer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;security-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;web-resource-collection&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;web-resource-name&amp;gt;bank service most restricted&amp;lt;/web-resource-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/addCustomer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/addCustomer.html&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/web-resource-collection&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;auth-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;role-name&amp;gt;bankemployee&amp;lt;/role-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/auth-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/security-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;security-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;web-resource-collection&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;web-resource-name&amp;gt;bank service restricted&amp;lt;/web-resource-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/findCustomer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;url-pattern&amp;gt;/findCustomer.html&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/web-resource-collection&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;auth-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;role-name&amp;gt;bankcustomer&amp;lt;/role-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;role-name&amp;gt;bankemployee&amp;lt;/role-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/auth-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/security-constraint&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;security-role&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;role-name&amp;gt;bankemployee&amp;lt;/role-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/security-role&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;login-config&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;auth-method&amp;gt;BASIC&amp;lt;/auth-method&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;realm-name&amp;gt;file&amp;lt;/realm-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/login-config&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;welcome-file-list&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;welcome-file&amp;gt;index.html&amp;lt;/welcome-file&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 51, 153);"&gt;&amp;lt;/welcome-file-list&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;The second detail was the creation of a Sun's specific descriptor, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;"WEB-INF/sun-web.xml"&lt;/span&gt;, which did not exist in the sample code. The key point here was to map existing groups already specified in the application server's realm file into roles used inside the WEB application. In the current case they share the same names, "bankcustomer" and "bankemployee", on both environments. Here's the new file:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;!DOCTYPE sun-web-app PUBLIC&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;   "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN"&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;"http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd"&amp;gt;&lt;br /&gt;&amp;lt;sun-web-app&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;context-root&amp;gt;/BankService&amp;lt;/context-root&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;security-role-mapping&amp;gt;&lt;br /&gt;  &lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt; &amp;lt;role-name&amp;gt;bankcustomer&amp;lt;/role-name&amp;gt;&lt;br /&gt;  &lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt; &amp;lt;group-name&amp;gt;bankcustomer&amp;lt;/group-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;/security-role-mapping&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;security-role-mapping&amp;gt;&lt;br /&gt;  &lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt; &amp;lt;role-name&amp;gt;bankemployee&amp;lt;/role-name&amp;gt;&lt;br /&gt;  &lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt; &amp;lt;group-name&amp;gt;bankemployee&amp;lt;/group-name&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 153, 153);"&gt;&amp;lt;/security-role-mapping&amp;gt;&lt;br /&gt;&amp;lt;/sun-web-app&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;That's it, it worked at last and I ran the whole book sample codes!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I'm gonna take a rest watching "The Hunt for the Red October", which had just finished on the eMule's queue...! :D&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;References:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[1] Michael Sikora, "EJB 3 Developer Guide", &lt;a href="http://www.packtpub.com/developer-guide-for-ejb3/book" target="nova"&gt;http://www.packtpub.com/developer-guide-for-ejb3/book&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[2] Code Download, &lt;a href="http://www.packtpub.com/support/book/developer-guide-for-ejb3" target="nova"&gt;http://www.packtpub.com/support/book/developer-guide-for-ejb3&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/578610887231886448-4449737467894629840?l=www.hjort.co' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hjort.co/feeds/4449737467894629840/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.hjort.co/2009/02/ejb-3-developer-guide-errata-on-web.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4449737467894629840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/578610887231886448/posts/default/4449737467894629840'/><link rel='alternate' type='text/html' href='http://www.hjort.co/2009/02/ejb-3-developer-guide-errata-on-web.html' title='EJB 3 Developer Guide: Errata on Web Security Sample'/><author><name>Rodrigo HJORT</name><uri>http://www.blogger.com/profile/01765383138213631207</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-ng5fiab9D4s/TmoTMqInEbI/AAAAAAAAAYw/OE_n5hrGyg4/s220/P1080348-linkedin192.JPG'/></author><thr:total>0</thr:total></entry></feed>
