Caused by: java.io.NotSerializableException: com.mysql.jdbc.DatabaseMetaData
This will happen when you get hold of java.sql.Connection
or even directly DatabaseMetaData
as instance variable of a serializable class like below.
public class ReportController implements Serializable {
private Connection connection; // BAD!!
private DatabaseMetaData metadata; // BAD!!
// ...
}
You're not supposed to declare and get hold of external resources such as java.sql.Connection
, Statement
and ResultSet
nor its properties as instance variables of a class. You should acquire, use and close them as soon as possible, exclusively within the method local scope. Get rid of those instance variables from the ReportController
bean, move them into method local scope and this problem shall disappear. Only having DataSource
(the server-managed connection pool) as instance variable is OK.
public class ReportController implements Serializable {
@Resource("jdbc/someDB")
private DataSource dataSource;
public void someMethod() {
try (Connection connection = dataSource.getConnection()) { // OK.
// ...
}
}
// ...
}
The <a4j:keepAlive>
isn't exactly the cause of this problem. It just remembers the bean instance in the HTTP session across HTTP postback requests on the same page. HTTP session attributes are inherently usually serialized. This serialization merely triggered and exposed your hidden design problem. Volatile one-time-use resources such as database connection, statement, metadata, inputstream, outputstream, etc are absolutely not supposed to be serializable and hence this exception.
See also: