Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to hide a service implementation

I want to hide the implementation (concrete class) of a service (interface) from the API user. The implementation is provided to the user by a factory which uses the Java API ServiceLoader mechanism. This Loader requires the implementation class to have public visibility. This is OK as long as the implementation is hidden in a different JAR (apart from the API JAR) the user is not directly depending on.

However, for easy distribution the content of the JAR with the default implementation is packed into the API JAR. So effectively the user depends on this prepacked JAR where the default implementation class is available with public visibility. Nothing keeps people from directly instantiating the implementation. I don't want that to be possible.

My bad ideas:

  • implement an own version of ServiceLoader which allows to load package private implementations (btw, why does the Java API ServiceLoader doesn't allow this?)
  • ship separate API and implementation JARs

What do you think is the right way? Any compromise?

Using OSGi or other heavy machinery is out of question.

like image 978
Alexander Avatar asked Oct 04 '22 04:10

Alexander


2 Answers

Disappointing maybe but:

  • Make a separate jar and put that with the other third party jars.
  • Let the installer/the deployment process handle nice packaging of all.
  • Do not make this jar available during compile time; maven: <scope>runtime</scope>.

The only other way would be the have @Deprecated in the javadoc, with as comment how to use the corresponding class using the java service API.

like image 103
Joop Eggen Avatar answered Oct 10 '22 04:10

Joop Eggen


In C# you can create an internal interface that is visible only to relevant friend assemblies, and then explicitly implement the interface. I'm not sure how you would do this in Java, but conceptually this is how I've been able to work around this problem in the .NET world.

EDIT I just looked it up, from what I can tell Java doesn't have explicit implementation for interfaces. As an FYI, an explicit implementation of an interface requires you to make a function call through an interface member, you can't call it as a member of the implementing class. This is why my technique works for me, at least in the .NET world.

Alternatively, I would suggest putting the interface in another JAR, and don't distribute it with the API

like image 40
Bender the Greatest Avatar answered Oct 10 '22 04:10

Bender the Greatest