GSSCredential

Mark Rotteveel mark at lawinegevaar.nl
Tue Jun 11 14:54:48 UTC 2019


On 2019-06-10 17:06, Douglas Surber wrote:
>> Given using proxies and reflection is very common in JDBC drivers
>> and related tools and libraries (especially with `DataSource`
>> related things), declaring as `requires static` is not an acceptable
>> solution. Declaring with `requires` will be the minimum necessary to
>> ensure proper functionality and the least amount of surprise.
>> Probably `requires transitive` is better as JDBC drivers will need
>> to actually implement this method as well. Otherwise, the driver
>> will need to use `requires static`, `requires` or `requires
>> transitive` themselves; although I have actually not seen
>> modularized JDBC drivers yet so maybe that is of lesser importance.
> 
> As a driver implementer I have no problem with the driver
> module-info.java including 'requires static java.security.jgss'. The
> driver would use 'requires static' so that driver users would not have
> to include java.security.jgss unless they actually used it.

My point was more that the java.sql module at minimum will need to 
declare `requires java.security.jgss` to avoid nasty surprises with 
proxies and reflection. The `requires` dependency isn't inherited, but 
it will at least prevent NoClassDefFoundErrors at runtime as the module 
will be loaded and present.

> Proxying requiring java.security.jgss is a bigger concern. As you say,
> proxying a very common in stacks that use JDBC. I doubt any of our
> customers would care. I have no idea if there are any JDBC users that
> require an absolutely minimal module set and that also use proxying.

I doubt users of JDBC will look to minimize dependencies, but that it is 
all too easy to use that as an excuse not to consider the impact of 
these types of changes.

> Sure this can be just a proprietary extension; there no real necessity
> that it be part of the standard. But from that perspective there isn't
> much need for a JDBC standard at all.In spite of all the
> standardization around SQL, the various databases are all quite
> different. It is hard to write a vendor independent JDBC app of much
> sophistication.

I'd beg to differ, there are a lot of tools that build on the 
foundations of JDBC, and those tools only exists because JDBC offers a 
common API. And JDBC - with all its problems - is one of the better 
database APIs compared with other languages.

> But since we have a JDBC standard. since GSS is itself
> a standard, and since using GSS to authenticate to a database is
> common enough, it seemed reasonable to add GSS support to JDBC. Oracle
> is not the only vendor to want to support GSS. I know SqlServer does
> also. I can't say about other vendors.

I accept that, but then, shouldn't we go all out and also add it to 
DriverManager (DriverManager.getConnection(String url, GSSCredential 
credential)) and to CommonDataSource 
(CommonDataSource.setGSSCredential(GSSCredential) or DataSource 
(DataSource.getConnection(GSSCredential))? Why only to 
ConnectionBuilder? Would repeatedly using it in a data source even work 
(or would that require a different approach)?

If there is such a need, wouldn't ConnectionBuilder be the least 
relevant API to add it?

> Mostly I am disappointed that Jigsaw has such a profound effect on API
> design. Without Jigsaw this question would never have arisen.

Yes, I agree. But I'm also surprised there isn't anything in the 
java.security package (part of java.base) that could serve as a 
parent-interface for GSSCredential or as an alternative way to get 
credentials.

In any case, I don't mind adding this to JDBC, but we will need to 
carefully consider if the module dependency should be `requires` or 
`requires transitive`. I don't think using only `requires static` is a 
good idea.

If we do want to minimize the module dependency to only when it is 
really necessary, then we'll need to look for a more convoluted 
solutions.

Example of such a convoluted approach:

public interface WithGSSCredential {
    void setGSSCredential(GSSCredential gssCredential);
}

Then if implementations want to use it, they would need to implement it 
as an extra interface, and users would need to explicitly unwrap to that 
interface to set it. As implementations that make this explicit choice 
will depend on the module anyway, the reflection or proxy headache will 
go away. Although workable, it wouldn't win a beauty contest.

Or maybe

public interface CredentialSource<T> {
    T getCredential();
}

and in ConnectionBuilder:

    ConnectionBuilder setCredentialSource(CredentialSource<?> 
credentialSource)

and maybe add a simple wrapper around GSSCredential in JDBC, eg

public GSSCredentialSource implements CredentialSource<GSSCredential> {
     private final GSSCredential credential;

     public GSSCredentialSource(GSSCredential credential) {
         this.credential = credential;
     }

     public GSSCredential getCredential() {
         return credential;
     }
}

Alternatively, in ConnectionBuilder, just use

    <T> ConnectionBuilder setCredential(T credential);

This would allow more flexibility (other credential types could be 
used), but these last two solutions lead to an unclear API (or at least: 
unclear expectations).

There are probably better solutions though, but right now, none come to 
mind.

It all comes down to the question: do we care about extending the module 
dependencies of JDBC or not?

Mark


More information about the jdbc-spec-discuss mailing list