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.

Iterating over iterator contents with a for loop

How an iterator works:

Iterator i = collection.iterator();
while( i.hasNext() ) {
 Object o = i.next();
 //do stuff
}

Well, I want to move the red line in the loop init, so it would not mingle with the loop body where only business logic would reside.

Unfortunately that cannot happen. A for loop first inits the data, then checks the condition. With an iterator one has to first check if there are elements, then to get them.

And why would someone give you an iterator instead of a collection, my mind cannot understand. (org.hibernate.Interceptor#postFlush(java.util.Iterator))

Hibernate, AuditLogging, cannot configure listeners in persistence.xml

First, what's my goal

I want to do an audit log. I read the http://www.hibernate.org/318.html and there two different approaches were mentioned.

The first is using a Listener.

The second is using the new eventing model in Hibernate3.

The author said that he couldn't make the eventing approach work for an unknown reason.

I'm using Hibernate via JPA. I'm using it in an EJB. So the problem
with the first approach is that it is difficult (if possilbe) to supply
the same transaction to the interceptor so that it can write an entry
in the audit log. There is a solution with a static field holding a
session or an EM, but that seems ugly.

So I chose the second approach. I created a class, inherited few
eventhandlers (PreInsertEventListener, PostUpdateEventListener ) and
tried to add the class as a listener.

Using the API, it worked (the callback methods in the listeners were called):

AnnotationConfiguration configuration = new AnnotationConfiguration();


configuration.setListener( "post-update", new Test1() );

configuration.addProperties( hibernateProperties );

EntityManagerFactory factory = new EntityManagerFactoryImpl( configuration.buildSessionFactory(),

  
PersistenceUnitTransactionType.RESOURCE_LOCAL, true );

EntityManager result = factory.createEntityManager();

Using properties (as if using persistence.xml) failed(the callback methods in the listeners were NOT called):

Properties hibernateProperties = new Properties();

...

hibernateProperties.put( "hibernate.ejb.event.pre-update", "package.Test1" );

hibernateProperties.put( "hibernate.ejb.event.pre-insert", "package.Test1" );

 
AnnotationConfiguration configuration = new AnnotationConfiguration();

configuration.addProperties( hibernateProperties );

EntityManagerFactory factory = new EntityManagerFactoryImpl( configuration.buildSessionFactory(),

  
PersistenceUnitTransactionType.RESOURCE_LOCAL, true );

EntityManager result = factory.createEntityManager();

Ideas why?

Strongly-typed vs. weakly-typed

There is a certain group of people (counting me too) that are used to working with strongly typed languages. It's really hard for that group of people to understand how technologies like php, html, javascript (..., rss, perl, ...) become so popular.

The answer is (in my humble opinion) the ease of use and rapidness. Everybody can learn to use them. Sacrificing the good style and the heavy approach (that comes from the heavy books) comes out be (in most cases) an acceptable loss.

The biggest screen resolution I have ever seen - found in my living room

Have you ever seen a screen that supports that big a resolution? This is (...calculating...) ~4.29 GigaPixels. Quite a lot, huh?

Check out how many options it gave for color depth.


P.S. This happened on a friend's machine after two years of no support and windows update.

A custom res:


In a few days

In a few days this adventure (having a blog) is going to have its first birthday. I remember the birthday because it is embedded in the admin password (yea, try me ;).

Today I was reading a few articles about having a blog (here and here) and the impression I got left with was that starting a blog is not always a good idea and to do that you have to have something to share and to follow some rules and most importantly have a goal.

F**k that. (Update: I don't know why I put asterisks, maybe I'm afraid of the moderators ?!)

I don't know if I have something to share. I don't know if I have a goal set for my blog. I didn't know about the rules until today. But I don't care.

What made me start the blog was an article from Joel (I can't find it right now) that simply said that a blog can help you express yourself better, can help you perfect the language you present your blog in, can help you understand yourself better. And one other thing - get more feedback for yourself - and that one is particularly precious for me.

So, do I follow the rules - no. Do I care - I guess not. (yea, sometimes I check the logs to see how 'famous' am I and the good results and some comments boost my ego, but that's pretty much it). Overall, I find it a good experience and the time spent on the blog wasn't completely waisted.

What am I going to do from now on - I guess pretty much the same thing.

P.S. Thank you my one reader for the continuing support and the few comments you left from different IPs (appreciate the effort). I would gladly buy you a beer.

'I'm shocked'

'I'm shocked' is what Charlie Sheen playing Charlie from 'Two men and a half' always says with a beer in his hand when his brother does something stupid.
(Comment to me: I have a problem: cannot produce short sentences.)

Here I am playing the dumb thing Vasko and I gave as a present to one crazy dude:


Update: it's fu*king unpleasant.

E-banking - finally, there may be a winner

Seeing these posts first may help get the context of the talk:
What not to do when you're a bank
What to do when most e-banking interfaces suck?
First Investment Bank, the sequel
SG Expressbank

Being stuck with SG Expressbank made electronic transfers impossible, because they didn't work with epay.bg (prohibited) nor did they work with the e-banking software (every recepient has to be registered offline on-site (bank office), and for the ones that are registered the software does not work 🙂 ).

Almost by accident I tested a card I had in epay.bg for the balance (most banks have stopped this service, because of too many requests). And... I got it. It was working. Strange.

I remebered that I had registered the e-banking for that bank and had left the user/pass somewhere.

After a few days of searching I found it.  Keep in mind that getting the user/pass from the bank was quite an adventure and took more than 20 days and quite a few trips to the local office.

The login screen is right on the main page of the bank. I was amazed to see how easy the generation of the certificate was. While doing it I saw that they support smart cars (e-signatures). Well done.

The interface is really user friendly. Supports almost everything or at least it seems so. I haven't tried it yet, because the bankaccount is nearly emtpy.

From the interface notifications can be defined: SMS notifications, email notifications. Now I'm waiting to see whether it works.

A minor drawback was that I can't tranfer money to another bank account via epay.bg - I guess only FIB cards can (FIB is connected to epay).

And because I'm lazy to do it the old-fashion way - now I'm using the only possible way to transfer money electronically from SG Expressbank card to the new card I have - the epay's microbill (микросметка) - another thing I have to learn how to use. It was quite straight forward to start up and use, but it takes a few days (in my case 2 full days) to tranfer the money and the commissions are not going to be small.

@Lob in JPA, what if the class is not Serializable

If you have

@Entity
public class Student {
    @Lob
    private static MyPictureClass picture;

and suppose you forgot to put Serializable to MyPictureClass, then guess what: there's no exception. You have to check the data in the DB.

Surprise no2:
Suppose MyPictureClassis a base abstract class and it is not Serializable. Suppose every inheriting class is Serializable. Then what happens? Well one thing's for sure: there wouldn't be an exception, but there wouldn't be any data in the DB (you'll get null). The runtime checks (in Hibernate) check the signature of the defining class I suppose, not the supplied class at runtime - and I would assume the opposite, because serialization works the opposite way. Maybe it's because Hibernate does some runtime bytecode modifications.

Primitive types as fields in an JPA Entity

The JPA spec supports primitive types as @Columns. What they don't say (assuming Hibernate is the implementation (maybe TopLink does that too)) is that this column becomes nullable = false and the default value is the default for the primitive type. And that is so, even though the @Column(nullable by default is true.

So

@Entity
public class Person {
    private int age;
    private boolean male;

actually means

@Entity
public class Person {
    @Column( nullable = false )
    private int age = 0;
    @Column( nullable = false )
    private boolean male = false;


So watch out.

hudson ant javac unit-tests fork=true, cannot start javac.exe compiler

Hudson is a continuous integration tool similar to CruiseControl. It has a very good web GUI for defining tasks unlike CruiseControl.
Inside it I have configured a call to an ant task.

Strangely enough in on of the projects that had to be build I got:

build.xml:200: Error running _path_to_jdk_/javac.exe compiler

Strange.

I double checked the script in eclipse. It worked.
Manual call to ant on the eclipse machine also worked.

Then I went to the Hudson machine (a test environment). I ran the script manually. The same freaking error.
I copied the whole dir to another place on the test environment: no problem.

Maybe it's the credentials: added read/write to all. Still the same error.

Then I ran the script with: ant -verbose and see what I got:

_path_\build.xml:75: _path_\javac.exe compiler
        at org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter.executeExternalCompile(DefaultCompilerAdapter.java:509)
        at org.apache.tools.ant.taskdefs.compilers.JavacExternal.execute(JavacExternal.java:61)
        at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:997)
        at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:820)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
        at org.apache.tools.ant.Main.runBuild(Main.java:698)
        at org.apache.tools.ant.Main.startAnt(Main.java:199)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: java.io.IOException: Cannot run program "_path_\javac.exe": CreateProcess error=87, The parameter is incorrect
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
        at java.lang.Runtime.exec(Runtime.java:593)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.taskdefs.Execute$Java13CommandLauncher.exec(Execute.java:828)
        at org.apache.tools.ant.taskdefs.Execute.launch(Execute.java:445)
        at org.apache.tools.ant.taskdefs.Execute.execute(Execute.java:459)
        at org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter.executeExternalCompile(DefaultCompilerAdapter.java:506)
        ... 20 more
Caused by: java.io.IOException: CreateProcess error=87, The parameter is incorrect
        at java.lang.ProcessImpl.create(Native Method)
        at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
        at java.lang.ProcessImpl.start(ProcessImpl.java:30)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
        ... 29 more
--- Nested Exception ---
java.io.IOException: Cannot run program "_path_\javac.exe": CreateProcess error=87, The parameter is incorrect
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
        at java.lang.Runtime.exec(Runtime.java:593)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.taskdefs.Execute$Java13CommandLauncher.exec(Execute.java:828)
        at org.apache.tools.ant.taskdefs.Execute.launch(Execute.java:445)
        at org.apache.tools.ant.taskdefs.Execute.execute(Execute.java:459)
        at org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter.executeExternalCompile(DefaultCompilerAdapter.java:506)
        at org.apache.tools.ant.taskdefs.compilers.JavacExternal.execute(JavacExternal.java:61)
        at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:997)
        at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:820)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:357)
        at org.apache.tools.ant.Target.performTasks(Target.java:385)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
        at org.apache.tools.ant.Main.runBuild(Main.java:698)
        at org.apache.tools.ant.Main.startAnt(Main.java:199)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: java.io.IOException: CreateProcess error=87, The parameter is incorrect
        at java.lang.ProcessImpl.create(Native Method)
        at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
        at java.lang.ProcessImpl.start(ProcessImpl.java:30)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
        ... 29 more

