+1 to Yifan’s recommendation. In Java, we may need to mark a method public for 
different reasons. Hence better to have annotations to mark public APIs.
+1 to David’s point that we may need tooling to parse annotations and 
error/warn accordingly.


> On Aug 18, 2026, at 4:50 AM, Yifan Cai <[email protected]> wrote:
> 
> +1 to Josh's annotation-based approach over "public by default". 
> 
> Java's public keyword is not an API commitment. Plenty of public methods 
> exist only because they're called from another package in the same project, 
> not because they are public APIs intended for external consumers to depend on 
> them. Treating Java's public keyword as API contract conflates two different 
> concerns. 
> 
> Scope annotations (@Public/@Internal/whatever we settle on) aren't just 
> documentation for consumers, but also a relief to code maintainers. W/o the 
> annotations, every public method becomes something we can't safely rename, 
> update or remove, even when it was never meant to be depended on by external 
> consumers. 
> 
> Explicit annotations let authors keep refactoring freely on everything not 
> deliberately promoted as public API, while still giving consumers a clear 
> surface to build against. 
> 
> Starting narrow and widening over time takes (significantly) less effort than 
> defaulting everything to public API and spending years walking it back. 
> 
> - Yifan 
> 
> On Mon, Aug 17, 2026 at 1:34 PM David Capwell <[email protected] 
> <mailto:[email protected]>> wrote:
>> > They're all internal, this is a convenience to improve code sharing.
>> 
>> Once they go into utils they are not “internal” (whatever that means).  Why 
>> I started this effort in the first place is that the test utilities have 
>> been requested to be used in projects like Cassandra-ecosystem, but also 
>> non-cassandra projects.  Both users need to know that a hot fix doesn’t 
>> break their build hence why I propose basic properties you would expect: 
>> major versions might have breaking changes, minor / patch won’t.  For the 
>> classes anyone has talked about moving here, non of them should have issues 
>> with this; we are free to add new methods over time, but removing causes 
>> issues for consumers.
>> 
>> > to improve code sharing.
>> 
>> Even if you think about this only for cassandra ecosystem, if I depend on 
>> version 0.1.0 and we find a bug so get that fixed and now we depend on 
>> 0.1.10… I shouldn’t expect to deal with breaking changes.  The mentality of 
>> “They’re all internal” as a justification to not document these assumptions 
>> causes me concern as breaking changes explicitly make it harder for parties 
>> to depend on these classes; breaking changes make is so much harder to 
>> “share code”.
>> 
>> > We only care about versioning to ensure we don't break any builds
>> 
>> What do you mean by this?  Major versions I am ok with breaking changes; 
>> minor / patch is what I want to avoid.  We can add new APIs without issue, 
>> the concern is only on removal.
>> 
>> > and even decide when we upgrade the jar so can spot and fix any breakages.
>> 
>> If we are upgrading to enable a new JDK change, I wouldn’t expect users to 
>> have to rewrite all their tests, redo all their collections, etc…. You 
>> shouldn’t have to worry about upgrading the version cross minor / patch 
>> versions, as that should impose a no breaking change rule.
>> 
>> 
>> > On Aug 14, 2026, at 3:06 PM, Benedict Elliott Smith <[email protected] 
>> > <mailto:[email protected]>> wrote:
>> > 
>> > Why are we defining this at all? They're all internal, this is a 
>> > convenience to improve code sharing. We only care about versioning to 
>> > ensure we don't break any builds, and we have all the builds, and even 
>> > decide when we upgrade the jar so can spot and fix any breakages.
>> > 
>> > Let's not overcomplicate things, or bind our future selves in red tape and 
>> > regret.
>> > 
>> > On 2026/08/14 17:57:40 Josh McKenzie wrote:
>> >> While I read your email I found myself wondering "To what are we 
>> >> referring to when we say 'API'"? ;)
>> >> 
>> >> Are you talking about a public interface? Or are you talking about "any 
>> >> class that's public and any public method within a public class"?
>> >> 
>> >> If the latter, my primary theoretical concern is that if we pull in code 
>> >> that has components that are scoped public for cross-package 
>> >> accessibility within-project, promoting those to "public by default" 
>> >> immediately calcifies their interface whether we intend for that to be 
>> >> consumed or not. Basically, we don't have an interim scope layer between 
>> >> "package private" and "public" that corresponds to "project public". In 
>> >> theory the post JDK9 modularity kind of provides that but then everyone 
>> >> just add-opens bulldozes across things (the joys of legacy code...).
>> >> 
>> >> I think "Any interface that's public is a public API" is pretty obvious 
>> >> to maintainers and users and good. I'm also good with "anything public is 
>> >> an API unless otherwise documented" and we add a simple annotation like 
>> >> @INTERNAL 
>> >> <https://github.com/apiguardian-team/apiguardian/blob/main/src/main/java/org/apiguardian/api/API.java#L87>
>> >>  from API Guardian to basically say "yeah, this is public, but it's not 
>> >> intended for public consumption" (I think we should roll our own to match 
>> >> our proposed lifecycles but that's a clear example of the idea).
>> >> 
>> >> I'm worried about the approach of "Any public method in a public class is 
>> >> considered public API and you can't change it". I'd prefer we start with 
>> >> a more constrained surface area we commit to as being an API and widen it 
>> >> later if we find there's a need; it's much harder to go in the other 
>> >> direction.
>> >> 
>> >> On Fri, Aug 14, 2026, at 1:24 PM, David Capwell wrote:
>> >>> Josh and I talked about this offline and not perfectly in-sync so would 
>> >>> be good to get other peoples views
>> >>> 
>> >>> My take is that if you are adding the API to this shared repo we need to 
>> >>> care about backwards compatibility so things should be PUBLIC by default 
>> >>> (anything that is java public is part of the public interface and 
>> >>> breaking changes are not allowed without a long enough deprecation 
>> >>> window similar to Cassandra’s.). I think Josh is in favor of using a 
>> >>> annotation to mark that a API is public, but without custom tooling I 
>> >>> don’t think anyone will notice and then we will get to a effectively 
>> >>> public state and breaking changes will be a nightmare to deal with for 
>> >>> the community.  So if you want to post the API here, it should be stable 
>> >>> and we shouldn’t be putting APIs that have not been fleshed out first.
>> >>> 
>> >>>> On Aug 7, 2026, at 8:16 AM, Josh McKenzie <[email protected] 
>> >>>> <mailto:[email protected]>> wrote:
>> >>>> 
>> >>>> One thing worth immediately calling out that we might want to split 
>> >>>> out: we *could* do this work in Ant.
>> >>>> 
>> >>>> It would be somewhat more imperative and brittle: we'd explicitly 
>> >>>> orchestrate the build ordering in Ant, while relying on the Gradle 
>> >>>> build inside Accord for its cassandra-utils dependency resolution / 
>> >>>> source substitution. That leaves us with a somewhat more complicated 
>> >>>> mixed Ant/Gradle build relationship but it's entirely workable for an 
>> >>>> interim time.
>> >>>> 
>> >>>> So if the Gradle migration is a sticking point, we can break that out 
>> >>>> into a separate discussion and CEP rather than making it part of CEP-65.
>> >>>> 
>> >>>> Doing so would mean retaining and extending some of the complexity in 
>> >>>> our existing build system that a future migration could remove, but 
>> >>>> it's not a crushing amount of additional complexity. The benefit of 
>> >>>> doing that work here with this CEP is that we have one more concrete 
>> >>>> build need providing a reason to move toward a unified build stack, and 
>> >>>> it fits the "clean things up and refactor as you're working on things 
>> >>>> that could benefit from that work" approach many have argued for in the 
>> >>>> past on the project.
>> >>>> 
>> >>>> On Fri, Aug 7, 2026, at 10:58 AM, Josh McKenzie wrote:
>> >>>>> As per the previous ML thread: [DISCUSS] Forking Cassandra utilities 
>> >>>>> into a separately released library 
>> >>>>> <https://lists.apache.org/thread/7kllp45vvonsg7ggzxpz39c5kdcy7r6g>, 
>> >>>>> David and I put together a draft of what we discussed and worked 
>> >>>>> through some implications and requirements that came up as we tried to 
>> >>>>> nail things down.
>> >>>>> 
>> >>>>> The goal here is to provide a material backstop to continue our 
>> >>>>> discussion and version it. As with all CEP DISCUSS threads, this is 
>> >>>>> very fluid and none of it should be taken as settled or an implicit 
>> >>>>> mandate. Let's see if we can make some progress on this long-standing 
>> >>>>> pain point in our ecosystem.
>> >>>>> 
>> >>>>> CEP-65 DRAFT: link 
>> >>>>> <https://cwiki.apache.org/confluence/spaces/CASSANDRA/pages/446071230/CEP-65+cassandra-utils+-+A+shared+utility+library+for+the+cassandra+ecosystem+DRAFT>
>> >>>>> 
>> >>>>> *Why You Should Read This Draft:*
>> >>>>> 1.  Build system impact: we need a parent project and one of its 
>> >>>>> submodule to depend on another submodule. We're proposing freezing 
>> >>>>> ant's API surface area, maintaining that into perpetuity, and moving 
>> >>>>> to gradle going forward.
>> >>>>> 2. Branching model: read the draft to see what "One Branch to Rule 
>> >>>>> Them All" means.
>> >>>>> 3. API Lifecycle: Is @BETA/@STABLE/@DEPRECATED enough? Do we need a 
>> >>>>> @PRIVATE?
>> >>>>> 4. To Release or Not To Release: we're proposing consumers embed this 
>> >>>>> as a submodule initially to minimize friction in moving shared code 
>> >>>>> into a shared space.
>> >>>>> We have 1 outstanding unanswered question we didn't come up with an 
>> >>>>> opinionated proposal for:
>> >>>>> 
>> >>>>> What should unannotated methods and classes in the library be 
>> >>>>> considered by potential consumers? @PRIVATE? @PUBLIC? Should we lint 
>> >>>>> and fail on any class without a top-level annotation forcing us to 
>> >>>>> make a choice on our dev list [DISCUSS] threads whenever we bring in 
>> >>>>> new things?
>> >>>>> 
>> >>>>> There's no timeline on this thread; let's keep turning the crank on 
>> >>>>> this until we've hit our pareto-polish frontier. ;)
>> >>>>> 
>> >>>>> ~Josh
>> >>>>> 
>> >>>>> 
>> >>>> 
>> >> 
>> 

Reply via email to