I recently helped a customer tune a slow JPQL query. It turned out to be at least partially due to Hibernate’s implementation of fetch joins. The problem is generic, so it is a good thing to be aware of.
The query was supposed to return entities one page at a time and several relations, including collections, had to be initialized. That was done using fetch joins in order to keep the number of database round-trips down.
When I checked the SQL statement I quickly noticed that it had no LIMIT clause. Hibernate normally uses the LIMIT clause with MySQL for paging, but not this time. Why?
The specification for JPA 1 (JSR 220) states that the effect of applying setMaxResults or setFirstResult to a query involving fetch joins over collections is undefined. Hibernate fetches the records and performs paging in memory, not in the database. As this tends to be expensive, a warning is logged:
WARNING: firstResult/maxResults specified with collection fetch; applying in memory!
Well, that was clear enough. But why? Poor thinking? No, rather a difficult problem. Hibernate wants to get a certain number of entities per page, not a certain number of database rows. With fetch joins for collections there is no way to know how many database rows to get for one entity, so what to do? Read database rows and pile them up in memory until the page size has been reached (including pages that have been visited before and are not returned for this request). At least that works.
So, as the specification and the Hibernate documentation advises, stay clear of fetch joins for collections if you want to use paging (or the other way around)!
This is the presentation for my session at JavaOne 2013, complete with footnotes.
At JavaOne I used the small travel wall with 6 Raspberry Pi units. A pity I couldn’t bring the full-scale wall with 48 units, but the small one was also quite popular with the crowd, both at JavaOne and on the streets in San Francisco. Many people and one mascot stopped me and wanted to know more about it.
If you haven’t already, check out JBoss Forge. I attended a session at JavaOne where it was used to build a Java EE application with JPA database access, a REST interface and a JSF web interface in less than 50 minutes. Sure, the speaker used prepared scripts for many tasks, but even so it was impressive – like Rails but for Java. And there are no JBoss dependencies in the generated code.
JavaOne 2013 is in full swing and I’m in the middle of it. As usual the days are crammed with sessions with little or no time for anything else (such as lunch – so thanks for the peanuts, OTN!).
My favourite Monday session was CON7859 (The Road to Lambda). It provided a good overview of the design underpinning the long awaited lambda language feature due in Java SE 8. The developers have really done a great job, adding the new feature with a natural syntax and without breaking existing code. I didn’t like inner classes when they were introduced, as they made the language more complex, but this time the change feels right. I can hardly wait for the final version to be available from OTN.
It was also quite interesting to see BOF7786, demonstrating how to create a supercomputer with Hazelcast, 48 Raspberry Pi units and lego. It overlaps CON4177, which I will present on Thursday, where we are using a wall with 48 Raspberry Pi units for load tests. Many similarities, but also some differences.
Hope to see you at JavaOne!
As I found out the hard way several years ago the documentation for Oracle’s FTP adapter in SOA Suite 10.1.3 does not match the code. For public key authentication with ssh-dsa the preferredPKIAlgorithm property should be set to ssh-dsa according to the documentation, but the code expects ssh-dss. It turns out that this bug remains in 220.127.116.11. The documentation still insists on ssh-dsa and the code steadfastly uses ssh-dss. Some things never change.
The latest supported Java version from Oracle for the Rasperry Pi (as of this writing) is Java SE 7 Embedded for Linux/ARM. It requires a license and it supports only the somewhat dated soft-float image. Anyone using it must stick with soft-float for now. Unfortunately recent versions of the Raspberry Pi fail to boot with the soft-float image! We got a batch where some units worked and some failed. Personally I think that a hardware change that breaks compatibility with old software should be branded as a new revision, but with the Raspberry that has not happened.
Fortunately there is a workaround. The newer hard-float images work and the Linux kernel in the soft-float image works as well. Copy the three files bootcode.bin, start.elf and fixup.dat from the boot partition of the latest hard-float image to the old soft-float image and the problem is solved.
Credits to StackOverflow for the solution. Please note that simply copying start.elf is not enough, all three files are needed.
There are several possible Java engines for the Raspberry Pi, but it is not trivial to pick the right one. Oracle’s Java versions are the fastest by far, but they are not free. Oracle Java SE 7 Embedded for Linux/ARM requires a license and it supports only the old soft-float version of Raspbian, not the newer hard-float version. Oracle Java SE 8 Embedded supports hard-float and is the fastest option, but it is still in preview and may not be used in production at all.
OpenJDK is free, supports hard-float and is easy to install, but it is much slower (see chart).
The test case is fairly simple (generate random numbers and compute their MD5 sum), but the results match other tests. Personally I would go for OpenJDK with Avian or one of Oracle’s Java versions, depending on the situation. Hopefully Java SE 8 will be released soon and without the need for a cumbersome license…
EDIT: With a more realistic and long-running test case Avian ran into problems. This illustrates the problem with micro-benchmarks. Be sure to test with real-world code before making a choice! Oracle’s JVM is still the fastest. The test measures the number of business transactions completed per minute.