Monday, August 25, 2008

Win + T, a great new shortcut

It's pretty nice - navigates through the tabs in the task bar.

A great day

As opposed to the previous gloomy post, here I'll tell you (my dear single reader :) about a great day I had a few days ago.

It all started at 8 in the morning: the phone call confirmed - the weather was great. Then a drive from Varna to Russalka (one of the best resorts on our seaside ever) - the trip was great - village roads light on traffic. I arrived in a sexy small bay with a motor boat (I don't know what that's called) on it and a really small island 10 meters from the shore. After a two-hour wait (I was late) I got on the wet suit and the oxygen bottle and my coach and I made a really nice trip around the island - up to 8-meter dives.

I tried to schedule a 25 meter dive - no luck. I had to have a special certificate.

Then with the pass for the diving I was free to do anything inside the resort. Now is the time to say that Russalka is a closed resort. Once inside everything is free - I had three cokes. It's very beautiful. (No camera sorry, I swam with my phone). I almost read Truman Capote's Summer Crossing.

Then on the way back I decided to go check out cape Shabla. Pretty nice place. Pretty close to the border with Romania. No more than 20 minutes there.

On the way there I stopped at Kamen Bryag and checked the ancient Tracian fortress Ajla. An amazing elevated view towards the sea. So pretty. Again 20 minutes there only.

Finally I arrived at Kaliakra - this is by far the most beautiful place I have ever seen in my life. Especially on sunset. The sea looked so powerful and mighty.

The day finished at Slunchev Bryag after a two hour drive at a Roger Sanchez's party. My car got towed and they gave it back for the humble price of 60 leva :( and a 800-meter, 15-leva taxi trip.

I got to bed at 6:30 after the same 2-hour drive after the party.

A great day.

About killing

Few days ago I accidentally hit a sparrow with my car. The poor creature did not survive. There's a really heavy feeling that grabs you right after that moment. Anger, frustration, trying to exonerate one's self. Sadness.

And if that's not enough, yesterday I hit a fox on the highway. I did not even stop to see what happened for which I kinda feel guilty. Again the sadness and thinking about life, the universe and everything else.

Damn bad luck. I have never hit anything before. And from the feeling of it - I'm no good for taking lives - I just can't bare the thought of it.

 Wednesday, August 20, 2008

Blogs that supply part of the content in the RSS/Atom feeds

There are blogs that only supply a resume or part of the content in the RSS. And the reason, I guess, is that they want you to leave the comfort of your own RSS reader and visit their site and maybe see some ads or who-cares-else what.

Well, FUCK THEM. The best I know are not doing it. Actually the best I know have no ads and have minimalistic web sites (I understand it as only content and unobtrusive navigation buttons/links).... and..... provide outstanding content.

Blogs that do that:
http://www.karieri.bg/blog/
http://www.nova-rabota.com/

I decided to stop reading them.


Other things that turn me down - copyright footer, a lot of links like "vote for me in ...." and guys that start taking themselves too seriously. For the latter I'm ready to make an exception, because some of them have an amazing style.

Operation Chicago

