When developing a tiered Java EE database application there are a tremendous number of program errors that will only be discovered at runtime. If one is using Hibernate as the Object-relational mapping tool, even JPQL queries embedded within your Java application will (likely) pass Java compilation because the syntax and semantics of the JPQL query isn’t checked at compile time, but only at runtime when the Hibernate JPA library attempts to convert the JPQL query into an SQL query for the specific DBMS used by the application. In my case, recently that database has been Oracle 12c but the same principle applies to any DBMS.
Two things in particular exacerbate the runtime error issue when working with Java EE. First are the heavy use of Java annotations (or XML files if you like to avoid annotations) for configuring the interactions between the Java application, the ORM mapper (in my case, Hibernate), and the underlying DBMS. Second is the (certain) requirement to use native SQL queries within your application, because it will be the rare application that doesn’t require either (a) an SQL language feature that Hibernate does not support, such as outer joins over derived tables, or (b) a more streamlined, set-oriented result set, such as one that uses SQL analytic functions, that return a concise result from the server in a single SQL request.
I’ve written about using native SQL queries with JPA and Java annotations previously; a recent blog post by Lukas Eder nicely outlines the issues with native queries and JPA. However, these problems exist even for JDBC applications since (again) there is no compile-time checking of SQL queries.
Consequently, one usually goes through many compile/run/debug cycles in developing a Java EE database application. For this reason it is essential to ensure that the majority of your program code executes within Java try/catch blocks, and that when exceptions are thrown then an indication of the error is output. When using GlassFish as the application server, the server’s log files (by default in the C:\glassfish4\glassfish\domains\domain1\logs directory) will contain any error stack traces generated by printStackTrace() methods from anywhere within your application.
Another error that can come up is a known out-of-memory condition with the Java VM, caused by a memory leak in the class loader when deploying Java EE applications to GlassFish repeatedly. When using Eclipse to deploy the application, the error can manifest itself in a couple of different ways, but the end result is that the deployment will fail and it may not be obvious within Eclipse’s IDE that the PermGen error has occurred. However, a look at the GlassFish server’s current log file will normally confirm the problem:
1 2 3 4 5 6 7 8 9 10 11 12
[2015-08-25T13:05:27.893-0400] [glassfish 4.1] [WARNING]  [javax.enterprise.ejb.container] [tid: _ThreadID=27 _ThreadName=http-listener-1(1)] [timeMillis: 1440522327893] [levelValue: 900] [[javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean: java.lang.OutOfMemoryError: PermGen space at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionClientTx(EJBContainerTransactionManager.java:665) at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507) at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566) at com.sun.ejb.containers.StatefulSessionContainer.postInvokeTx(StatefulSessionContainer.java:1853) at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074) at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044) at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220) at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88) at com.sun.proxy.$Proxy398.open(Unknown Source)
The workaround is to simply bounce the GlassFish server, easy to do from within Eclipse using the “Servers” view.
Alas, inconsistencies with SQL queries from within a Java EE application aren’t the only source of runtime errors for developers; there are others. More on another class of such errors in my next post.