How to deal with changing APIs (Plugin-Plugin integration)?

Discussion in 'Spigot Plugin Development' started by Rsl1122, Dec 3, 2019.

  1. Hello.

    I have a plugin that integrates 30 other plugins into my plugin - Some are stable, some are abandoned and some are moving forward. When going forward the classes and methods for performing certain tasks might change, leading to exceptions on those that depend on the previous functionality (NoClassDefFoundError & NoSuchMethodError).

    I have been hacking at this problem for some time and unfortunately I have also been on the side that causes headache to other developers with large class changes.

    Currently I'm using similar approach to that of PlaceholderAPI and BentoBox where each integration is its own project - with one key difference that is causing me headache: A lot of the implementation of the integration is done & distributed by me, so when a plugin breaks API, more work is added to the pile.


    I think one option might be to do defensive coding and place all interaction behind a reflection layer, but that seems like a very extreme measure to take, and would reduce user facing issues instead of the amount of work.

    Have you come across integration issues and how do you manage them?
    • Like Like x 2
  2. Personally i just have a class for each dependency and i load each one inside a try catch for NoClassDefFoundError and NoSuchMethodError. If it fails i output a console warning saying that dependency's version is currently not supported.
    For some plugins i even have different classes for different versions of the same plugin like in the case of WorldGuard 6 and 7.

    I decided to split them into classes instead of projects because i found it easier to make changes although sometimes there are some annoying conflicts. This doesn't really eliminate the work of having to update myself whenever a plugin's API breaks but i don't think there's any other way except if you got other plugin developers to hook into your plugin themselves.
    #2 NoChanceSD, Dec 3, 2019
    Last edited: Dec 3, 2019
    • Agree Agree x 1
  3. Well, are all of the integrations really necessary? If there's permissions/chat/economy plugins that can be simplified to using an abstraction library like Vault, swap them out for Vault (if you don't already have it).
    If you grab any dependencies from Maven repositories, make sure the scope is "compile" and not "provided", otherwise the dependency will need to be present during runtime.
    If there is no Maven repository, then - as mentioned above - sectioning off this dependent code to its own class(es) would also work.
    • Agree Agree x 1
  4. They are not really necessary for the plugin to work, but since the goal is visualizing data of other plugins, many of the integrations have been requested by users. Vault is one of the dependencies.
    I don't think it makes sense to use 'compile' scope, as doing so would cause any other project to depend on this dependency via transitive dependencies (In cases where there is no maven repository this will make compilation fail for other developers, in case of plugins some maven repositories can also suddenly go down so it is not reliable.) - It makes sense to need the other plugin be present at runtime in order to integrate with it.
    Sectioning to own classes is of course a must, otherwise missing dependencies could cause the whole plugin to crash.
    I'm trying to find even more effective means - I heard in a conference talk that in the 70s an idea of programs telling each other how to communicate was presented (sort of auto-integration). I dunno what happened to it yet.