Monday, June 25, 2012

let me introduce you project Lombok

Problem: Have you ever been in a situation, when you tough that creating all those boring equals(), hashCode(), toString() methods is quite time consuming and maintaining these is error prone?
SolutionIf so, read on :) Project Lombok might be the answer.

Yesterday, while searching for some solution on this (with having in mind the tutorial of spring roo I've read quite some time ago where these could be handled by AOP using annotations) I've found as a possible solution project Lombok:
http://projectlombok.org

Lombok demo and features list
I really like their demo video, if you want an introduction to this project, make sure you watch it:
http://projectlombok.org/
And there is also quite nice feature list available: 
http://projectlombok.org/features/index.html

Encouragement
OK, so what's next? Am I brave enough to go for it? While doubing it I've found out I'm not the only one:
http://stackoverflow.com/questions/3852091/is-it-safe-to-use-project-lombok

That gave me some encouragement. So let's go and try it.

I have some small open source project, so let me show you my code prio and after the change to give you an overview (or rather motivation :)).

Code snippets comparison
See:
  • eclipse generated methods:
    // eclipse generated methods way
    public class Schedule implements Serializable {
    
    ...
    
     @Override
     public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((bgImage == null) ? 0 : bgImage.hashCode());
      result = prime * result + (blank ? 1231 : 1237);
      result = prime * result + (clear ? 1231 : 1237);
      result = prime * result + (live ? 1231 : 1237);
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      result = prime * result
        + ((presentations == null) ? 0 : presentations.hashCode());
      return result;
     }
    
     @Override
     public boolean equals(Object obj) {
      if (this == obj)
       return true;
      if (obj == null)
       return false;
      if (getClass() != obj.getClass())
       return false;
      Schedule other = (Schedule) obj;
      if (bgImage == null) {
       if (other.bgImage != null)
        return false;
      } else if (!bgImage.equals(other.bgImage))
       return false;
      if (blank != other.blank)
       return false;
      if (clear != other.clear)
       return false;
      if (live != other.live)
       return false;
      if (name == null) {
       if (other.name != null)
        return false;
      } else if (!name.equals(other.name))
       return false;
      if (presentations == null) {
       if (other.presentations != null)
        return false;
      } else if (!presentations.equals(other.presentations))
       return false;
      return true;
     }
    
     @Override
     public String toString() {
      return "Schedule [presentations=" + presentations + ", bgImage="
        + bgImage + ", name=" + name + ", blank=" + blank + ", clear="
        + clear + ", live=" + live + "]";
     }
    
    }
    
  • Lombok way:
    // lombok way
    @ToString
    @EqualsAndHashCode
    public class Schedule implements Serializable {
    
    ...
    
    }
    
  • manually written ones with Equals/ToString/HashCode Builders:
    // manual way using Equals/ToString/HashCode Builders
    public class Schedule implements Serializable {
    
    ...
    
     @Override
     public int hashCode() {
      return new HashCodeBuilder()
      .append(this.getPresentations())
      .append(this.getBgImage())
      .append(this.getName())
      .append(this.isBlank())
      .append(this.isClear())
      .append(this.isLive())
      .toHashCode();
     }
    
     @Override
     public boolean equals(Object obj) {
      if ( !(obj instanceof Schedule) ) return false;
      Schedule castOther = (Schedule) obj;
      return new EqualsBuilder()
       .append(this.getPresentations(), castOther.getPresentations())
       .append(this.getBgImage(), castOther.getBgImage())
       .append(this.getName(), castOther.getName())
       .append(this.isBlank(), castOther.isBlank())
       .append(this.isClear(), castOther.isClear())
       .append(this.isLive(), castOther.isLive())
       .isEquals();
     }
    
     @Override
     public String toString() {
      return new ToStringBuilder(this)
      .append("\n presentations", this.getPresentations())
      .append("\n bgImage", this.getBgImage())
      .append("\n name", this.getName())
      .append("\n blank", this.isBlank())
      .append("\n clear", this.isClear())
      .append("\n live", this.isLive())
      .append("\n")
      .toString();
     }
    
    }
    
So as obvious from the samples, instead of writing/maintaining the code you can rather just annotate. (Btw. if there were no lombok way, I'd go for Builders way => manual writing + maintaining).

Integration
The great thing is that there is a simple integration with maven (that is the build tool of my choice). See instructions:
http://projectlombok.org/mavenrepo/index.html
Moreover integration with Eclipse seems really straitforward too (all the autocompletition as well as Outline view work as expected or rather unexpectedly well).

Some more motivation
To encourage lazy developers (like me) even more, there are things available for:
- getters and setters (@Getter, @Setter)
- logging (depending on your logging library: @CommonsLog, @Log, @Log4j, @Slf4j)
- there is even more, but for the rest I might not be brave enough ( yet :))

