Friday, November 2, 2012

FEST Assertions for Joda Time

Do you write unit tests? Of course you do. Do you use Joda Time? I think so. Do you use FEST Assertions? You should try it if you haven't yet. With FEST Assertions we can write fluent code like this:
assertThat(result).isEqualTo(expected);
assertThat(testRunSeconds).isLessThan(maxTestRunSeconds);
assertThat(someList).isNotNull().hasSize(3).contains("expectedEntry");
Now let's assume we have some functions that return joda DateTime, and we want to test it. Can we do this in FEST Assertions?
assertThat(resultDateTime).isAfter(timeframeBeginning).isBefore(timeframeEnd);
No, we can't :( FEST Assertions don't handle Joda Time classes. However, do not worry :) At SoftwareMill we have written our own TimeAssertions for that :) So you can write your code like this:
TimeAssertions.assertTime(someTime).isAfterOrAt(someOtherTime);
TimeAssertions works for org.joda.time.DateTime, java.util.Date and org.joda.time.LocalDateTime. You can freely exchange DateTime and Date, i.e. you can compare DateTime to Date, DateTime to DateTime etc. LocalDateTime can be compared only to instances of the same class, as it doesn't make sense to compare it to DateTime or Date without specifying the time zone. TimeAssertions is available on github. If you want to use it from Maven project, add repository:
<repository>
    <id>softwaremill-releases</id>
    <name>SoftwareMill Releases</name>
    <url>http://tools.softwaremill.pl/nexus/content/repositories/releases</url>
</repository>
And dependency:
<dependency>
    <groupId>pl.softwaremill.common</groupId>
    <artifactId>softwaremill-test-util</artifactId>
    <version>70</version>
</dependency>
Happy testing!

Wednesday, September 26, 2012

Get script's own directory in bash script

It was always a problem for me to get the directory the called script is stored in, in the script itself. Thanks to this SO question (http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in) it's not a problem anymore. As it says:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Or, to get the dereferenced path (all directory symlinks resolved), do this:
DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Saturday, September 15, 2012

Get specific PC IP from "arp -a"

I want to extract IP of machine leonidas. arp -a returns such line (among others): 
leonidas.home (192.168.1.5) at 0:1c:c0:de:8f:28 on en1 ifscope [ethernet] 

To have only IP:
arp -a | grep leonidas | cut -f 2 -d ' ' | sed 's/[()]//g'
prints
192.168.1.5

Monday, January 9, 2012

My encounter with a small bug in Hibernate

The problem

At work, I needed to use entities with @DiscriminatorColumn inheritance. It means all types are kept in the same table, with value in this column showing what type given row is of. It's not recommended way to handle inheritance, but for some reasons we needed to use it. In developement, locally, I was using PostgreSQL database. When I tried to store this entities, I was receiving strange errors. Saying I cannot store an entity because entity with such id is already in database. It was quite strange, I was trying to store vanilla new entity. Test case to show this error is very short, so I'll include it here:
//Parent entity
@Entity
@Inheritance(strategy = SINGLE_TABLE)
@DiscriminatorColumn(name = "CLASS_ID", discriminatorType = INTEGER)
public abstract class ParentEntity {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  private Long id;
}

//Child entity with discriminator  
@Entity
@DiscriminatorValue("1")
public class InheritingEntity extends ParentEntity {
}

//Test
public class PersistChildEntitiesWithDiscriminatorTest extends BaseCoreFunctionalTestCase {
  
  @Test
  public void shouldPersistTwoEntities() {
    Session session = openSession();
    session.beginTransaction();
    InheritingEntity child1 = new InheritingEntity();
    InheritingEntity child2 = new InheritingEntity();
    session.save(child1);
    session.save(child2);
    session.getTransaction().rollback();
  }
}

The cause

