Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to distinguish between API and SPI #127

Open
gunnarmorling opened this issue Mar 16, 2016 · 6 comments
Open

Allow to distinguish between API and SPI #127

gunnarmorling opened this issue Mar 16, 2016 · 6 comments

Comments

@gunnarmorling
Copy link

In libraries one usually has two kinds of contracts:

  • Things to be invoked by client
  • Things to be implemented by a client (often, that's more advanced use cases, or things like callbacks, or things geared towards integrators of a library)

Different rules apply for the evolution these two categories. E.g. adding method to an interface intended to be invoked by users is perfectly fine. Whereas adding a method intended to be implemented is a breaking change.

Thus I'd like to propose the following:

  • Provide means for configuring which parts of the analyzed library are API and which are SPI
  • Apply different rules depending on whether a class is API or SPI

I know it's are bigger change, but maybe we can get a discussion about it started?

@siom79
Copy link
Owner

siom79 commented Mar 21, 2016

As far as I understand your concern, the SPI part of the library is concerned about "source compatibility" while the invoked part is concerned by "binary compatibility".

Currently you could go by defining two executions (assuming that your SPI and your invoked API reside in two different packages):

<plugin>
    <groupId>com.github.siom79.japicmp</groupId>
    <artifactId>japicmp-maven-plugin</artifactId>
    <version>${project.version}</version>
    <executions>
        <execution>
            <id>api</id>
            <phase>verify</phase>
            <goals>
                <goal>cmp</goal>
            </goals>
            <configuration>
                <oldVersion>
                    <dependency>
                        <groupId>com.github.siom79.japicmp</groupId>
                        <artifactId>japicmp-test</artifactId>
                        <version>${project.version}</version>
                    </dependency>
                </oldVersion>
                <newVersion>
                    <file>
                        <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path>
                    </file>
                </newVersion>
                <parameter>
                    <includes>
                        <include>your.api.package</include>
                    </includes>
                </parameter>
            </configuration>
        </execution>
        <execution>
            <id>spi</id>
            <phase>verify</phase>
            <goals>
                <goal>cmp</goal>
            </goals>
            <configuration>
                <oldVersion>
                    <dependency>
                        <groupId>com.github.siom79.japicmp</groupId>
                        <artifactId>japicmp-test</artifactId>
                        <version>${project.version}</version>
                    </dependency>
                </oldVersion>
                <newVersion>
                    <file>
                        <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path>
                    </file>
                </newVersion>
                <parameter>
                    <includes>
                        <include>your.spi.package</include>
                    </includes>
                </parameter>
            </configuration>
        </execution>
    </executions>
</plugin>

This would also generate two different reports.

@GwtarPlayer
Copy link

I just posted a similar proposal, with some more detail, not realizing that there was this one here already:

#136

Please have a look at that one. This is not about source vs. binary compatibility. It is quite different. Source vs. binary is more about generics and what can survive at compile time vs runtime.

@io7m
Copy link
Contributor

io7m commented Mar 6, 2017

I think the primary difference here is interfaces.

If I'm a service consumer (a user of a type exposed as a Java interface), then if a new method is added to that interface, it hasn't broken compatibility. It's a change that should trigger an increment of the minor version number.

However, if I'm a service provider (an implementor of a type exposed as a Java interface), then if a new non-default method is added to that interface, it has broken compatibility with my existing code and should therefore trigger an increment of the major version number.

The OSGi alliance published a nice short paper on this: https://www.osgi.org/wp-content/uploads/SemanticVersioning.pdf

@gunnarmorling
Copy link
Author

@siom79 describes exactly what I'm after. Being able to express this kind of separation would be a big improvement to this - already very useful - tool.

@doggy-dev
Copy link

There are two osgi annotations exactly for this purpose: @org.osgi.annotation.versioning.ProviderType and @org.osgi.annotation.versioning.ConsumerType

@io7m
Copy link
Contributor

io7m commented Mar 24, 2018

There are two osgi annotations exactly for this purpose

In fact there's even a Maven plugin that will perform similar checks to japicmp but will also take those two annotations into account:

https://github.com/bndtools/bnd/tree/master/maven/bnd-baseline-maven-plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants