Hi Trejkaz,
I can reproduce your results if my UserAuthenticator throws a
SQLException whose SQLState is 08004, one of the SQLStates reserved for
use by Derby. If my UserAuthenticator throws a SQLException whose
SQLState is ZZZZZ, a state not reserved by Derby, then the exception
traverses the network correctly and is seen by the client application.
Here is a sample program showing the success case:
import java.sql.*;
public class ZZ
{
public static void main( String... args ) throws Exception
{
try {
Connection conn = DriverManager.getConnection
(
"jdbc:derby://localhost:8246/memory:db;create=true;user=foo;password=bar" );
}
catch (Throwable t) { printThrowable( t ); }
}
private static void printThrowable( Throwable t )
{
if ( t == null ) { return; }
println( "\nThrowable is a " + t.getClass().getName() );
println( " message = " + t.getMessage() );
if ( t instanceof SQLException )
{
SQLException se = (SQLException) t;
println( " SQLState = " + se.getSQLState() );
printThrowable( se.getNextException() );
}
printThrowable( t.getCause() );
}
private static void println( String text ) {
System.out.println( text ); }
}
...and here is the UserAuthenticator I used:
import java.sql.SQLException;
import java.util.Properties;
import org.apache.derby.authentication.UserAuthenticator;
public class Z implements UserAuthenticator
{
public Z() {}
public boolean authenticateUser
(
String userName,
String userPassword,
String databaseName,
Properties info
)
throws SQLException
{
throw new SQLException( "I can't do that, Dave.", "ZZZZZ" );
}
}
Hope this helps,
-Rick
On 4/26/12 10:09 PM, Trejkaz wrote:
On Mon, Apr 23, 2012 at 10:50 PM, Rick Hillegas
<[email protected]> wrote:
UserAuthenticator.authenticateUser() can throw a SQLException which explains
that the user doesn't have access to the given database. I find that
SQLExceptions raised by the following code reach the application:
[snip]
I just gave this a shot, but it doesn't appear to work, at least not
over the client-server connection.
I tried it using a mock authenticator:
mockery.checking(new Expectations() {{
oneOf(authenticator).authenticateUser("bob", "bob",
dbDir.getAbsolutePath(), new Properties());
will(throwException(new
SQLNonTransientConnectionException("Database access denied for user
bob", "08004.C.3")));
}});
Then when I connect to the database, I do get back SQLState "08004",
but it's "08004.C.1" with a different error message to the one I
returned. My initial guess would be that Derby swallows the
authentication exception on the server side, sends some kind of error
code over the wire and then the client driver propagates a brand new
exception to the application.
TX