Based on best practices I've read in different places (one example), it is ideal to separate API and implementation but also to only export packages in the API bundle and not in the implementation bundle, which should register as a service instead.
However I'm still not clear how are you supposed to extend a concrete class. It seems to me that to be able to do
class Child extends com.foo.ParentImpl {
}
the impl bundle would need to expose com.foo
AFAIU there are only two ways
So what is the right way to do this?
You can expose the implementation class as an export — OSGi will not prevent you from doing so. Just be aware that you are violating the best practice.
You may argue that best practices are meant to be broken, and in some cases you'd be right. However, this one really does exist for a good reason! Inheritance in Java creates a very tight coupling between the base- and sub-classes. By allowing other bundles to have visibility of your implementation classes and potentially subclass them, then you severely restrict your ability to make implementation changes in the base class. Essentially the implementation is the API, and so cannot be changed in the future.
So my advice would be to forget about inheritance. It's overrated.
If you really want to do it, then keep the hierarchy together, as per your option number 2.