EJB Sucks: one more reason why

I'm trying to like the specification, but I just can't.
Here's one more reason why:

I have SSB (Stateless Session Beans). The persistence is via JPA (implementation is Hibernate).

All my business method look something like:


...
public Object1 doSomething( Object2 ) throws ApplicationException1;
...

I use CMT (Container Managed Transactions) which means that the container calls begin() before the method call and commit() after the method call is over.

The problem: what happens if the transaction is rolled back?

A RollbackException is thrown. It looks common sense to try to rewrite it as ApplicationException1. Well.... YOU CAN'T.

No F way (at least not an easy one).

Solution1:
Make the Beans stateful and use SessionSynchronization. UGLY - I don't want to be stateful.

Solution2:
Implement TransactionSynchronizationRegistry - just look at it.

Solution3:
Make a facade EJB that calls my own EJBs which should use requiresNew. One more level of abstraction? I have to change the contract? I don't have just one Bean, so a wrapper for every single one of them?

Solution4:
Switch back to BMT (Bean Managed Transactions) and call begin() and commit() myself. Well then the container becomes useless. But my business methods are rarely longer than a few lines, so I'm choosing this one.

CMT without any simple way to plug after commit() and this is an enterprise level spec? Really?

I'd be really happy if someone corrects me and shows me a simple way to do what I need.

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.

MySQL sucks: one more reason

MySQL is a RDBMS. Or at least that's what it's creators claim it to be.

There's no other self respecting database who's only engine that implements transactions (innoDB) is not created by MySQL guys. Only until recently their own engine claims to support them. Even small in-process databases like Hypersonic and Derby fully support transactions from version one. Flawlessly.

Today I found one more reason for which I think MySQL should not be put under the category RDBMS:

Caused by: java.sql.SQLException: Too many tables; MySQL can only use 61 tables in a join
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2975)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1600)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1695)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:3026)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1137)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1231)
        at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:236)
        at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1787)
        at org.hibernate.loader.Loader.doQuery(Loader.java:674)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)

Until recently the maximum was only 31 table. A major WTF?!

I would gladly bet that Hypersonic and Derby do not have a constraint like that (haven't investigated it though).

The stack trace is intently complete to show that this comes from Hibernate. This can be reproduced by having a rich object model with EAGER fetching.

Maybe I'll write a little more on the EAGER fetching and the issues I have: here.

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.

ICQ in GoogleTalk web client (gmail) - revised

What I wrote so far:

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

After a week of using it this is what I noticed:

  1. Cyrillic doesn't always work with everybody, sometimes UTF-8 comes as cp-1251, even though the browser is in UTF-8.
    1. However, when I write, everybody sees it correctly.
  2. No way to give authorization to people, no way to ask for one.
  3. No way to see user info. No way, really.
  4. Some of my peers receive everything in html. It's hard to chat with them.
    1. I guess people without the official client.

After all - it's still usable, but I'm not going to recommend it to any more.

[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 🙂

Старата фонетична за Виста

(Само и само да си вдигна рейтинга в Гугъл...)

Както всички, които са ползвали поне малко Windows Vista, са забелязали
- няма я старата фонетична подредба. Аз лично я ползвах доста. Вместо
нея има сложена една "стандартизирана от БАН" фонетична подредба, на
която обаче няколко букви са разместени. Примерно Ж е на мястото на W,
което на мен не ми харесва.

Имаше някъде спор из нета относно коя да бъде - старата или новата, но ме мързи да търся.
Аз
си харесвам старата и открих един инструмент от Майкрософт (тук ще ги
похваля), с който сравнително лесно могат да се пренаредят клавишите
(едно време имаше нещо подобно във FlexType (моля ви, не си слагайте
FlexType - Инженерът ще се кара)).
Инструментът се казва Microsoft Keyboard Layout Creator. Работата с този инстурмент не е толкова елементарна колкото изглежда, аз няколко пъти оплесквах нещата.

Та а използвайки тоя инструмент си направих фонетична подредба.

Update: във фонетичната на БАН забелязах нещо интересно: Shift + ь = ѝ.
Тоест малка оптимизация. Ер малък се използва само като малка буква.
Главна такава буква в Българския език няма. На мястото на главната
буква те са сложили "и с ударение". И с ударение също няма главна
буква, тоест ѝ трябва само една позиция на клавиатурата. За "и с
ударение" имам малко инфо тук.
Та аз реших да направя същата оптимизация и направих нова версия на класическата фонетична за Виста.

Инструкции за инсталация:

  1. от zip файла с инсталатор цъкнете на setup.exe, следвайте инструкциите.
  2. Клавиатурата сама се "пъха" в активните, така че веднага е готова за употреба.
  3. Ако
    все пак искате да цъкате ръчно разни неща: "Regional and Language
    Options" в Contol Panel -> "Keyboards and Languages" -> "Change
    keyboards..."
  4. Фонетичната на Виста/БАН се казва "Bulgarian (Phonetic)", моята излиза като "Bulgarian (Phonetic) - REAL"
  5. Ако
    имате старата ми версия инсталирана, по-добре я махнете, тъй като и
    старата и новата излизат с еднакво име. В списъка с инсталирани
    програми се различават по версията, обаче.

Поддържани хардуерни платформи: i386 (32 bit), ia64 (64 bit), amd64, wow64 (дори не знам какво е това).

Това е фонетичната подредба за Windows Vistа (в архива има инсталатор):
Bulgarian (Phonetic) - Old School (by Mihail Stoynov).zip (253.38 KB) (без оптимизацията за "и с ударение")
Bulgarian (Phonetic) - Old School (by Mihail Stoynov) v2.0.zip (252.92 KB) (с оптимизацията за "и с ударение")

Ето и самата подредба (ако някой иска да си играе с нея, не е никак елементарно):
Bulgarian (Phonetic) - Old School (by Mihail Stoynov).keyboard layout.zip (2.26 KB) (без оптимизацията за "и с ударение")
Bulgarian (Phonetic) - Old School (by Mihail Stoynov) v2.0.keyboard layout.zip (2.33 KB) (с оптимизацията за "и с ударение")

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