Behind the scenes
OK, sounds nice, but how it works internally?
In fact lombok generates expected methods/fields to the target class. So the nice thing is that you don't need it during runtime/deployment. Once compiled, classes will contain the stuff.

How do you guys feel about it? Would you give it a try? Or do you have some other approach on this? Feel free to share your ideas/feelings.

code syntax highlighting in blog posts


Problem: Need to syntax highlight the code in the blog posts (to improve it's readability).
Solution: github's gist (http://gist.github.com/)

OK now what's the story? I tried to find some simple solution for me to be used in the blogger.com in the dynamic templates.
I've found: gist. 
As one of the quite popular proposals on stackoverflow said :
http://stackoverflow.com/questions/679189/formatting-code-snippets-for-blogging-on-blogger

What is gist?
(Copy pasted from their site) "Gist is a simple way to share snippets and pastes with others. All gists are git repositories, so they are automatically versioned, forkable and usable as a git repository."

Sounds good. But when trying it didn't work for the blogger and dynamic templates.
After some googling found following post:
http://blog.moski.me/2012/01/gist-with-bloggers-dynamic-views.html
and that worked for me!

So since from now on, you can expect some nicely highlighted code snippets in my posts :)

Repost new blog notification to social networks

Problem: How to automatically send status notifications on the new blog posts on blogger to google+, facebook and twitter?
Solution: Two step approach worked for me:
1. use official blogger to google+ integration (to post to google+)
2. use "+Rob Mcgee" (to repost from Google+ to facebook and twitter)

How to achieve it? Go on reading.

Official integration blogger to google+.
Follow the instructions here:
http://support.google.com/blogger/bin/answer.py?hl=en&answer=1752748
Or more specifically, to merge the profiles do so here:
http://www.blogger.com/switch-profile.g

Google+ to Facebook and Twitter reposting
Use the site with the official instructions: http://gplus.sagg.im/
I've found this approach on:
http://lifehacker.com/5868019/how-can-i-post-to-facebook-twitter-andor-google%252B-all-at-the-same-time

In fact I need to test it somewhere, so if you see this post in all these 3, it should be working fine.
Let's see :)

Saturday, May 5, 2012

me-tv 1.4.x built from source on xubuntu 11.10

Q: How to run the latest me-tv 1.4.0.9 on xubuntu 11.10 (64bit)?
For solution, go on reading :)

Motivation for me-tv
I'm the user of me-tv as for me it's the most comfortable solution of watching dvb-t on linux. It has simple ui showing me all the needed in one screen:
- video in the upper part as well as
- per channel schedule shown bellow.
For me it means no time wasted in menu clicking / new dialogs / ...

Motivation for latest version
vlc backend support (as opposed to xine only backend support in 1.3.x versions)

Status research
As in repos there is still 1.3.x version available and I'd like to use the latest one, let's do some research.

Q: What is the latest version?
Short A:  Currently it's 1.4.x
Long A: Based on this link: https://answers.launchpad.net/me-tv/+question/182263 there is new maintainer (original is gone) - Frédéric Côté (frederic-cote) and he restarts development of me-tv in 1.4.x branch that seems to be merge of stable 1.3 (xine based) and 2.0.x (xine/vlc/gstreamer based). The good news here is the usage of vlc as backend. Finally! :)

UPDATE:
hey, after writing this post, I've found that there exists me-tv development PPA: https://launchpad.net/~me-tv-development/+archive/ppa
And for the that's my choice. For those still interested in compiling from source, go on reading.

