Java, the Programming, and Everything

Tuesday, January 22, 2013

Spock testing framework


Some time ago I gave presentation about Spock on Szczecin JUG. Later I gave this presentation also on my company SoftwareMill meeting. 

I think it's high time to share it on my blog too: http://amorfis.github.com/spock-pres/ (navigate with arrow keys).

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!