Cannot create a process?!
That's weird.

So tired enough I did something desperate:

From

<javac fork="true"

I went to


<javac fork="false"

and it worked ..... 🙁

Keep in mind that in the same build project I was calling a few other build.xml doing <javac fork="true"
several times before this one.
But this one was the only one having a reference to junit.jar (somewhere on the net I saw an article saying something about junit but don't remember what).

So I left it like this.

First Investment Bank, the sequel

I was unhappy with my bank (What not to do when you're a bank).

Recently, the rumors about it going bankrupt became stronger and stronger so I cashed out my accounts and went for another bank.
The rumors came out to be fake and I felt like a dumb ass, becase I followed unchecked information.

But overall I don't regret my decision. The bank now has a new software which sucks big time. I was on a few occasions unable to access my money (ATM, online, bank office), so I don't think this is a bank that I could trust.

First Investment Bank, you were one of the best, now you're one of the worst.

What to do when most e-banking interfaces suck?

In a previous post (here) I spoke about having trouble with e-banking software of my bank.

There is a pretty simple solution - the online payment operator - epay.bg. It also can do bank transfers, so it's perfect for the task.

Epay can work with almost all bank cards, it's cheap, it's user-friendly, it's reliable. It's the perfect solution.
One minor drawback - it can't check balance, because for sometime now most banks don't support that feature for epay 🙁

Still I'm going to use it. I can check my balance using the e-banking app.

What not to do when you're a bank

My primary bank is First Investment Bank.
I chose a quite a while ago because it had the reputation of a bank that was the first in everything.

It's e-banking was uncomparable with the competitition - outrageously ugly, but accepted smartcards and did all I wanted it to do.

Now it's getting different - they changed their system with a new one. Something called FlexCube. Weirdly enough owned by Oracle.

From internal sources I know that the new system sucks and they failed to deploy it for more than a year. And when they finally made it last week during the weekend - my bank card was not working, meaning me without access to my money just before I went to Serbia. I had to take a loan to be able to go - not a pleasant thing to do.

So about the new e-banking interface - it sucks, all my preferences and beneficients are gone. It's ugly and hard to learn.

So I'm looking for a new bank with a decent e-banking services.

I have experience with SG Expressbank and Postbank - they suck too.

Update: the comments following that post reminded me of a story:
I was in the Netherlands. Once talking to one of the guys we discussed how much cash does each of us carry. I did carry a lot, he counted on the cards he had. My case: bank cards don't work on the road, on the street, they can fail, cash cannot fail.

Later that week:
There was this friend with which we drank quite a few drinks and on the way back to the hotel (I was in an apartment, the friend in a hotel) they said the employer forgot to pay the room, so it couldn't be used. We tried all the credit/debit cards we had - no luck - none of them worked. He had to sleep at my place. Cash is bulletproof !

Srbija

I spent a couple of days in Serbia. Pictures here.

Overall I was surprised by what I saw - although they are not a rich country, its visible that they are situated closer than us to the more developed countries.
They don't speed on the road, it's clean and nice and green and ordered, people are really polite, roads are so much better than the Bulgarian ones.
Overall they are more advanced than we are.

EJB Exception wrapping, commiting broken transactions, resource handling in finally statement - overridding thrown exceptions

In this piece of code the task is to override system exceptions (JPA, JTA exceptions) with application exceptions:

try {
    transaction.begin();
    bm(); //business method
} catch (PersistenceException) {
    //rewrite persistence exception and throw it     (1)
} finally {
    try {
        transaction.commit();
    } catch (RollbackException re) {
       if( re.getCause() instanceof PersistenceException ) rewrite
       else // THROW SOME DEFAULT EXCEPTION          (2)
    }
}

The rewriting of PersistenceException (PE) is straightforward.
It could come from the business method (bm()) and from commit().
When it comes from commit() it is wrapped in RollbackException. Thus the if.

Unfortunately if PE is raised from the bm(), it is also raised from the commit().

So if I throw an exception at (1), it gets overridden in (2). As simple as that. Because of the finally's ability to override results (OOP got messy here).

So what should be fixed?
First, at (2) I shouldn't throw any exception.

Second, I'm thinking of checking the result of bm() - if an exception, don't call commit(), but rollback().
Sounds right.

JPA (Hibernate), EJBs, and WebServices interface.

Here's the design:
EJBs for business logic, JPA @Enitities for object (domain) model, Web services for a public interface.

The model is quite complex.

Even in the presentation (web services) I use the entities model.

The problem comes from that in the presentation a call is made to an EJB. The EJB returns an entity which after the call is ended gets disconnected. So all collections (@OneToMany) cannot be loaded.

EAGER fetching was the solution but then half of the database was loaded on a single method call. And eventually I got to a really ugly MySQL limitation (A query with more than 61 joins (inner selects + cases + at least 40 left outer joins) and a length of 436 lines.

Now before returing the entity in the EJB method via Reflection I initialize all the collections I need. Ugly.

What I need and would perfectly fit me would be an eager fetching only until some level of deepness is reached, then switch to lazy. Then a level of 2 or 3 would be perfect.

Currently I don't of something like that existing.

If someone has an idea, please let me know.

Localization (L10n) vs. Internationalization (i18n)

As simple as that:

Internationalization can be thought of as the design and information technology practices that enable localization to take place. It adapts products for potential use all over the world, whereas
Localization allows products to be suitable for a specific place, or “locale.”

So before thinking about localization, product and software designers must conceive the product in a way that will allow it to be later localized to many different cultures.

[Joke] IT Developers in projects

Five cannibals (Man eaters) get appointed as programmers in an IT company.

During the welcoming ceremony the boss says: "You're all part of our team

now. You can earn good money here, and you can go to the company canteen

for something to eat. So don't trouble the other employees". The cannibals

promise not to trouble the other employees.

Four weeks later the boss returns and says: "You're all working very

hard, and I'm very satisfied with all of you. One of our developers has

disappeared however. Do any of you know what happened to her?" The

cannibals disown all knowledge of the missing developer. After the boss

has left, the leader of the cannibals says to the others: "Which of you

idiots ate the developer?"

One of the cannibals raises his hand hesitantly, to which the leader of

the cannibals says: "You FOOL! For four weeks we've been eating team

leaders, managers, and project managers and no-one has noticed anything,

and now YOU ate one developer and it got noticed. So hereafter please

don't eat a person who is working."

source: here

Refactoring

On a recent project I had after some thoughts I decided to unify some coding styles.
Eclipse rules in that matter. It was cumbersome, but easy enough. Until I reached a point.

Refactoring some coding style differences is a piece of cake.
Refactoring some design issues you want to fix is mission impossible.

The best way to proceed - scrap it and start from scratch. By scrap it I mean make a clean project and copy only relevant stuff.

Now this project has 2 times less classes 🙂

JPA (Hibernate) and enums, Updated

If there's an enum
(this is all java 5)
  

@Entity
public static enum Type {
    TYPE_1(1);

private int i;
    private Type(int i) {this.i = i;}
}

you can't do entityManager.merge( Type.TYPE_1 ), because merge returns a persisted copy of that object and requires a default constructor.
Even if you add

      

private Type(){}

it would fail.

The only way to add the possible values is with persist:

step1:
for( Type type : Type.values() ) {
    entityManager.persist( type );
}

Unfortunately I don't know of a shortcut for that operation - it seems logical all enum values to be in the DB, but are not there by default.

So what happens if there's an object

@Entity
public class Subscription {
   // Cascading for all operations
   protected Type type;
}

and one wants to persist an object like that: 

entityManager.persist( new Subscription() ); // would work even without step1
entityManager.merge( new Subscription() ); // would work only with step1
entityManager.merge( new Subscription() ); // without step1: "
InstantiationException: No default constructor for entity

So the conclusion is:
It's relatively easy to use enums as @Entities as long as on DB init all the enum values are preloaded in the DB (step1).

UPDATE:
What I wrote so far is true, BUT:

Even if one can persist enum, one cannot get them back, because of the aforementioned problem with the default constructor.

I was thinking of the doing the type-safe enum design pattern myself (as it was done pre- java 5): useless supplying a default .ctor prevents having a small number of instances - so again no good. Maybe if the .equals() and .hashcode() are rewritten this could work (but with a larger number of instances and a small number of different hashcodes) - just thought of it, may or may not work. One has to think about @Enumerated (JPA) or about Enum.name() and enum.ordinal() - still it does not look achievable.

There is an ugly solution of which I shall speak tomorrow because I want to go home !!!.

UPDATE: The solution: (be warned it's really ugly).

There should be an @Entity with an int (or whatever actually) @Id.
Then there should be the enum with a private property, whose type should be the @Id of the previous class. There should be a getter of that property
The getter() and setter() of the @Entity should be with the enum's type and in the getter and the setter the wrapping between the enum and it's int (or whatever actually) should occur.

Examples when I get back from lunch.

UPDATE: Example

// The enum
public enum Gender {
  Male(0),
  Female(1);
  private int value;

  private Gender(int value) {
    this.value = value;
  }

  public getValue() {
    return this.value;
  }
}

@Entity
public class Entity1 {
  @Id
  private int gender;

  // ... other properties

  public Gender getGender() {
    return Gender.valueof(this.gender);
  }

  public Gender setGender( Gender gender) {
    this.gender = gender.getValue();
  }

  // ... other stuff.
}

Yes, I know - it's ugly, but this is the best I know.

ICQ in GoogleTalk web client (gmail) - amazing

Open browser, go to the messenger part, log in, as simple as that.

First impressions:

  • no ICQ groups - that sucks - I used to use it a lot
  • aliases of people are retained ('MG Zas' for example) - which is a backup for groups ('group MG -> user Zas' becomes 'MG Zas').
  • Cyrillic characters work fine (if it was working with my other client - Pidgin/Gaim)

Concerning the standalone client - Google Talk - I have no idea if it works there - Google have a pretty wierd update policy - they update silently and only some clients - it sucks.

After all  - it's usable

180° flips with and without help

The last two days I went skiing (well, actually snowboarding) with a friend with which I haven't before and learned some new tricks. Now 180° turns aren't a problem. First the training started with doing (trying to do) turns without jumps (this is really exhausting because a jump alleviates the whole thing - rises you in the air), then little by little I started testing steep jumps with low speed (rises you high without being fast) and it worked.

Some of the turns (when riding on the back edge of the board) can be done in an easier manner when part of it is touching the snow while turning - it looks like doing half a circle. This way if there's some unevenness it can be used to help lift the board.

The whole thing took a lot more energy than usual, because of all the jumping and falling down. Now I have muscle aches all over my body, but it was worth it.

There are no pictures because it's hard to take some with two pairs of gloves and wrist-protectors in the middle.