OK, let's do the job.
Installation steps of me-tv 1.4.x (working for me):
1. download latest stable tgz archive, for me it was https://launchpad.net/me-tv/1.4/1.4.0/+download/me-tv-1.4.0.9.tar.gz (however link is on the main page, check for the latest one: https://launchpad.net/me-tv)
2. unpack it and get in dir
3. install dependencies (I installed all the dependencies listed on: https://answers.launchpad.net/me-tv/+faq/352)

sudo apt-get install build-essential gettext debhelper autotools-dev libxml-parser-perl pkg-config devscripts libtool intltool libgnomemm-2.6-dev libgnomeuimm-2.6-dev libgtkmm-2.4-dev libgnet-dev libsqlite3-dev libvlc-dev libxine-dev libdbus-glib-1-dev libunique-dev

moreover I had to install these:
sudo apt-get install libxml++2.6-2 libxml++2.6-dev gnome-common libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev

4. prepare / start compile/install
./autogen.sh
./configure --prefix=~/Desktop/apps/me-tv_1.4
make
make install

5. now it's time to cross fingers, try to start it:
cd ~/Desktop/apps/me-tv_1.4/bin/
./me-tv-server

got error:
2012-05-05 08:19:06: Me TV Server 1.4.0.9 started
2012-05-05 08:19:06: An unhandled exception was generated
2012-05-05 08:19:06: Error: The Me TV database version does not match the Me TV server version.

OK, seems we need to cleanup configuration (as I've used on the same PC also older version):
mv ~/.me-tv/ ~/.me-tv_backup
it didn't help => as suggested here (https://bugs.launchpad.net/me-tv/+bug/886367) I did also:
mv ~/.local/share/me-tv ~/.local/share/me-tv_backup

one more try:
./me-tv-server
no error
./me-tv-client
we're done! :)

OK, now let's make sure no confusion with the older version happens:
sudo apt-get remove me-tv

There are still things to be fixed, like server auto start as well as integration with UI, however these I'd await from upstream.
For me it's worth using 1.4.x version and that my cpu doesn't need to be burning on 100% with xine any more. Cool!

Tuesday, May 1, 2012

music sync for android on linux

Q: What are the options for managing music on android based device on linux?
A: Banshee, Clementine, ...

First make sure device is connected via usb cable :)

For Banshee:
- start banshee
- import music via: right click (and hold) Libraries -> Music and choose Import Media -> Folders -> Choose Folders (please note that it won't scan the music if it's too deep in subdirs, for me it worked only up to level artist/album/songs)
- wait for scan to complete
- as you connected the device, you should see it in Devices -> [Device name] -> Music
- drag and drop anything from Libraries -> Music to Devices -> [Device name] -> Music
- moreover you can manage (remove,...) your library on the device by activating Devices -> [Device name] -> Music and doing the needed

For Clementine:
- start clementine
- import music via menu: Tools -> Preferences -> Music Library
- choose Add new folder
- wait for scan to complete
- as you connected the device, you should see it in Devices -> [Device name]
- in Library right click on album and choose Copy to device
- choose Destination (your [Device name]) and click OK
- moreover you can manage (remove,...) your library on the device by activating Devices -> [Device name] and doing the needed


Then sync happens, whenever device is disconnected you're done

phone contacts migration - Sony Ericsson W580i to Samsung Galaxy Y

Q: What is the simplest way to get all the contacts from Sony Ericsson W580i to Samsung Galaxy Y?
A: Send them via bluetooth.

I've seen various ways to achieve this on web, however the most of them are via some PC tools. This seems to be at least for me unnecessary. I've found the answer in the comments of one that kind of PC tool based approach.

When trying to migrate all of my contacts I just needed to copy them via bluetooth:
- in w580i went to contacts
- chose More -> Options -> Advanced -> Send all contacts -> Via Bloetooth
- found the target device, sent and voila! done :)

xml anonymization

You might already have been in the situation, where you needed to ask very specific question at some public forum/mailing list that is however coupled with particular XML content.
And possibly the content should not be seen by public.
I needed to, so I checked the options.

How can I anonymize xml?
Google pointed me to - xmlanonymizer (http://code.google.com/p/xmlanonymizer/)
After some stuggling I even found the way to use it.

To get the very latest version, you need to import svn hosted source and build yourself:
- import svn project to eclipse (http://xmlanonymizer.googlecode.com/svn/trunk/), I imported it as Java project afterwards
- Configure -> Convert to Maven project (you need m2e plugin in eclipse installed to do this)
- build as maven project (for example via cli: mvn clean install)
- anonymize your content:
java -jar target/XMLAnonymizer-0.0.2-SNAPSHOT.jar in.xml -outfile=out.xml -overwrite=true
 where in.xml is the xml you need to anonymize and out.xml is the output file

OK, so now you (should) have it running.
 As per default only xml text and argument values are anonymized

But what if you need to go a step further?
I summed up my needs in the bug report there (http://code.google.com/p/xmlanonymizer/issues/detail?id=1):
- I'd need to have also element names anonymized
- I'd like to do anonymization via random digit/char rather than next digit/char in the sequence (as for the xml with maaaaany elements I came to situation, that there were no more element names left => endless loop)
- I'd like to keep anonymized character case sensitivity (lower/upper case)

and finally attached the patch, as the implementation was quite easy