Monday, July 4, 2011


Dropbox monitoring problem

Briefly, if you see a system notification like this one:


Please run "echo 100000 | sudo tee /proc/sys/fs/inotify/max_user_watches" and restart Dropbox to correct the problem.

Do as following:

foogaro@foobian:˜$ sudo vi /etc/sysctl.conf

and insert the following line at the bottom

fs.inotify.max_user_watches = 100000

save and exit (:wq)
and reboot the system and launch Dropbox again.

Enjoy it!

Ciao, Foogaro

Friday, June 17, 2011


Debian 6 Squeeze and GNOME 3

I tryed the GNOME 3 Live CD and I have to say that it looks realy nice!

I thought, I must have it on my laptop on my Debian!

Do not start without making a backup of all your data! It is a must, you never know what it could happen! ;)

Just replace all the "squeeze" and "stable" words in your /etc/apt/source.list with "wheey", add some experimental repository and you are ready to start installing GNOME 3! Yeahhh...
$ sudo aptitude -t experimental install gnome3-session
Just say "Yes" to all dependencies download/remove/upgrade advice/suggestion!

Fill your moka with coffee and water, turn on the cooker and then get a coffee.
If you like you can add some milk belong with some cookies!

Once your done with the coffee and your system is totaly compromised (I didn't say fucked up), grab your Debian 6 CD/DVD, put it in your optical drive and enjoy Debian 6 with a wonderfull GNOME 2.32!

Remember why you chose Debian, stability over all, otherwise you would have chosen Ubuntu!

I'm very sorry Debian for being such a maroon!

Ciao,
Foogaro.

Wednesday, May 18, 2011


Dropbox on Debian Squeeze

Briefly:
"Error: Dependency is not satisfiable: libnautilus-extension1 (>= 1:2.22.2)"

What to do?
$ mkdir -p extract/DEBIAN
$ dpkg-deb -x nautilus-dropbox_0.6.7_amd64.deb extract/
$ dpkg-deb -e nautilus-dropbox_0.6.7_amd64.deb extract/DEBIAN/
$ vi extract/DEBIAN/control


change "libnautilus-extension1 (>= 1:2-22-2)" to "libnautilus-extension1 (>= 2-22-2)"

save and exit (:wq)


$ mkdir build
$ dpkg-deb -b extract/ build/
$ sudo dpkg -i build/nautilus-dropbox_0.6.7_amd64.deb


Enjoy it!

Ciao, Foogaro

Sunday, May 1, 2011


NoJSF

NoJSF, it is a basic project which aims to be the base for projects that do NOT want to use any obtrusive frontend frameworks like JSF.
This variant of the project is based on the IoC pattern provided by Spring.
The project uses RESTeasy for the REST layer and Spring 3 to provide injection between layers.
So, if all you want is just html, js, css and a restful backend... you found what you were looking for.

This is how it works:
  • the user acts on the client sending an ajax request;
  • the REST controller (aka restler) intercepts the request and delegates it to the business layer;
  • the effective business component does the hard work and, if necessary, asks the persistence layer to query or persist entities/documents;
  • the persistence component goes directly to the database through the appropriate and provided driver.
Layers chain terminates with a HTTP code, hopefully a 200 or 201 code! ;)

You can download it from github.

Let's look inside of it.

The Client side
Two things that probably I didn't tell you: one is that I am a fan of Single Page Website (also SPW) approach, second I'm not good with design, graphics and all.
Ok, now we can start.
First of all you will need an "index.html" as your root for your site; in this HTML file you will declare all your main resources such as JavaScript files, style sheet files and all the other things you might need.

Anyway here is my "index.html":
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>NoJSF - foogaro.com</title>
    </head>
    <body>
        <div id="header">
            <div id="menu">
                <ul>
                    <li><a href="#home">Home</a></li>
                    <li><a href="#users">Users</a></li>
                </ul>
            </div>
        </div>
       
        <div id="content">
        </div>
       
        <div id="footer">
        </div>
    </body>
    <link type="text/css" href="css/ui-lightness/jquery-ui-1.8.9.custom.css" rel="stylesheet" />
    <script type="text/javascript" src="js/jquery-1.5.min.js"></script>
    <script type="text/javascript" src="js/jquery-ui-1.8.9.custom.min.js"></script>
    <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
    <script type="text/javascript" src="js/nojsf.js"></script>
    <script type="text/javascript">
       
        $(document).ready(function () {
            f_handleMenu();
        });
        function f_handleMenu() {
            $("a[href=#home]").click(function () {
                $("#content").empty();
                return false;
            });
            $("a[href=#users]").click(function () {
                f_loadReource("fragment/user/main.html", "js/user/main.js", $("#content"), "f_user");
                return false;
            });
        }
    </script>
