Begin to label interfaces for stability (OPENDJ-996)

[OPENDJ-999] Determine which SDK Java APIs may be considered stable / evolving. Created: 20/Jun/13  Updated: 07/Nov/19  Resolved: 27/Jun/13

Status: Closed
Project: OpenDJ
Component/s: core apis
Affects Version/s: 2.6.0
Fix Version/s: 2.6.0

Type: Sub-task Priority: Major
Reporter: Matthew Swift Assignee: Matthew Swift
Resolution: Fixed Votes: 0
Labels: None

Sprint: Sprint 11

 Description   

We should use annotations for this, but let's just document them for now.

Candidates for evolving APIs include:

  • server side APIs (RequestHandler, ServerConnection, etc)
  • SchemaBuilder - may be I can just hide the ugly constructors for now
  • Rest2LDAP


 Comments   
Comment by Matthew Swift [ 26/Jun/13 ]

For the Java APIs I propose that we introduce three new annotations:

  • @Stable
  • @Evolving
  • @Internal

In addition, we can re-use the @Deprecated annotation from java.lang. Another option is to use a single parameterized annotation like @Stability, which has a parameter indicating the stability level. However, a single annotation prevents us from taking advantage of @Deprecated, forcing us to effectively duplicate information, e.g:

@Stability(level=DEPRECATED)
@Deprecated
public interface MyDeprecatedInterface { ... }

Obviously, the first approach allows a developer to annotate an element with conflicting levels, e.g:

@Evolving
@Deprecated
public interface MySchizoInterface { ... }

Another important issue how these stability annotations will be inherited, since it would be pretty cumbersome to have to provide annotations on every single class and method. There are two axes of "inheritance", the first being via traditional class/interface inheritance, and the second via scope (i.e. package, then class, then individual methods and fields). We should support both, and provide the ability to override where needed. For example, I should be able to tag an entire package as stable, and a single class as deprecated or evolving. In other words, a method or field will inherit its stability level from its containing class, which in turn inherits its stability level from its package or parent super-class / interface. A problem with this approach is how we should handle cases where there are conflicting inherited stability levels (e.g. between a class's package and its super-class/interface, or between super-interfaces).

Finally, it would be nice if Javadoc generation could extract any inherited stability levels so that it is easy to determine the effective stability level of an element without having to understand the rules and navigate through parent classes and packages.

Comment by Jean-Noël Rouvignac [ 26/Jun/13 ]

I think @Stability annotation + enum for the Stability level is more expressive.
I am not too worried about the duplication/burden of annotating with @Deprecated since this can be automatically checked during the build or nightly builds.

I suppose the @Stability annotation can also be applied to methods, right?

Concerning the javadocs:

  • you must apply the @Documented annotation to the annotations you want to see appear in the javadocs.
    • some testing will be required to figure out how this is working with type inheritance
  • I doubt javadoc can fit our need for package scoped stability. Some other alternative/tooling will have to be found/written.

Concerning conflicting stability levels, we must define an inheritance order, like for example:

  1. super-type(s) - sub-types cannot be more stable than super-type
  2. current class - can override package level stability
  3. current package - broader and least-precise stability level

The harder bit is when hierarchically unrelated super-classes/super-interfaces have conflicting annotations. I think it is best to retain the least stable stability level.
It could be an option to force a developer to annotate the class when such case exist.

As I mentioned earlier, unit tests can be written to ensure everything is hunky-dory.

Comment by Matthew Swift [ 27/Jun/13 ]

Thanks Jean-Noel. I agree with your comments. I originally proposed using separate annotations in order to allow us to re-use @Deprecated. However, there are some aspects of Deprecated that don't really fit so well with some of the semantics described above. For example, @Deprecated is not inherited. In addition, we will not be able to extend it either, e.g. to add version information, like "since version xxx".

Comment by Matthew Swift [ 27/Jun/13 ]

Back to the original goal which is to document the SDK APIs. Unless specified the default stability is internal.

opendj-ldap-sdk

This module is stable with exceptions:

  • all com.* packages are internal
  • the following server classes, interfaces, and methods are evolving:
    • org.forgerock.opendj.ldap.Connections#newInternalConnection
    • org.forgerock.opendj.ldap.Connections#newInternalConnectionFactory
    • org.forgerock.opendj.ldap.Connections#newServerConnectionFactory
    • org.forgerock.opendj.ldap.FutureResult
    • org.forgerock.opendj.ldap.LDAPClientContext
    • org.forgerock.opendj.ldap.LDAPListener
    • org.forgerock.opendj.ldap.LDAPListenerOptions
    • org.forgerock.opendj.ldap.MemoryBackend
    • org.forgerock.opendj.ldap.RequestContext
    • org.forgerock.opendj.ldap.RequestHandler
    • org.forgerock.opendj.ldap.RequestHandlerFactory
    • org.forgerock.opendj.ldap.ServerConnection
    • org.forgerock.opendj.ldap.ServerConnectionFactory
  • the following client and core classes and interfaces are evolving:
    • org.forgerock.opendj.ldap.ConnectionSecurityLayer
    • org.forgerock.opendj.ldap.LDAPUrl
    • org.forgerock.opendj.ldap.requests.BindRequest - including sub-types and especially SASL sub-types
    • org.forgerock.opendj.ldap.schema.MatchingRuleImpl
    • org.forgerock.opendj.ldap.schema.SchemaValidationPolicy
    • org.forgerock.opendj.ldap.schema.SyntaxImpl
  • the following client and core classes, interfaces, and methods are deprecated:
    • org.forgerock.opendj.ldap.LDAPOptions#getTCPNIOTransport
    • org.forgerock.opendj.ldap.LDAPOptions#setTCPNIOTransport
  • the class org.forgerock.opendj.ldap.CoreMessages is internal

opendj-ldap-sdk-examples

The examples in this module are evolving.

opendj-ldap-toolkit

The command line tools provided by this module are evolving.

opendj-rest2ldap

This module is evolving.

opendj-rest2ldap-servlet

This module is evolving.

opendj-server2x-adapter

This module is stable, although it should be noted that the server APIs with which it interacts are evolving.

Comment by Matthew Swift [ 27/Jun/13 ]

Annotating the SDK will be addressed in a separate issue post 2.6.0

Generated at Sun Jan 17 00:41:43 UTC 2021 using Jira 7.13.12#713012-sha1:6e07c38070d5191bbf7353952ed38f111754533a.