8

I'd like to have a jar file in which only the API package is accessible. All the other packages (containing implementations) would not be accessible by another jar (nor by any other class).

Is it possible ?

If yes, how ?

glmxndr
  • 45,516
  • 29
  • 93
  • 118

8 Answers8

4

Currently scheduled for Java 8 (2012?) is JSR 294. This JSR introduces better modularization language constructs into Java.

Today, an implementation can be partitioned into multiple packages. Subparts of such an implementation need to be more tightly coupled to each other than to the surrounding software environment. Today designers are forced to declare elements of the program that are needed by other subparts of the implementation as public - thereby making them globally accessible, which is clearly suboptimal.

Alternately, the entire implementation can be placed in a single package. This resolves the issue above, but is unwieldy, and exposes all internals of all subparts to each other.

The language changes envisioned will resolve these issues. In particular, we expect to introduce a new notion of modules (superpackages) at the language level where existing public access control would apply only within a language level module and access to API's from outside a module would be restricted to API's the module explicitly exports.

Now I believe the expert group is still discussing the details of this concept. But I believe one thing you might be able to do is this (source: Super Packages in Java 7.0):

superpackage com.myorg.myApp.model
{
    member package com.myorg.myApp.model.swing;

    member package com.myorg.myApp.model.html;

    export com.myorg.myApp.model.swing.SEmployee;
    export com.myorg.myApp.model.swing.SDepartment;

    export package com.myorg.myApp.model.html;
}

In other words, for a given "superpackage" you can define what is and isn't exported, independent from visibility keywords like public.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • Here's a link to Mark Reinhold's blog, which bizarrely seems to be the most authoritative source on the future of Java: http://blogs.sun.com/mr/entry/plan_b_details – Mark Peters Dec 08 '10 at 15:38
  • That JSR is marked inactive and the last activity was in 2007 - is it really likely to happen? – bacar Mar 07 '12 at 22:17
  • that link to Mark Reinhold's blog seems to be defunct, here's an updated couple: http://mreinhold.org/blog/module-system-requirements, http://mreinhold.org/blog/plan-b – bacar Mar 07 '12 at 22:48
  • 1
    It's probably worth mentioning that it doesn't appear that the super package mechanism made it into the now-released Java 7... – bacar Mar 08 '12 at 00:26
4

If you have classes that should not be used, put them into a subpackage named "internal". While this does not prevent others from using the classes, it is a strong indication that they should not.

Example:

my.library.Stuff
my.library.StuffFactory
my.library.internal.StuffImpl
my.library.internal.MoreStuff
my.library.internal.xml.DataStuff

While this is not an actual solution, I would consider it a best practice.

glmxndr
  • 45,516
  • 29
  • 93
  • 118
Cephalopod
  • 14,632
  • 7
  • 51
  • 70
2

this isn't really possible in Java 6 unless you're using OSGI which I assume you're not. what I usually end up doing to hide classes is to use package friendly classes for implementations - but you might still need to expose some class-es if you're implementation classes do live in a separate package.

sample:

package com.example;

public class Service { } assume the API class uses ServiceImpl as it's implementation

now if ServiceImpl lives in the same package you might remove it's public class modifier and it won't be accessible outside the package ...

if it lives in a different package (your case) it needs to be public :

package com.example.impl;

public class ServiceImpl { }

but all implementation details (related classes it uses) from the same package need not to be public !

kares
  • 7,076
  • 1
  • 28
  • 38
1

In a "normal" java application that is not possible. Although in OSGi environment you define which packages are exposed by your bundle (slightly modified jar file) to other bundles and which are private (not visible outside your bundle).

wesoly
  • 552
  • 2
  • 11
0

Why not simply create a jar with the API classes and a seperated jar with implementations depending of the API one. That way, you can distribute your API classes without distributing your implementation.

KR.

Thomas
  • 111
  • 2
0

I can see the reason why do you want to do it. It has always troubled me when I try to use someone's library. There are so many classes which I don't know where to start with.

As far as I can see from most libraries, there is no such a library that try to hide unrelated classes. Although, this is not a solid evidence , it must means there is no way to do it. Normally, they budle api and the implementation into seperated jar files.

However, if you are running your application through OSGi framework, it is possible to bundle your jar file in such way that the OSGi frame can see only the API classes you want. But using OSGi might be a bit of work.

gigadot
  • 8,879
  • 7
  • 35
  • 51
0

You can add an ant-task or a maven-jar-plugin configuration to jar the components you need given your building tool preference.

dimitrisli
  • 20,895
  • 12
  • 59
  • 63
0

Another solution is to set default access modifier in implementation classes and put them in the same package as interfaces. Although its a bit dirty way.

wesoly
  • 552
  • 2
  • 11