</html>
There is not much to explain in the above code except for one thing: the "href".

As you have noticed I valued user anchor "href" attibute with "#user", while I could have used "#" and setted the "id" attribute and handle the element by id, but.... as we are making a SPW we want our site to be indexed by search engines. Doing so the crawler wont skip our anchors from semantic analyses giving the page a better score (in this case the word "user" wont help us much).

In the javascript code we are loading two files: "fragment/user/main.html" and "js/user/main.js".
These two files are needed to update the DOM and include a JavaScript source respectively.

main.html
<div id="mainUsers">
    <h2>Show users</h2>
    <img src="images/icons/group.png" alt="Show users" title="Show users" id="imgShowUsers" />
    <img src="images/icons/user_add.png" alt="Add user" title="Add user" id="imgAddUser" />
    <div>
        <table >
            <thead>
                <tr>
                    <th>First name</th>
                    <th>Last name</th>
                </tr>
            </thead>
            <tbody id="tblUsers" ></tbody>
            <tfoot />
        </table>
    </div>
</div>

main.js
function f_user() {
    f_handleImgAddUser();
    f_showList();
}

function f_handleImgAddUser() {
    $("#imgAddUser").click(function () {
        f_addUser();
    });
}

function f_showList() {
    $("#tblUsers tbody").empty();
    $.ajax({
        url:"rest/users",
        type: "GET",
        dataType: "json",
        success: function (backData, status, xhr) {
            f_loadUserListTpl(backData.response.userDTO);
        },
        error: function (xhr, status, ex) {
        },
        complete: function (xhr, status) {
        }
    });
}

function f_loadUserListTpl(dataList) {
    $.ajax({
        url: '/web/template/user/userList.tpl',
        data: '',
        dataType: 'text',
        success: function (templateText) {
            $.tmpl(templateText, dataList).appendTo("#tblUsers");
        }
    });
}

function f_addUser() {
    $("#userDialog").remove();
    $("#mainUsers").append("<div id=\"userDialog\"></div>");
    $("#userDialog").dialog({
        bgiframe: true,
        autoOpen: false,
        height: 200,
        width: 550,
        modal: true,
        resizable: false,
        draggable: true,
        closeOnEscape: true,
        title: "Add new user",
        zIndex: 2000,
        close: function() {
            $("#userDialog").remove();
        }
    });
    $("#userDialog").load("/web/fragment/user/edit.html");
    $("#userDialog").dialog("open");
}

function f_saveUser() {
    $.ajax({
        url: "/web/rest/users/user",
        type: "POST",
        dataType: "json",
        contentType: 'application/x-www-form-urlencoded; charset=iso-8859-1;',
        data: $("#userForm").serialize(),
        success: function (backData, status, xhr) {
            $("#userDialog").dialog("close");
            f_showUsers();
        },
        error: function (xhr, status, ex) {
        },
        complete: function (xhr, status) {
        }
    });
}

function f_viewUser(userId) {
    $("#userDialog").remove();
    $("#mainUsers").append("<div id=\"userDialog\"></div>");
    $("#userDialog").dialog({
        bgiframe: true,
        autoOpen: false,
        height: 200,
        width: 550,
        modal: true,
        resizable: false,
        draggable: true,
        closeOnEscape: true,
        title: "User information",
        zIndex: 2000,
        close: function() {
            $("#userDialog").remove();
        }
    });
    $.ajax({
        url:"/web/rest/users/" + userId,
        type: "GET",
        success: function (backData, status, xhr) {
            $("#userDialog").load("/web/template/user/view.tpl", function(template) {
                $.tmpl(template, backData).appendTo(this);
            });
        },
        error: function (xhr, status, ex) {
        },
        complete: function (xhr, status) {
        }
    });
    $("#userDialog").dialog("open");
}

function f_updateUser() {
    $.ajax({
        url: "/web/rest/users/user",
        type: "PUT",
        dataType: "json",
        contentType: 'application/x-www-form-urlencoded; charset=iso-8859-1;',
        data: $("#userForm").serialize(),
        success: function (backData, status, xhr) {
            $("#userDialog").dialog("close");
            f_showUsers();
        },
        error: function (xhr, status, ex) {
        },
        complete: function (xhr, status) {
        }
    });
}

function f_deleteUser(userId) {
    $.ajax({
        url: "/web/rest/users/" + userId,
        type: "DELETE",
        dataType: "json",
        contentType: 'application/x-www-form-urlencoded; charset=iso-8859-1;',
        success: function (backData, status, xhr) {
        },
        error: function (xhr, status, ex) {
        },
        complete: function (xhr, status) {
            f_showUsers();
        }
    });
}

