What does the private-package manifest header do?
Asked Answered
H

3

15

I am familiar with Import-Package and Export-Package, but this is a new one for me. What does it do?

Hardback answered 22/11, 2012 at 13:49 Comment(0)
D
18

At runtime in the OSGi container it does nothing. In fact, it's not even mentioned in the OSGi specification (I checked R4).

However, it can be specified in a .bnd file for use by bnd at build time. If so, it can be used to determine what goes into the bundle. When bnd builds a bundle, it automatically determines which classes need to go into the bundle. All the classes in packages that are exported are included, and all the classes that they depend on (transitively) are included too. This means that if a class doesn't appear to be used, then it won't be included in the bundle. However, you can use the Private-Package instruction to tell bnd to include the contents of the package in the bundle, even if it appears to be unused. If the Private-Package instruction is not specified, then it will be automatically generated by bnd.

The documentation for Private-Package reads as follows:

Private Package

The method of inclusion is identical to the Export-Package header, the only difference is, is that these packages are not exported. This header will be copied to the manifest. If a package is selected by noth the export and private package headers, then the export takes precedence.

Private-Package= com.*

Dinorahdinosaur answered 22/11, 2012 at 14:14 Comment(0)
C
13

If you know what static linking is then you understand Private-Package. Otherwise read on.

Private-Package is bnd's way of telling you the packages that must be inside the jar but that are not exported. It is not an OSGi header but a bnd 'instruction'.

The instruction defines the packages from the classpath (with wildcards) that must be included in the JAR. bnd is unique that it populates the JAR from a specification and not some directory like most build tools. The reason is that unless modules are 'designed' and their layout carefully considered they are rarely provide modular benefits.

In general Private-Package specifies the packages holding the classes that should not be shared with other bundles, i.e. the implementation classes. Though in general they come from the corresponding project that bnd is used in it is perfectly acceptable to get them from any other JAR on the classpath.

One use case is a library with utils. Turning a util library in a bundle is usually wreaking havoc with dependencies since utils tend to depend on lots of unrelated things; you use one tiny method and suddenly you drag in 30Mb of dependencies. bnd itself heavily uses this model with the aQute.lib* packages, packages from this library should never be exported. It is a trade of between bundle size and 'downloading the internet'. The difference is visible between the Eclipse's and Apache Felix's worlds. Apache Felix bundles are usually standalone and do not require all kinds of support and util bundles while Eclipse's bundles have a tendency to require lots of plumbing bundles. I think this difference is largely caused by Eclipse's PDE that makes it impossible to include packages from other projects unless you copy the source code which is of course a big no-no.

In the C world they have something called static linking. After a program is linked, any unresolveds are retrieved from a library and added to the target. To a certain extent Private-Package is the same idea. There is actually a header Conditional-Package that statically links the specified packages and anything they transitively depend on (as long as they fall in the pattern).

In the end bnd shows the expanded packages that are not exported in the Private-Package header in the manifest. After all, a manifest is supposed to describe the contents ...

If you're the author you can remove the header with -removeheaders: Private-Package (or in maven with <_removeheaders>Private-Package

Clementeclementi answered 23/11, 2012 at 7:25 Comment(2)
may I ask why BND doesn't "private-package" all the non-exported classes? if you have a class in your project it is because you need it; so if it's not exported, shouldn't it be private. In other words, when do you not Export-Package nor Private-Package a package?Ericerica
You must designate the private packages because bnd does not assume all classes from the src directory should be included, so there is no scope that would allow the subtraction of exported packages. Any package on bnd's class path can be included in a bundle, either private or exported. This way, bnd can build multiple bundles from a single project unlike most build environments. It also allows for the export of API packages that are provided by the bundle, even if they come from another bundle/jar.Clementeclementi
B
5

In fact Private-Package does more than just not exporting a package. If the packages specified in Private-Package are not defined inside you own project and are not imported in Import-Package then they are automatically inlined into your jar. So this is an easy way to include non OSGi dependencies. Be careful though that inlining can easily lead to classpath problems.

Bimolecular answered 23/11, 2012 at 7:15 Comment(1)
It would be great is the OSGi R7 documentation explicitly mentioned the "easy" way to include non-OSGi packages instead of making it hell trying to figure that out. It just says under 3.7.1 Diagrams and Syntax "Packages that are not exported or imported are called private packages."Assumption

© 2022 - 2024 — McMap. All rights reserved.