Tuesday, November 27, 2007

Extending the transaction boundaries beyond the EJB layer

A recent e-mail from a reader gave me the chance to write this post about transaction boundary extension. The configuration used is jboss 4.2.2, ejb3/jpa(over hibernate) with stripes as the web tier. Session bean methods that return pojos to the web tier always return detached objects.This is because the automatic transaction management starts the transaction when you call a session bean method and commits the transaction (and closes the associated hibernate session) when the session bean method returns. This means that you have to initialize every lazy field that you may use in the view layer, otherwise a lazy loading exception is waiting for you around the corner. One solution, therefore, is to initialize the lazy fields and do a very good design of your API taking care to return correctly initialized objects for each of your views. Another "lazy" solution is to extend the transaction boundary to the view layer thus keeping the peristence context active throughout each http request. This seems wrong at first glance (it violates layering !!!!), but for small applications I don't think that might be a problem. Nevertheless, each http request completes very quickly so that the transaction is not extended for large periods of time.

One way to do this extension is to use a servlet filter that manages the transactions at the request boundary.

public class TransactionFilter implements Filter {

    /**
     * Logger for the class
     */
    private final static Logger logger = Logger.getLogger(TransactionFilter.class);

    /**
     * @param request The request that we serve
     * @param response The response that we create
     * @param chain The chain of other filters that may have been defined
     * @throws IOException wraps any I/O related exception thrown during
     *             processing
     * @throws ServletException wraps any exception thrown during processing
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            UserTransaction utx = null;
            try {
                Context ctx = new InitialContext();
                Object ref = ctx.lookup("UserTransaction");
                utx = (UserTransaction) PortableRemoteObject.narrow(ref, UserTransaction.class);
                utx.begin();
                chain.doFilter(request, response);
                int status = utx.getStatus();
                if (status == Status.STATUS_ACTIVE)
                    utx.commit();
                else
                    utx.rollback();
            }
            catch (Throwable e){
                try {
                    if ((utx != null) && (utx.getStatus() == Status.STATUS_ACTIVE))
                        utx.rollback();
                }
                catch (Throwable e1) {
                    logger.error("Cannot rollback transaction", e1);
                }
                if (e instanceof ServletException)
                    throw (ServletException) e;
                if (e instanceof IOException)
                    throw (IOException) e;
                if (e instanceof RuntimeException)
                    throw (RuntimeException) e;
                throw new ServletException(e);
            }
        }
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig arg0) throws ServletException {
    }
}


The filter begins a transaction at the beginning of each http request and commits at the end. Each call to session bean methods has already an active transaction associated so the session bean does not start a new one (if it is configured with TransactionAttribute REQUIRED). Thus the transaction and the associated hibernate session are active throughout the request and we can use the pojos in the action classes (struts, stripes) or in jsps without caring about uninitialized lazy fields.

Don't forget to configure the filter to intercept every request associated with the view layer e.g.

    <filter-mapping>
        <filter-name>TransactionFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>


    <filter-mapping>
        <filter-name>TransactionFilter</filter-name>
        <servlet-name>StripesDispatcher</servlet-name>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

Sunday, November 11, 2007

Welcome (back) to Stripes

A couple of weeks ago, we started an extension to an old project. It was one that started in 2004 if I remember correctly and went through several rounds of extensions (the customer is happy and constantly asks for new features :-)). The technology behind it was servlets with a custom template engine for the web tier, stateless session ejbs for the business tier and the dreaded CMP Entity EJBs for the data tier. This time, we thought that it 's a good idea to spice things up a little bit. "Why don't we use hibernate at least for the new functionality?" we asked ourselves. "Ok, but then why don't we switch to EJB3 too and use injection and other cool features ?". "Oh, and what about the web? Let 's use struts!! Oh, wait a minute. Why not stripes ????".

So here we are, mixing stripes, ejb3 session beans and jpa/hibernate with servlets, ejb2 session bean with CMP entities. It really seems we are looking for trouble but 'till now everything works great. And we did a port from jboss 4.0.5 to 4.2.1. Ok, this is not something to brag about, it was the easiest part.

I will write more about our troubles with this technology party in later posts. I hope not :-)

Monday, September 17, 2007

Fame

This post is not about java. At least not strictly. I was wondering the other day why I read the blogs that I read (and I read quite a lot as you can see on the right). Why do I read Jonathan Schwartz's Weblog ? Why Neal Gafter's blog ? Why Paul Buchheit ? Do I read them because they write nice things ? Maybe. But how did I know it when I started reading them ? Did someone recommended them to me? True, but why I cared ?

The answer is I read them because they are famous. Jonathan Schwartz is the CEO of Sun. Neal Gafter works at Google (Google Calendar I think) and on closures for java, Paul Buchheit is also at Google (Gmail, AdSense). Their fame is the reason I cared to subscribe to their feeds. Their smart posts maybe is the reason I keep reading them but the fact that they are very well known is the reason I started looking at their blogs. Of course I read some of my friends 's blogs and they are not famous. I didn't say that I read only the blogs of the famous.

So the next question is: why are they famous? Is it because they write blogs ? Is it because they have written books ? Of course not. They are famous because they did something great. Blogs and other stuff came later. They first created something great, something big. This is what they are known for.

When I started this blog I wanted mainly to create an archive of the solutions I give to problems in my everyday job as a programmer. But in the back of my mind I also had the thought that the blog is a good way to be known for what I do. Ok, now I don't think so. As a matter of fact, what I do is not something that I 'm worth being known for. What I do is using the technology and the great things that others have created. Maybe the visitors that come here through a search in Google for "hibernate troubles" will remember me for some time but this definitely does not make me famous.

My advice: If you want to become famous do something great. Then you can start a blog about it.

Monday, August 6, 2007

Friday, June 1, 2007

This one is for Amalia…

"Every patient has the right to being respected and maintaining his dignity."
(Greek law, article 47, L.2071/1992)

"Quacks should be the exception, you guys, not the norm…"
(Amalia Kalyvinou , 1977-2007)

Since the age of 8, Amalia Kalyvinou started having pains. Despite her numerous visits to doctors and several admissions to hospitals, no-one managed to diagnose her in time with the benign neurinoma of her lower extremity, which was the actual diagnosis at that point. 17 years later, Amalia was told that the neurinoma had transformed by then into a malignant tumour.

For the next 5 years, Amalia not only had to fight with the cancerous disease and amputation, but also with a corrupt Greek National Health System: it ignores (by choice) the ongoing patient-to-doctor bribery and insists on time-consuming bureaucratic methods and practices. Besides radiotherapy and chemotherapy, Amalia had to face the financial exploitation by doctors that stood opposite to rather than by her side. On top of her pain, she had to endure the greediness of private clinics and the exhaustingly long waiting queues of the health insurance system, in order to get legal approval for some ridiculously low financial compensation.

Amalia passed away on Friday, May the 25th, 2007. She was just 30 years old.

Before dying, she managed to document her experience and share it with us in her blog http://fakellaki.blogspot.com. The promising literature graduate named in there each and every one of the doctors she had to bribe, praising at the same time the ones that honoured the Hippocratic Oath. Her testimony moved thousands of people that stood by her side all the way to the end.

"Amalia's main aim was to tell her story, so that she could awaken as many people and as many consciences as possible. She mainly wanted to show that there are ways to resist not only the self-regulation and authority of dishonest and heartless doctors, but also the bureaucrats of the Health System."

(Dikaia Tsavari & Georgia Kalyvinou – Amalia's mother & sister)


According to the Greek law, it is considered a major disciplinary offence for the doctors of the Greek National Health System to:

"Accept bonus and especially any compensation or property grant, for any medical service provided.”

Amalia Kalyvinou fought for things that are taken for granted in a modern European country. Unfortunately, this is not the case for Greece. Continuing Amalia’s effort where she left off, we protest in public and we demand:


* THE STATE TO TAKE IMMEDIATE ACTION TO STOP BRIBERY AND THE INEQUALITY BROUGHT IN THE TREATMENT OF PATIENTS.

* THE NATIONAL HEALTH COMMITTEE TO BE MORE FLEXIBLE SO AS PATIENTS STOP FALLING VICTIMS TO TIME-CONSUMING BUREAUCRATIC PROCESSES.

* THE DEPARTMENT OF HEALTH TO ENSURE STRICTER CONTROL ON THE RELATION OF DRUG COMPANIES – MEDICAL SERVICE.

* FULL UTILISIZATION OF CURRENTLY ABANDONED HOSPITAL INFRASTRUCTURE. CONTINUOUS AND COMPLETE SCIENTIFIC TRAINING & DEVELOPMENT FOR DOCTORS AND NURSES.

* CREATION OF A NATION-WIDE ELECTRONIC MEDICAL RECORD SYSTEM, TO SPEED UP PROMPT DIAGNOSIS AND TREATMENT

LET’S END THE HYPOCRISY OF THE ONES THAT GOVERN, WHO PREFER TO ALLOW DOCTORS TO BE BRIBED BY THEIR PATIENTS, INSTEAD OF PROVIDING THEM WITH A DECENT SALARY.


* NO MORE BRIBERY
* NO MORE BUREAUCRACY
* NO MORE LIES

WE DEMAND FREE AND EFFICACIOUS HEALTHCARE SERVICES FOR ALL.

Next time you’ll have to bribe a doctor, just don’t. Choose instead to make a donation. Amalia’s last wish was to contribute to the -under construction- Oncological Centre for Children. (Elpida foundation, tel no 0030210-7757153, email: info@elpida.org, Bank accounts: National bank of Greece, account no 080/480898-36, Alphabank account no 152-002-002-000-515. Please remember to quote that your donation is “for Amalia”)

INTERNET MOVEMENT OF AMALIA’S FRIENDS

Saturday, May 26, 2007

Annoying warnings

If you are annoyed by warnings about unchecked conversions and the
@SuppressWarnings("unchecked") seems too broad (you have to annotate a whole method for just a line of code) this has an interesting suggestion. Interesting java syntax, too.

Tuesday, May 22, 2007

All about singletons

This is a little bit old but quite thorough article about singletons. It addresses all singleton issues with concurrency, classloading and serialization. However, the fourth implemention of a thread-safe singleton (Example 7) misses the lazy-loading requirement (the singleton instance is not created when first accessed but earlier at class loading). This article gives a different implementation that is both thread-safe and lazy-loaded and this explains why. See also the discussion here.

Thursday, May 17, 2007

Field access vs Property access in JPA

JPA allows for two types of access to the data of a persistent class. Field access which means that it maps the instance variables (fields) to columns in the database and Property access which means that is uses the getters to determine the property names that will be mapped to the db. What access type it will be used is decided by where you put the @Id annotation (on the id field or the getId() method).

I have developed a preference for field access mainly for two reasons. First, because I frequently define getter methods that are not property accessors e.g. a getter that does not just return the value of a field but does a calculation and returns the result. In that case (and if you use property access) you have to annotate the getter with @Transient. If you forget to do this (as I did many times) you are looking for trouble. JPA will think that the getter corresponds to a property and funny things will happen.

The second reason I prefer field access is that with property access you have to define getter methods for every field just for use by JPA even if your code will never call them.

Until now I haven't find any argument in favor of property access but I would like to hear if anybody has.

Wednesday, May 2, 2007

Transaction management and JPA

My current project is a web application with Struts in the web tier, a stateless session ejb (EJB3) in the middle tier and various entity pojos (JPA) that model the data. The application server is Jboss 4.2.0.CR2 that uses Hibernate as the persistence provider.

In this configuration with container-managed transactions, the transaction boundary is the ejb method call. Struts action classes make calls to the session ejb methods in order to retrieve data for display in various jsps. The problem is that after the ejb method returns, the transaction is over, the persistence context has ended and the pojos returned are detached. If the jsp that displays the data tries to access any lazily loaded associations an exception occurs. One solution might be to load every association eagerly but this could become very expensive in terms of performance and is definitely not scalable. Another approach might be to write different ejb methods that initialize the associations needed in different views but this will make the API between the web and middle tier very complicated.

What I finally did was borrowed by Hibernate. Hibernate suggests the use of the HibenateUtil class that manages transactions and is called usually in an HttpFilter. In this configuration the transaction boundary is the http request. In my case, I extended the Struts RequestProcessor and overridden the process method.


public class MyRequestProcessor extends RequestProcessor {
    private static Logger logger = Logger.getLogger(MyRequestProcessor.class);
  
    private static final ThreadLocal<UserTransaction> threadTransaction = new ThreadLocal<UserTransaction>();

    @Override
    public void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        UserTransaction utx = null;
        try {
            utx = threadTransaction.get();
            if (utx == null) {
                Context ctx = new InitialContext();
                UserTransaction utx = (UserTransaction) ctx.lookup("UserTransaction");
                threadTransaction.set(utx);
                utx.begin();
            }
            super.process(request, response);
            utx.commit();
        }
        catch (Exception e){
            try {
                if (utx != null)
                    utx.rollback();
            }
            catch (Exception e1) {
                logger.error("Cannot rollback transaction", e1);
            }
            throw new ServletException(e);
        }   
        finally {
            threadTransaction.remove();
        }
    }
}

At the beginning of the processing the UserTransaction is initialized and after the processing it is committed. If an exception happens it is rolled back. By using this approach we make sure that the transaction and the persistence context are active after the ejb method returns and during the action and jsp execution thus enabling us to traverse association from inside the jsps. This approach has a problem though. If a forward is done from a struts action to another the request processor is called again in the same thread and thus the transaction will be committed twice (once per request processor call) resulting in an exception in the second attempt to commit. This can be resolved by use of some flag that marks the outermost call, so that we do the commit only there.

Another approach would be the use of an http filter that begins and commits the transaction thus moving the transaction boundaries at the http request.

All the above approaches do not make any reference to Hibernate classes so the implementation is persistence provider agnostic.

Thursday, April 19, 2007

Where is "delete-orphans" ?

A Customer has a shopping cart with OrderItems in it:

public class Customer {
    ...
    @OneToMany(cascade=CascadeType.ALL)
    private Set<OrderItem> cart;
    ...
}


What happens if one removes an OrderItem from the cart ? As I noticed today, the item no longer belongs to the customer 's cart but unfortunately still remains in the database as an orphan record.

Ok, let's set the cascade type to all-delete-orphans (like in hibernate) so that orphans get automagically deleted. Not so easy, though. JPA (JSR-220) does not support the "delete-orphan" feature of hibernate and other persistence providers. What can one do? Either use a hibernate specific annotation (other persistence providers like TopLink have similar features) to declare the cascade as delete-orphan or delete the orphan entity programmaticaly (after removing it from the Customer 's collection).

Personally, I chose the second approach as the first ties the application with the specific persistence provider (hibernate in my case).

Friday, April 13, 2007

ORA-00907: missing right parenthesis

What follows is not new. It is very well known by jboss+hibernate users and a lot of info can be found at jboss and hibernate forums. Anyway, it took me almost four hours to clean up the mess so I think it is suitable for this blog (for those who have not realized yet, this blog is mostly about my troubles in the java world). So here it goes:

I was trying to configure a many-to-many relation between documents and document bodies. Each document has a collection of bodies, where each body represents a different translation, so each body corresponds to a different language. Each body on the other hand can belong to many documents, thus making the relation many-to-many. On top of this configuration, I wanted to access the bodies of a document by their language id so the map-based solution seemed ok:

public class MyDocument {
    ...
    @ManyToMany
    @MapKey(name="langId")
    private Map<Integer, MyDocumentBody> bodies;
    ...
}

The bodies Map is keyed by the integer language id.

Unfortunately, due to this bug, hibernate generates illegal sql for Oracle, when trying to initialize the bodies Map. To be more specific, it uses a table alias in the FROM clause but it puts the "AS" keyword in front e.g.:

select * from TableA as a where blah, blah

The "as" is optional but acceptable by many databases. However it is not acceptable by Oracle, as it is explained in the links mentioned above. As I found here the generation of "as" is due to a bug in annotations and the upgrade to hibernate-annotations 3.3.0.GA is suggested. However, the use of this version requires an upgrade of the hibernate-entity manager to version 3.3.x as the compatibility matrix suggests. My troubles didn't end at this point though, because I was using jboss-4.0.5.GA whose EJB3-JPA support is not compatible with the new hibernate-entitymanager. The upgrade to 4.2.0.CR1 seemed inevitable (this has a better EJB3 support but the hibernate-* jars still needed upgrading). Alas, a java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager was waiting for me during deployment. Another google search and this finally solved my problem. hibernate-annotations-common.jar, which is not included in jboss by default, was needed in the lib folder. Four hours and a lot of googling later, I had my map-based many-to-many relation.

Thursday, April 12, 2007

Deploying an EJB twice ... :-)

OK. I know that what follows is a terrible mistake. Actually I knew it from the very beginning but I was curious to see what would happen. Here is how it goes: Two web applications were running on jboss for some years on two separate machines in the client 's data center. For ease of management, some time ago, the client requested that the two applications should be deployed on one machine with a single instance of jboss. No problem, I thought at first. After installing jboss 4.0.5 on the new machine and testing the two apps separately, it was about time to put them together. In the past we had some problems with such deployments if the two apps were using common libraries. Jboss documentation suggests that if you have two .ear files that include the same jars, a good practice is to remove the duplicate jars from the ear files and put them in the jboss 's lib folder. Another approach is to set

<attribute name="Isolated">true</attribute>

in the ear-deployer.xml file located in the deploy folder. This means that each ear has its own class loader isolated from other deployments and therefore each ear can have the same jars with the other without conflicts such as ClassCastException, LinkageError, etc.

The problem in our case was that the two web apps were using a unique id generator implemented as a session EJB (let 's call it UniqueIDEJB). This EJB had been developed internally years ago, it was packaged in a jar along with all the necessary deployment descriptors and nobody wanted to mess with it. The first ear that contained the UniqueIDEJB was deployed without problems but when the second app was deployed an error occurred indicating that the UniqueIDEJB was already registered in the jndi under the same name.
No problem, one might think. Just deploy the second instance under a different jndi name. After all, that is what deployment descriptors are for. Remember though that nobody wanted to mess with the legacy EJB, so we chose to remove to jar containing the EJB from the two ear files and deploy it independently.

At first, all went well and the two apps along with the UniqueIDEJB were deployed successfully. However there still was a jar file containing the client stubs of the EJB that was included in both apps. This should not be a problem due to the class loader isolation that we used, but things turned out differently. It seems that when the EJB is deployed, jboss creates some proxies that implement the remote and home interfaces, but when the web app looks the EJB up in jndi and tries to cast the result to the home interface, this home interface is loaded by a different class loader (the one of the web app), therefore a ClassCastException occurres.

Conclusion: Class loader isolation does not help when an EJB is included in several web apps. What one should do is deploy the EJB outside of any ear file and put the client stubs jar in jboss 's lib folder.

Tuesday, April 3, 2007

Saturday, March 24, 2007

Adventures in hibernate #1

Recently, in one of the projects I am involved, I had to cope with the following situation: Two database tables (TableA and TableB) were mapped to two java classes (ClassA and ClassB) by use of the hibernate orm framework. Those tables had a one-to-many relation from TableA to TableB by use of a single foreign key. In java ClassA had a Set<ClassB> property and ClassB had a ClassA property (a bi-directional one-to-many).

public class ClassA {
...
   Set<ClassB> b;
...
}

public class ClassB {
...
   ClassA a;
...
}

The corresponding mapping in ClassA.hbm.xml

<set name="b">
   <one-to-many class="ClassB">
   <key>
      <column name="a_id">
   </key>
</set>

and in ClassB.hbm.xml

<many-to-one name="a" class="ClassA" column="a_id">

As it is shown, TableB has a column a_id which is the foreign key to TableA. By use of this foreign key hibernate can correctly map both sides of the relation.

A few months after the system had been in production, due to a functionality extension required by the client, a new type of data was introduced that could be modeled as a subclass of ClassB.

public class SubclassOfB extends ClassB {
}


Hibernate provides many ways to map class hierarchies to tables, however the single table per hierarchy method was chosen not only for its efficiency but mainly because it was a requirement that the two types of data (ClassB and SubclassOfB) should be accommodated in the same table (TableB). What further complicated the situation was the requirement that instances of ClassA had to define two sets: one Set<ClassB> and one Set<SubclassOfB>. That was simply because the existing functionality should not be disturbed. Now ClassA had an additional Set in xml mapping

<set name="sb"
    <key>
        <column name="a_id"/>
    </key>
    <one-to-many class="SubclassOfB"/>
</set>

Note that the foreign key column is the same. So we have two one-to-many relations from ClassA to ClassB using the same foreign key column. Big mistake though it didn't look like a problem at first. However, in certain cases, hibernate had a very strange behavior (e.g. trying to get the set of SubclassOfB instances from a certain instance of ClassA was actually returning instances of ClassB belonging to another instance of ClassA thus resulting in WrongClassException errors).

The solution to the above was to use a different foreign key column for the second relation. So the two sets were mapped:

<set name="b">
   <one-to-many class="ClassB">
   <key>
      <column name="a_id">
   </key>
</set>

<set name="sb"
    <key>
        <column name="a_id_new"/>
    </key>
    <one-to-many class="SubclassOfB"/>
</set>

Instances of ClassB had a many-to-one property to the containing instance of ClassA. This property was as well inherited to SubclassOfB and was mapped to the common foreign key. Now that we had two foreign keys, this property was correctly mapped to the first foreign key for ClassB, but for instances of SubclassOfB the foreign key column contained null values (because the relation from ClassA to SubclassOfB was mapped through the other foreign key). So we had two options: First one was to override this property in SubclassOfB and mapped the new one in a new foreign key column, but this was unacceptable because it would destroy the abstraction (we needed that SubclassOfB and ClassB use the same property to go back to ClassA). So we chose to map the existing property in ClassB (that was also inherited by SubclassOfB) to a third foreign key:

<many-to-one name="a" column="a_id_inverse" class="ClassA"/>

So we now have:
-- a foreign key that relates one instance of ClassA to many instances of ClassB
-- a second foreign key that relates one instance of ClassA to many instances of SubclassOfB
-- a third foreign key that models the other direction from ClassB and SubclassOfB back to ClassA

This is certainly a problem for the database administrator but it is the only way to map correctly a double one-to-many bidirectional relation.