The interesting part here is in these two methods: "f_showList()" and "f_loadUserListTpl(dataList)".

The first one is responsible to call the rest service to get the user list from the backend and then giving it to the second method.
The latter is doing probably something new for some people: it is loading an external resource "/web/template/user/userList.tpl" which is actually a HTML template, as follow:

<tr>
    <td>${firstName}</td>
    <td>${lastName}</td>
    <td>
        <img id="${identifier}" class="userViewIcon" src="images/icons/user_go.png" alt="View" title="View" />
        <img id="${identifier}" class="userEditIcon" src="images/icons/user_edit.png" alt="Edit" title="Edit" />
        <img id="${identifier}" class="userDeleteIcon" src="images/icons/user_delete.png" alt="Delete" title="Delete" />
    </td>
</tr>

Here the jQuery Template engine will loop through the "dataList" which contains the users, evaluating the above expression in the HTML just like JSTL would do. That is nice, isn't it? :D

Without going through all the application (which actually it doesn't go any further :P) what is all about?
First of all an assumption: if you are a programmer, then you like coding, so you like doing things your way, and if you are here is cause you don't want to use the JSF trap anymore.

Now if you download the project from GitHub, compile it and deploy it and... and ... and if you open firebug or the Chrome developer tool, you will notice that most of the resources are cached and what goes back and forth from the server are just JSON requests, which means a lot's of bytes, kilobytes saved... now calculate this for 1 user, 10th users, 100th users... 1000th users.

How much bandwidth will you save?
How much control will you earn?

;)

Ciao,
Foogaro

Wednesday, February 9, 2011


Debian 6.0.0 Squeeze

Finally the awaited release did come out!
Welcome Squeeze!

DV3-4101sl

During installation you will not able to connect to the internet via protected WPA/WPA2 WiFi, the installer only gives you the opportunity to use the WEP one (cannot understand this)!
Anyway a good workaround is to get wired, or just setup your wifi with WEP encryption - even with no password.

The installation goes clear and within 40/45 minutes you should get for your first boot in Debian Squeeze.

As you log in, you will notice that it is not so different from Ubuntu... now you can connect to your WiFi via WPA/WPA2. Now on it is all up to you! ;)


What I needed: Dropbox, JDK6, Skype.

Dropbox

I had to download the source package "nautilus-dropbox-0.6.7.tar.bz2".

foogaro@foobian:˜/Downloads$ bunzip2 nautilus-dropbox-0.6.7.tar.bz2
foogaro@foobian:˜/Downloads$ tar -xvf nautilus-dropbox-0.6.7.tar
foogaro@foobian:˜/Downloads$ cd nautilus-dropbox-0.6.7

Now I need two things:

foogaro@foobian:˜$ sudo aptitude install libnautilus-extension1 libnautilus-extension-dev
foogaro@foobian:˜$ sudo aptitude install python-docutils

Now we can start installing Dropbox:

foogaro@foobian:˜/Downloads/nautilus-dropbox-0.6.7$ ./configure
foogaro@foobian:˜/Downloads/nautilus-dropbox-0.6.7$ make
foogaro@foobian:˜/Downloads/nautilus-dropbox-0.6.7$ sudo make install

Good people would stop nautilus and that restart it... I just logout and login again! :D
Now in your Application/Internet menu you will find Dropbox... click it and enjoy it!
It may take a while to download and initialize itself!


JDK6

Just download the binary somewhere and install it.

foogaro@foobian:˜$ ./jdk-6u23-linux-x64.bin

Than I created a symbolink link: java6

foogaro@foobian:˜$ ln -s jdk1.6.0_23 java6

Then I download the docs and install it.

foogaro@foobian:˜/Downloads$ cp jdk-6u23-docs.zip ../java6/
foogaro@foobian:˜/Downloads$ cd ../java6/
foogaro@foobian:˜/java6$ unzip jdk-6u23-docs.zip

Now it is time to export my java home:

foogaro@foobian:˜$ vi .profile

And insert those two lines:

export JAVA_HOME=/home/foogaro/jdk1.6.0_23

PATH=$JAVA_HOME/bin:$PATH


Skype

First install the 32-bits emulation libraries... it is not due to Debian, it is up to Skype guys!!!

foogaro@foobian:˜$ sudo apt-get install ia32-libs ia32-libs-gtk libasound2-plugins libqt4-core libqt4-guilib32v4l-0

..some more of them...

foogaro@foobian:˜$ wget ftp://ftp.gplhost.com/pub/skype/lib32-gdbm3_1.8.3_amd64.deb
foogaro@foobian:˜$ wget ftp://ftp.gplhost.com/pub/skype/lib32-wrap0_7.6.q_amd64.deb
foogaro@foobian:˜$ sudo dpkg -i lib32-gdbm3_1.8.3_amd64.deb lib32-wrap0_7.6.q_amd64.deb

Then you can download Skype for Lenny and install it on your 64 bits Squeeze system:

foogaro@foobian:˜$ sudo dpkg -i --force-architecture skype-debian_2.1.0.81-1_i386.deb

Running Skype
You can run Skype as usual (with the LD_PRELOAD to have the video working with the lib32v4l-0 package:

foogaro@foobian:˜$ LD_PRELOAD=/usr/lib32/libv4l/v4l1compat.so skype

Done... you will notice some log about "wrong ELF class: ELFCLASS64", which is due to the 32 bit application running on a 64 bit system!

Ciao,
Foogaro

Monday, January 3, 2011


First post, but not useless - Moongo my Java library for NoSQL MongoDB

Hi to all,
I just want to share with all of you, interested, my first post.
My first post is concerning another "my first time"... github!
@ this link https://github.com/foogaro/Moongo you will find my open source project about MongoDB, Moongo!

Creativity and fantasy are not my best (artistically speaking - lol), so what it is all about?

Moongo is a Java library, which aims to be an easy interface to play with MongoDB.
There are two main objects you would use with Moongo:

  1. Moongo
  2. QueryObject

The first one, is the main object which wraps all methods you have/need to use.
The second one, is the object used to create query criteria.

With Moongo you just have to write the code for your pojos and give them to Moongo.
Here is an example:

User user = new User();
user.setFirstName("Luigi");
user.setLastName("Foogaro");
Moongo moongo = new Moongo();
moongo.create(user);

Now you can check into your MongoDB instace for your fresh new document:

>use test;
switched to test
>show collections;
com.foogaro.nosql.moongo.User
system.indexes
>db.com.foogaro.nosql.moongo.User.find();
{ "_id" : ObjectId("4d1b3fc97b060183d154b8fd"), "firstName" : "Luigi", "lastName" : "Foogaro"}
>_

Moongo it supports embedded documents as well, here is another example:

Location location = new Location();
Nation nation = new Nation();
City city = new City();
city.setCode("RM");
city.setName("Rome");
nation.setCode("IT");
nation.setName("Italy");
nation.setCity(city);
location.setNation(nation);
moongo.create(location);

Now if you look into your MongoDB instance you will find:

>db.com.foogaro.nosql.moongo.Location.find();
{ "_id" : ObjectId("4d1b3fc97b060183d154c099"), "nation" : { "code" : "IT", "name" : "Italy", "city" : { "code" : "RM", "name" : "Rome" } } }
>_

When creating new documents, only the root document gets an ObjectId, unless... keep reading :)

Thinking about redundancy?
Moongo supports DBRef, just annotate your embedded documents with @DBReferenced and you are done!
From the previous example:

public class Location {
    @DBReferenced Nation nation;
}

Looking back again into your MongoDB instance you should have two more collections with their first new document:

>show collections;
com.foogaro.nosql.moongo.User
com.foogaro.nosql.moongo.Location
com.foogaro.nosql.moongo.Nation
system.indexes
>db.com.foogaro.nosql.moongo.Location.find();
{ "_id" : ObjectId("4d1b3fc97b060183d154c100"), "nation" : { "$ref" : "com.foogaro.nosql.moongo.Nation", "$id" : "4d1b3fc97b060183d154c101" } } >db.com.foogaro.nosql.moongo.Nation.find();
{ "_id" : ObjectId("4d1b3fc97b060183d154c101"), "code" : "IT", "name" : "Italy", "city" : { "code" : "RM", "name" : "Rome" } }
>_

Obviously if you would have annotated City inside Nation, you would have got the Nation collection document without the City embedded document, just its reference, and the City collection with its document as well.

Moongo will take care of all mapping to/from database. So retrieving the Location document with id "4d1b3fc97b060183d154c100" from MongoDB, you will get back a Location pojo as well as with its Nation property populated with its City property populated.

Location location = new Location();
location.set_id(new ObjectId("4d1b3fc97b060183d154c100"));
Location persistedLocation = (Location)moongo.read(location);

You might want to wrap the call to your Moongo to avoid casting everytime.

That's all for now,
stay tuned for upcoming releases and tips.

Ciao,
Foogaro