Implementation Vs Api

On gradle we have different ways of declaring a dependency. Two of the common ways is implementation and api. For example:

dependencies {  
  implementation('org.springframework.boot:spring-boot-configuration-processor')  
  api('org.reflections:reflections:0.10.2')  
}

The difference

implementation means the dependency doesn't need to be expose to the end-user. implementation means our application have access to the compileClassPath and the runTimeClassPath

  • compileClassPath means in the code, we can use the API in that dependency.
  • runTimeClassPath means when running the code, we can use that library to run something as well.

api means our dependency will expose to the end user to be a transitive dependency (which mean the user also have access to it).

  • api also have everything that implementation has.

When use which

When we using implementation vs api depends on if we're coding the ABI (Application Binary Interface)

If we only use the library in the body of a function (which is not path of the ABI (Application Binary Interface)), we use implementation.

If we use the library as the return type or parameter type (which is path of the ABI (Application Binary Interface)), we use api.

Example

Consider the following dependency:

org.reflections:reflections:0.10.2

if my code in the library is something like

import org.reflections.Reflections;

public Reflections getReflections() {
	return new Reflections();
}

Since i'm returning the Reflections object, we use api

If my code is just

import org.reflections.Reflections;

public Set<Class<?>> getClasses() {
	var reflection = new Reflections();
	return reflection.getTypesAnnotatedWith(MyAnnotation.class);
}

then it's just implementation

[!important]
To use api, we need to have plugins { id "java-library" } instead of java in build.gradle