JDK-8326482 : Inconsistent behavior in com.sun.jndi.ldap.Connection::createSocket
  • Type: CSR
  • Component: core-libs
  • Sub-Component: javax.naming
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11-pool,17-pool,21-pool,22-pool,23
  • Submitted: 2024-02-22
  • Updated: 2024-03-18
  • Resolved: 2024-03-18
Related Reports
CSR :  
Description
Summary
-------

Update the JDK built-in LDAP provider's client implementation to ignore a connect timeout value when a custom LDAP socket factory does not support the creation of unconnected sockets.

Problem
-------

The JDK built-in LDAP provider's client implementation allows to specify a custom socket factory implementation via the `"java.naming.ldap.factory.socket"` LDAP environment property.

Starting from JDK 9, such implementations are required to implement the `"javax.net.SocketFactory"` abstract class.

However, if a connect timeout is specified via the `"com.sun.jndi.ldap.connect.timeout"` environment property and the provided custom socket factory implementation does not implement the `"public Socket createSocket()"` method for creating unconnected sockets, the `"java.io.IOException"` is thrown by this method default implementation, and the LDAP connection attempt fails.

Such behavior contradicts the expectations set up by the following internal documentation in the JNDI/LDAP provider source code:

    "If a timeout is supplied but unconnected sockets are not supported
    then the timeout is ignored and a connected socket is created"

Solution
--------

Change the JNDI/LDAP provider client's internal implementation to ignore the timeout value if the provided custom socket factory implementation doesn't support the creation of unconnected sockets.

Document the following LDAP environment property that can be used to set a custom socket factory implementation:

    java.naming.ldap.factory.socket

Amend documentation of the following connect timeout LDAP environment property to set the expectations related to the custom socket factory implementations:

    com.sun.jndi.ldap.connect.timeout

Specification
-------------

    diff --git a/src/java.naming/share/classes/module-info.java b/src/java.naming/share/classes/module-info.java
    index c4c7a606c6c..11360e88676 100644
    --- a/src/java.naming/share/classes/module-info.java
    +++ b/src/java.naming/share/classes/module-info.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -36,21 +36,31 @@
      * The following implementation specific environment properties are supported by the
      * default LDAP Naming Service Provider implementation in the JDK:
      * <ul>
    + *     <li>{@code java.naming.ldap.factory.socket}:
    + *         <br>The value of this environment property specifies the fully
    + *         qualified class name of the socket factory used by the LDAP provider.
    + *         This class must implement the javax.net.SocketFactory abstract class
    + *         and provide an implementation of the static "getDefault()" method that
    + *         returns an instance of the socket factory. By default the environment
    + *         property is not set.
    + *     </li>
      *     <li>{@code com.sun.jndi.ldap.connect.timeout}:
    - *         <br>The value of this property is the string representation
    - *         of an integer representing the connection timeout in
    - *         milliseconds. If the LDAP provider cannot establish a
    - *         connection within that period, it aborts the connection attempt.
    + *         <br>The value of this environment property is the string representation
    + *         of an integer specifying the connection timeout in milliseconds.
    + *         If the LDAP provider cannot establish a connection within that period,
    + *         it aborts the connection attempt.
      *         The integer should be greater than zero. An integer less than
      *         or equal to zero means to use the network protocol's (i.e., TCP's)
      *         timeout value.
      *         <br> If this property is not specified, the default is to wait
      *         for the connection to be established or until the underlying
      *         network times out.
    + *         <br> If a custom socket factory is provided via environment property
    + *         {@code java.naming.ldap.factory.socket} and unconnected sockets
    + *         are not supported, the specified timeout is ignored
    + *         and the provider behaves as if no connection timeout was set.
      *     </li>
      *     <li>{@code com.sun.jndi.ldap.read.timeout}:
      *         <br>The value of this property is the string representation
    - *         of an integer representing the read timeout in milliseconds
    + *         of an integer specifying the read timeout in milliseconds
      *         for LDAP operations. If the LDAP provider cannot get a LDAP
      *         response within that period, it aborts the read attempt. The
      *         integer should be greater than zero. An integer less than or



Comments
Moving to Approved. If not done so already, please also consider whether or not a release note would be beneficial here.
18-03-2024

The `java.naming.ldap.factory.socket` edit looks good to me too.
15-03-2024

The updated wording looks good to me.
15-03-2024

Made the edit for `java.naming.ldap.factory.socket` and moved back to Finalized.
14-03-2024

[~darcy] FWIW - the `java.naming.ldap.factory.socket` property was previously documented in the tech guides - there's evidence it was already present in JDK 8: https://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap-gl.html#socket
07-03-2024

Given future edits are expected, moving to Provisional not Approved. (If the properties were Java SE properties instead of JDK-specific properties, the CSR would not be as easily backported to earlier release trains.)
06-03-2024

The Specification section is expected to be updated with a clarification to the `java.naming.ldap.factory.socket` requirement to implement the `getDefault` method, requested in the PR here: https://github.com/openjdk/jdk/pull/17797#discussion_r1514602203
06-03-2024

The proposed wording looks good to me too.
06-03-2024

Hi Aleksei, thanks for the edits. That looks perfect to me. Please review the CSR such that I can propose it.
04-03-2024

Hi Christoph, I've did initial review and edit of the CSR. Please, feel free to make additional changes and let me know when it is ready for review. Given that it is planned to retro-actively document (CSR + RN) the JDK-8048175 JDK 9 change in how socket factories should be implemented, I've removed the reference to JDK 8 specific behavior here.
04-03-2024