Will @CleanupUsingScript and @ApplyScriptXXX support multiline scripts?
jfrenetic Aug 30, 2012 6:20 PMRecently I've bumped into issue related to running scripts with APE annotations @CleanupUsingScript and @ApplyScriptXXX (which are effectively synonyms).
Suppose, I have the following script:
cleanup.sql
DELETE FROM PEOPLE DELETE FROM GROUPS
Running this simple test on Glassfish 3.1.2 and Apache Derby DB:
@Test @CleanupUsingScript(phase = TestExecutionPhase.AFTER, value="cleanup.sql") @UsingDataSet("init_people.xml") @DataSource("jdbc/MyPool") public void test() { }
results in the following exception:
org.jboss.arquillian.persistence.data.dbunit.exception.DBUnitConnectionException: Unable to close connection. at org.jboss.arquillian.persistence.data.dbunit.DBUnitPersistenceTestLifecycleHandler.closeConnection(DBUnitPersistenceTestLifecycleHandler.java:92) ... Caused by: org.jboss.arquillian.core.spi.InvocationException: org.jboss.arquillian.persistence.data.dbunit.exception.DBUnitDataSetHandlingException: Unable to execute script: DELETE FROM PEOPLE DELETE FROM GROUPS ... Caused by: org.jboss.arquillian.persistence.data.dbunit.exception.DBUnitDataSetHandlingException: Unable to execute script: DELETE FROM PEOPLE DELETE FROM GROUPS at org.jboss.arquillian.persistence.data.dbunit.DBUnitDataHandler.executeScript(DBUnitDataHandler.java:158) at org.jboss.arquillian.persistence.data.dbunit.DBUnitDataHandler.cleanupUsingScript(DBUnitDataHandler.java:131) ... Caused by: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "DELETE" at line 2, column 1. at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source) ... at org.jboss.arquillian.persistence.data.dbunit.DBUnitDataHandler.executeScript(DBUnitDataHandler.java:154) ... Caused by: org.jboss.arquillian.test.spi.ArquillianProxyException: org.apache.derby.client.am.SqlException : Syntax error: Encountered "DELETE" at line 2, column 1. [Proxied because : Original exception not deserilizable, ClassNotFoundException]
It's very obvious, because looking at the source of DBUnitDataHandler#executeScript you can see this:
private void executeScript(String script) { Statement statement = null; try { statement = databaseConnection.get().getConnection().createStatement(); statement.execute(script); } ...
So, the entire contents of a script is treated as one String. Why?
Can't something like ScriptRunner be used here?
Personally, I had to tweak it this way for my project:
for (String str : script.split("\r\n")) { statement.execute(str); }
I know, this is not ideal, but it works for me. I see no reason in using scripts with just one statement.
If you looked closer at the stack trace, you might have noticed another problem.
Take a look at the source code of DBUnitPersistenceTestLifecycleHandler#closeConnection
public void closeConnection(@Observes(precedence = 1000) EventContext<AfterPersistenceTest> context) { try { context.proceed(); databaseConnectionProducer.get().getConnection().close(); } catch (Exception e) { throw new DBUnitConnectionException("Unable to close connection.", e); } }
Why is the connection closed inside try, not the finally block? Isn't it the potential source of resources leak?