This test throws exception on second save, but only on PostgreSQL. Why is that? Well, when you save new entity to persistence context, Hibernate issues SQL call to database instantly. Other queries, like updates, are cached, and sent to database on em.flush or em.commit. But inserting of new entities is not cached and there is a reason for that. When we save new entity, Hibernate needs to assign ID to it, and this is taken from database. Most databases return ResultSet with one row and one column after insert, and it contains newly assigned ID. However, PostgreSQL behaves a bit differently. It returns whole inserted row (of course, with ID filled in). In most cases it works, because ID is the first column in this row, so when Hibernate takes value from the first row and the first column, it is the correct one. However, in case of classes with discriminator, ID is not the first column. Discriminator is the first column. So first insert is correct, ID 1 is assigned to child1, but then when we try to store child2, Hibernate also tries to assign 1 to it's ID, and complaints that there already is another entity with it.

The solution

So there was a bug in Hibernate. Can I solve it? I asked this question to myself, but to answer I couldn't do anything else than try ;) So I forked hibernate repository (yes, it's on github!) and... I was quite overwhelmed by the mass of code there. First challenge was to try to open it in my IDE, with all the subprojects and their interdependencies configured correctly. Thankfully there is gradle task for creating project files for IntelliJ IDEA, the IDE I'm happy user of. Next task was configuring Hibernate tests to use my PostgreSQL database. It turned out quite easy after one or two emails on hibernate-dev list. Now I had to change the code assigning IDs to entities to take it not always from first column first row, but sometimes from column of given name. So I had to get the name of column keeping IDs, which I did with a little help from other developers on the dev list.

The contribution

Now I commited fix to my forked repository on github, issued a pull request, got some comments, fixed files formatting... We'll see if it's accepted. UPDATE: It is accepted :)

Wednesday, December 28, 2011

Easy way to convert file encoding

Easy way to convert text files to UTF-8 on Ubuntu. Install package enca and you are able to:
enconv -L pl -x UTF-8 myfile.txt
Where after -L is language specified (necessary for enca to recognize file encoding before conversion) and after -x destination encoding.
Warning: enconv overwrites existing file, so better create backup copy before.


UPDATE: Another way, useful if you know source file encoding:
iconv -f ISO-8859-2 -t UTF-8 source.txt > utf8.txt

Wednesday, November 30, 2011

Play! with Heroku

Recently, inspired by some talks on Devoxx, I decided to check Play framework and Heroku.

Play is another java web framework, but this one is heavily influenced by Ruby on Rails. Convention over configuration, little code necessary etc. Looks like Play is gaining momentum, version 2 (now beta) supports Scala and now it became part of Typesafe stack.

Heroku is another cloud. Well, quite different than AWS or GAE (actually, as far as I know, it works on AWS). Heroku is not only running applications, it is also able to build and deploy them. So to deploy your changes, it's enough to make git push.

So first, download Play 2 beta from this site. Unpack, add dir to your $PATH, so that you could use play command from anywhere.

Go to dir where you want to create the app and issue play new helloapp (where helloapp is your app name). Play should create helloapp directory. No go into it. You can notice that Play nicely added .gitignore file there, so when you create git repository here, unnecessary files won't be added. Play created fully functional, basic web application. You can issue play run in helloapp directory and the server is going to be started and application deployed. You can now see it on localhost:9000.

Now you'll need account on Heroku. Create one on heroku.com, it's easy as creating email or forum account. Then just activate it by email sent to you from Heroku.

For your app to be able to run on Heroku cloud, you'll need to add one more file. In the helloapp dir create Procfile file with content like this:
web: target/start
If you created your app with Play 1.x instead of 2.0, Procfile should be quite different:
web: play run --http.port=$PORT $PLAY_OPTS

To interact with the cloud you'll also need heroku-toolbelt. Get one from here.

Ok, you have your app and all the tools necessary to deploy it to the cloud. You'll also need git, which I assume you have already installed ;) As I mentioned on the beginning, it's necessary to push your app's code to Heroku.

Create git repository in the helloapp directory. Enter the directory and issue the following comands.
git init
git add .
git commit -m init

This commands created git repository in the directory, added current directory (helloapp) to the git index, and commited the changes to the local repository.

Next thing to do is creating new application on Heroku: heroku create --stack cedar from helloapp dir. This not only creates new application, but also nicely adds remote git repository. Heroku has few stacks. Stack is OS and stuff installed on it for our applications to run. For now, the only stack that supports Play is called Cedar. It's not the default one, so you need to tell Heroku explicitely that it should be used for your application.

It is also going to ask about your credentials to authenticate you on Heroku. It is done only once, and then your credentials key and token are stored on disk. If you want to delete them, just heroku auth:logout.

Ok, so you have application on Heroku, with git repository added to your remote ones, and you have one app locally which you want now to deploy to the cloud. Well, it couldn't be simplier:
git push heroku master

From now on it only takes some patience. Deployment takes time. When it's finished, it gives you the address, something like http://blooming-stone-5863.herokuapp.com deployed to Heroku in the console.

Go to this address and you'll see your app. Have fun!

Thursday, October 20, 2011

Warsjawa 2011

Dear reader. This post is about Polish event, organised by Polish programmers for Polish programmers. Speaking only Polish. So if you don't speak Polish, I don't think you'd be interested. Therefore, this post is in Polish.

W miniony weekend wybrałem się na warsztaty Warsjawa 2011. Wybrałem się z ekipą ze Szczecina jak zwykle pociągiem, co okazało się mieć taki minus, że pora roku jaka już nadeszła zapewnia że w pociągu może być albo zimno, albo gorąco. My wybraliśmy zimno. Jakoś jednak dojechaliśmy rankiem do Warszawy. Ja udałem się załatwić jeszcze parę prywatnych spraw, i nie bez drobnych komplikacji dotarłem do budynku przy Nowowiejskiej na tyle wcześnie, że mogłem jeszcze pomóc nosić ławki i krzesła.

Z czterech dostępnych ścieżek wybrałem DDD i CqRS, prowadzone przez Sławka Sobótkę i Rafała Jamroza. Warsztaty miały części prezentacyjne, i stricte warsztatowe. O ile prezentacjom niczego nie zabrakło (przynajmniej dla mnie, ale obie widziałem już wcześniej), to część warsztatowa jakoś się "rozlazła".

Z początku wstęp do DDD, ciekawy i świetnie poprowadzony. Dowiedzieliśmy się co to takiego to DDD, do czego się nadaje i z czym to się je. Po wstępie Sławek "oprowadził" nas po wcześniej przygotowanej na warsztaty aplikacji, pokazując "klocki DDD", z których jest zbudowana.

W pierwszej części warsztatowej zadaniem uczestników było rozszerzenie funkcjonalności aplikacji w duchu DDD. Zaczęliśmy prawidłowo, od testów. Z braku czasu testy pozostały na etapie wstępnym, tzn. takim, w którym wystarczyło w klasie testowanej z każdej metody zwrócić true żeby przechodziły. Więcej chyba było w tej części dyskusji, pytań i odpowiedzi niż kodowania, ale nie uważam tego za jej wadę. Wszak programowanie to przede wszystkim komunikacja. I tak czas upłynął nam do obiadu.

Na obiad była pizza, zgodnie z obietnicami organizatorów nie zabrakło :)

Po przerwie obiadowej znowu miała miejsce część prezentacyjna, w której Sławek pokazał co to takiego ten CqRS, i jakie ciekawe triki można stosować w celu poprawienia wydajności aplikacji. Np. mieć osobną bazę danych do zapisu i osobną do odczytu.

Prezentacja dość płynnie przeszła w kolejne warsztaty, które jednak chyba więcej miały z prezentacji. Nie żeby mi to przeszkadzało, może nawet tak miało być :) Dowiedzieliśmy się czegoś więcej o kilku bardziej skomplikowanych wzorcach, jak Saga czy Specification.

W ostatniej części Sławek pokazał nowe dla mnie narzędzie JBehave. Musze powiedzieć, że zrobiło na mnie wrażenie, i zamierzam poświęcić trochę czasu na bliższe poznanie tegoż. Zauważam też spore podobieństwo do Cucumbera, ciekawym czym się różnią.

Po wszystkim cała nasza ekipa czuła się pozytywnie naładowana informacjami, czuło się entuzjazm do dalszego zgłębiania poruszonych tematów, a to przecież najważniejsze. I choćby to świadczyć może o sukcesie tych warsztatów.

Jeśli miałbym szukać minusów to może za mało było napojów, no i nie było kawy. Aczkolwiek nie był do duży problem, bo w budynku były automaty zarówno z kawą, jak i z zimnymi napojami.