I just got the video from the paintball game "Operation Chicago".
I appear in 0:28 and 0:34 (the skinhead guy with the light green camouflage). In 0:34 I get my ass kicked by cross-firing machine guns (I'm behind a pretty thin tree).

  

I should name my blog "Complaining about stuff"

The "sucks" category is flourishing.

But it's damn easier to complain about stuff, than to write something meaningful.

I have to change that.

My blog in Internet Explorer

I just noticed it. It sucks. It's ugly, the font is ugly. How did I not notice that.
OOO, man, I have to fix it :(

In firefox it looks fine. Damn.

SonyEricsson K750i. SonyEricsson people, THANK YOU

Sony Ericsson K750i was my phone for quite a while. This is a thank-you note to the creators of that amazing machine.
Yesterday the latest accident finished it. This time for sure. It doesn't want to switch on. It's not showing any sign of life.

This phone made amazing pictures, most of my public images are made with it. It was the best of its time. There are still phone that can't match that. The iPhone's camera, for example, sucks. With a really steady hand one could make night shots too. I had a 2GB flash card of the awful sony format - memory stick.

The opera mini made it a decent browser. I could read mobi.capital.bg and mobi.dnevnik.bg in the restroom. BTW mobi.dnevnik.bg is boring as opposed to mobi.capital.bg.
Opera mini, BTW, is an example of a perfect minimalistic software. It's amazing. Great job.

I could use the phone with a bluetooth GPS until I lost the GPS in Amsterdam. The software choice wasn't that great, because I only had Java and no operating system. Here's the place to mention Nav4All - an amazing map software with routing (navigation) maps for Bulgaria. Once I ended up in a construction site in Sofia, but I hear these things happen to every map software. Nav4All used internet for downloading maps, and that made it quite a drag.

ReaderManiac made the phone an electronic book reader. Again an amazing software - I was planning to write an article about it, but maybe some other time. I read like 10 books on it. See the read books section (phone pages state that I read this on the phone). Navigation was amazing. Different font and sizes, great software. It even told you when to rest your eyes. I could supply Cyrillic fonts.

Lacking an OS made the phone very stable and pretty fast. It crashed only once a few months. I hate the so called organizers - Windows Mobile sucks big time.

The 2GB flash made the phone an excellent mp3 player. While snowboarding at -20 degrees Celsius it was working flawlessly. The earpieces weren't that well attached but the quality was quite satisfying.

A business phone: when it said that the battery was depleted it could work for at least a day at heavy use.

Negative sides: the jacks got pretty dirty and the earpieces and the usb connection got interferences. The screen wasn't as bright as the new phones. The inside of the protective glass (plastic) in front of the screen got full with sand and dirt and it was quite hard to clean it up. Thanks, Steen. Ugly flash card jack (memory stick duo), ugly earphones jack (something SonyEricsson). Nokia beats it here..

Update: I'd like to thank the mobile-review site for the outstanding reviews they make. Here's the one for K750i. Surely, I'll consult them for my next phone too. Also, their news page looks quite deserted, I really hope, they would continue to write good reviews.

So chronologically:

First while free-riding (snowboarding outside the track in fresh snow) I dropped it. After 80 minutes of heavy ringing I found it pretty wet under 20cm of snow still working and most importantly ringing so I could find it.

Second, I swam with it in a pool for at least half a minute. After a complete drying it continued to work but with a few minor quirks. Battery swelled up few days later and nearly blew up the whole phone. The new battery didn't charge correctly. The quality of the talks went significantly lower.

Third, yesterday I was with the phone in the sea for around 10 minutes. This was the end of it. It didn't show any signs of life after that. I did everything I can.

It's over.

Thank you, SonyEricsson people. This is was an amazing example of equipment.

Unfortunately SonyEricsson does not have a decent model with GPS. And that's what I'm looking for. I'm planning to have an iPhone (my roommate has one, it's a decent thing, but not for a primary phone) and maybe a Nokia with a GPS. My friends say E71, although ugly, is a pretty good one for business purposes. Both suck at pictures.
Maybe N82 too. We'll see.
Update2: BTW, mobile-review guys give a pretty bad review of the iPhone. They're right, I also strongly dislike Apple and its "closed" approach, but the article seems a little prejudiced. It seems personal. A red (bad) point for them.

Any other suggestions? I'm looking for a GPS, decent mapping software with maps and routing/navigation, wireless, a decent camera, fast interaction, no Windows Mobile, a lot of space, decent mp3 player, sturdy....

Vital equipment dying

I think I'm having a bad dream.
Most of the most important technical equipment around me is failing:

First the phone: SonyEricsson K750i. An amazing machine. Very sturdy, survived a swimming pool, being lost in the snow while snowboarding, numerous hits, is now dead.

The laptop's battery completely fucked up, it's constantly overheating. The laptop itself is scaring me up - not to die one day - it's a DELL, so....

My car is on the end of its usable life. Although I'm so thankful to it for saving my life after all the stupid things I did when I was younger, I have to change it.

I'm planning to buy a motorcycle.

It's partly my fault - most of the equipment was showing dreadful signs for a long time, but I constantly postpone to take measures.

So now to be able to buy all that I'm thinking of finding a second job or sell a kidney.

 Friday, August 15, 2008

I hate CDs/DVDs

I really do. Windows doesn't seem to understand them - the whole system stops and waits for a single DVD. The laptop is shaking.

Read/write times are really slow. Burning them with the windows's ATAPI service is hell.

When used to working with 3-5 MB/sec without worm-up times and spin times and whatever else times, it's really annoying.

But DVDs are the only reasonable way to give someone 15 GB even though you'll have to spend 2 hours to burn them.

P.S. I want to remove my laptop's DVD combo whatever bullshit, but I can't :( It's such a waste of weight and space.

Vista doesn't want to update to SP1

I don't know why. The update just does not want to come.
There are always other updates.

I'm too afraid to update to SP1 manually. Who knows what will happen.

And I want to stress that this is a legal copy.

Firefox is slow and youtube fails

Firefox is getting really slow. I don't know why, it may be due to too many plug-ins - I have 4 or 5.

And if working for sometime it stops playing flash streaming videos (youtube, google video....).

It has to be restarted. I'm disappointed.

Vista/XP can't burn a single CD/DVD without infuriating you

This is part of the series 'Vista sucks'. Although XP sucks as much as Vista in this case.

There was a feature first introduced in XP for burning CDs. In Xp the service was called something like ATAPI burning or whatever. Couldn't burn DVDs. In Vista the same software could burn DVDs. I couldn't find the service name. I may have missed it somehow.

So this software was a nice feature - simple, fairly stable.

But it's so darn slow and requires twice as much space as the burned data. Here's why:

First you copy the files on the CD/DVD with Windows Explorer. This copies the files in a cache of some kind. Trying to burn 4.5 GB requires 4-5 minutes of copying - and the machine is unusable  - copying utilizes the HDD. If you do something else it could take up to 20 min.

Then to burn them, the wizard should be started - this again copies the files to another cache I guess. Again 5 to 20 minutes.

This means 9 GB of space needed + the actual 4.5 GB. And a lot of time.

Vista/XP you messed up a good idea again. Vista/XP you suck.

As far as I can remember Nero was a lot faster, no cache needed, or at least no that much. Is Nero still good? Is there a light version of it?

 Monday, July 21, 2008

Adding columns to join tables (in the context of JPA/Hibernate)

At some point in a @ManyToMany relationship I had to add some extra columns in the join table (the middle table).

Here's what Gavin King says in Java Persistence with Hibernate (a notable book on the subject):

Adding columns to join tables
You can use two common strategies to map such a structure to Java classes. The first strategy requires an intermediate entity class for the join table and is mapped with one-to-many associations. The second strategy utilizes a collection of components, with a value-type class for the join table.

Later in that chapter for the first approach (the extra entity for the middle table):
The primary advantage of this strategy is the possibility for bidirectional navigation: You can get all items in a category {...} and the also navigate from the opposite direction {...}. A disadvantage is the more complex code needed to manage {...} entity instances to create and remove associations—they have to be saved and deleted independently, and you need some infrastructure, such as the composite identifier. However, you can enable transitive persistence with cascading options on the
collections {...}, as explained {...}, “Transitive persistence.”

Later in that chapter for the second approach (the collection of components approach):
That’s it: You’ve mapped a ternary association with annotations. What looked
incredibly complex at the beginning has been reduced to a few lines of annota-
tion metadata, most of it optional.

Naively enough I chose the second approach. Who cares that there's a hibernate dependency in my JPA data access layer. I already have a few (a hibernate interceptor).

In this approach I had to use the @CollectionOfElements annotation. @CollectionOfElements works like that: it maps a collection (set, map, list) of something to a table. This table has no entity attached to it. It can work with value types, Strings and @Embeddables. In my case it had to be the @Embeddable.

Let me give you an example - it will clear things up: there are classes and there are students - two entities. There can be two classes with many students some of which are the same - so the relationship is @ManyToMany. The extra column in the join table would the grade of the student in that class.

So the approach with the @CollectionOfElements works like that: one of the entities holds the relationship - let it be the class entity - so it has something like that:

@Entity
public class Class {
    @Version
    private int version;
    ...
    @org.hibernate.annotations.CollectionOfElements
    private Set<GradedStudent> students;
    ...
}


Student is a simple entity, no code needed. Let's call the student with the grade an GradedStudent:
@Embeddable
public class GradedStudent {
    ...
    @OneToOne(..., cascade = {MERGE, PERSIST, REFRESH})
    private Student student;
    ...
    @Column( nullable = false, ... )
    private int grade;
    ...
}

That's pretty much it. Seems simple, you would think and straightforward.

BUT IT DOESN'T WORK.

Here's what gets wrong:
  1. Everytime a class entity gets queried, it's version gets incremented. This makes updating a disconnected entity far more difficult and makes the @Version kind of obsolete.
    Solution: none, I couldn't find anything remotely connected to this problem on the net.
  2. The primary key in the join table (with a name like 'class_gradedstudent') is not the [class_id, student_id] but is [class_id, student_id, grade]. If you put extra columns in the join table and they are nullable = false, they would become part of the primary key.
  3. Cascading fails. You have to create and persist a Student first in order it to become a part of a certain class entity. Even though a GradedStudent is said to cascade a Student.
    Solution: none, I tried everything I could think of - no luck. I couldn't find anything remotely connected to this problem on the net.

Regarding 2: a quotation from the same book:
There is only
one change to the database tables: The {...} table now has a primary
key that is a composite of all columns, not only the ids of the two object, as in
the previous section. Hence, all properties should never be nullable—otherwise
you can’t identify a row in the join table.
Well, what if I don't want that? It doesn't say.

So, actually the second approach is not an option.
 Friday, July 18, 2008

@CollectionOfElements, JPA, the documentation and the problems it raises

In a project that I mention a lot there's an persistent model using JPA as an interface to Hibernate.

There was case where I wanted to put extra columns in a @ManyToMany relationship. JPA cannot do that.

So I had to use the Hibernate's @CollectionOfElements.
It works like that: if there are the objects Class and Student, the extra columns go to the wrapper class EnhancedStudent. The EnhancedStudent has a property of type Student.

Now I have a few bugs related to it:
  1. Causes the @Version of the containing object (Class) to increment on EntityManager.html#find(java.lang.Class, java.lang.Object)
  2. The creation of an ExtraStudent cannot propagate (cascade) the inner Student - no matter what.
The funniest thing is that the documentation of the @CollectionOfElements is a single line:

Annotation used to mark a collection as a collection of elements or a collection of embedded objects

http://www.hibernate.org/hib_docs/annotations/api/org/hibernate/annotations/CollectionOfElements.html

:(

Gotcha MTEL, YOU CHEATING BASTARDS

From some time I noticed that Mtel (my mobile service operation) is using VoIP when I'm calling an Mtel number while roaming.
When I'm calling another operator's number while still roaming, there's no VoIP.

CHEAP BASTARDS. For these prices you can at least provide a decent service - a VoIP call is with bad quality and the callee cannot see who's calling, he sees some service number.

BUT THATS NOT ALL.

The top of the cherry is that when Mtel is using VoIP they clearly cannot see whether the other side answers or not, so no matter whether you make a successful call or not - while you're ringing you get billed. That's not right, is it?!

I found out all that today while checking my bill. Two months ago while in Brno I made a call and was quite sure that I would get billed for that call even though nobody answered.

GOTCHA, YOU CHEAP BASTARDOs


Update: other case of proved cheating:
Mtel made me pay 200 bucks for half a megabyte of internet while roaming. Before that I explicitly asked for the price. It came out that the price is 10 times more and they charge every GPRS session for a full megabyte (with 10 times the prices) without saying it.

Few months ago I caught them billing me for an international call to a friend I haven't spoken with for at least a couple of years.

 Thursday, July 17, 2008

Ctrl+Shift+T in Firefox = reopen last closed tab (window)

Ctrl+Shift+T is a popular shortcut in Eclipse.

Ctrl+T is a popular shortcut in Firefox - opens an empty tab.

Once by mistake I pressed the former by mistake and found out that Ctrl+Shift+T makes an undo for the last closed window (tab). And not only for the last tab.

Cool

Mocking an EJB Container

There are a lot of tests for some EJBs.

Starting an J2EE server is slow. I wanted to test the business logic faster.

Most of the beans reference only each other and a persistence context.

So what should the mock worry about - transaction demarcation and dependency injection. And... exception wrapping and unwrapping.

  1. First just add some setters or change the access level modifiers (from private to protected for example).
  2. Know your transaction authority.
  3. Count started transactions. If 0, begin. If 0, commit. Rollback when necessary.
  4. Listen for all the exceptions and wrap and unwrap them.
  5. Reuse as much as possible of the code.
If I have some spare time left, I'll write some code.


Serialization, cyclic references (via hashmaps) and overriding hashCode()

I'll try to simplify it.
There's an object model. In it there are cyclic references (one object references a second one, the second one - a third one, the third one - the first one).
Some of the cyclic references are through aggregations - one object has a map of other objects.
Some of the objects have a meaningful hashCode() and equals() overridden. These two depend on some properties in the object itself.

Some of the objects get serizalized/deserialized (travel through a stream).

Now here comes the problem - the deserialization first sees the cyclic reference, makes instances of all the objects, initializes all the primitive fileds, does not initialize the other fields, then links the objects.

Here comes the problem, linking two objects (one of which has a map of the other) requires hashCode(). This requires some specific properties in that object that are not initialized - this causes NullPointerException (or in my case an AssertionError).

If the hashCode returns a default value if the properties are not there - another serious problem si caused - there are objects in the map in the wrong buckets - they entered the map with the default hash, but when they got completely initialized - they now have a different hash. I think that is really bad - the map has to be rehashed.

Here's a bug detail:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4957674

Here's what some of the guys say on the subject:

The problem is that HashMap's readObject() implementation , in order to re-hash the map, invokes the hashCode() method of some of its keys, regardless of whether those keys have been fully deserialized.

And:

The fix for this is actually quite easy: Modify the readObject() and writeObject() of HashMap so that it also saves the original hash code. (I am currently using this fix in production code for a large web site.) That way, when the map is reconstructed, you don't have to recompute the hashcode----the problem is caused by recomputing the hashcode at a moment when it is not computable.

What you *give up* with this fix is that HashMaps containing Objects that don't override hashCode() and equals() will not be deserialized properly.

So basically, you have a choice: either it will be robust for classes that implement hashCode(), or it will work for bare Objects(). One or the other. I prefer the former, because people are supposed to implement hashCode().

But, not all my object have a rewritten equals (of course I can check with reflection which ones do and which ones don't, but...). This would also mean that I'm using a customized collection.


There's another proposition - to hash the hashcode.

The fix for this is actually quite easy:  Modify the readObject() and writeObject() of HashMap so that it also saves the original hash code.  (I am currently using this fix in production code for a large web site.)

The hashcode is a primitive type, so it would get initialized first and the problem would be solved. This would mean to have an hashCode() and equals() which check which one is available - the cached hash or the properties - isn't that UGLY.

I'll investigate more.
 Monday, July 14, 2008

73 meters from the ground

This is 73 meters from the ground. It is scary and physically intensive. I did this route twice, the first time without the special gloves. My fingers still hurt.



On the top the second time (on the verge of not making it).


It's over, let's have something to eat.


More pictures when I get them.

MySQL, I hate you so much [Installing mysql as a service]

The first idea was to have the DB (MySQL) start as part of the script that launched the tests. Google couldn't find anything good. MySQL is one of the most unintuitive things I have ever seen, so the decision was to not try to figure it out on my own.

The next thing was to install MySQL as a service. That turned out to be difficult.

I tried to install MySQL as a service:

/>mysqld --install

As easy as that. The problem is IT DID NOT WORK. The service did not want to start.

After some reading it came out that the RIGHT way was to do it like that:

__correct dir__/><<path>>\mysqld.exe --install MySQL --defaults-file="<<path>>\my.ini"

Why do I have to supply the mysql directory explicitly?
Why do I have to supply the my.ini directory explicitly?

Why doesn't mysqld give me an error message when I install it without the needed parameters?
Why doesn't mysqld give me an error message when I install it without the needed explicit paths?

...is beyond my inderstanding.

MySQL, you are a disgrace.
MySQL, not only are you not a real RDBMS but you can't even start without making your users' life misserable.


Google mail servers fail?! All of them?

Connection timed out on all their servers?!

Technical details of temporary failure:
TEMP_FAILURE: The recipient server did not accept our requests to connect.
[ASPMX.L.GOOGLE.com. (1): Connection timed out]
[ALT1.ASPMX.L.GOOGLE.com. (5): Connection timed out]
[ALT2.ASPMX.L.GOOGLE.com. (5): Connection timed out]
[ASPMX3.GOOGLEMAIL.com. (10): Connection timed out]
[ASPMX5.GOOGLEMAIL.com. (10): Connection timed out]
[ASPMX2.GOOGLEMAIL.com. (10): Connection timed out]
[ASPMX4.GOOGLEMAIL.com. (10): Connection timed out]