The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

kamrans (10) [Avatar] Offline
#1
Hi,

To experiment with OSGi modularity enforcement capabilities, I added a new private package called "org.foo.farewell" and also updated both org.foo.hello.main.Main (to load the new bundle) and org.foo.hello.client.Client (to import and instantiate the newly added org.foo.farewell.Farewell). But to my surprise the OSGi framework allowed my client to access and instantiate the Farewell class which in a private package.

This goes against what you have written in section "1.3.1 Modularity Layer" of your book.

What did I miss?

Appended below are the manifest.mf files for both org.foo.farewell.Farewell and org.foo.hello.client.Client classes.

Cheers,
Kamran

manifest for Client.java
------------------------------------------------------------
Bundle-ClassPath: .,META-INF/embedded
Manifest-Version: 1.0
Private-Package: org.foo.hello.client
Tool: Bnd-0.0.312
Bundle-Name: consumer
Created-By: 1.6.0_16 (Sun Microsystems Inc.)
Bundle-Version: 1.0
Bnd-LastModified: 1253714515015
Bundle-ManifestVersion: 2
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0
Import-Package: org.foo.hello;version="[1.0,2.0)"
Bundle-SymbolicName: org.foo.hello.client
Bundle-DocURL: http://code.google.com/p/osgi-in-action/
Include-Resource: META-INF/LICENSE=C:workspaceprojectsosgi-in-actio
n/LICENSE,META-INF/NOTICE=C:workspaceprojectsosgi-in-action/NOTICE
------------------------------------------------------------------


manifest for Farewell.java
-----------------------------------------------------------------
Bundle-ClassPath: .,META-INF/embedded
Manifest-Version: 1.0
Private-Package: org.foo.farewell
Tool: Bnd-0.0.312
Bundle-Name: provider
Created-By: 1.6.0_16 (Sun Microsystems Inc.)
Bundle-Version: 1.0
Bnd-LastModified: 1253714514406
Bundle-ManifestVersion: 2
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0
Import-Package: org.foo.farewell;version="[1.0,2.0)"
Bundle-SymbolicName: org.foo.farewell
Bundle-DocURL: http://code.google.com/p/osgi-in-action/
Include-Resource: META-INF/LICENSE=C:workspaceprojectsosgi-in-actio
n/LICENSE,META-INF/NOTICE=C:workspaceprojectsosgi-in-action/NOTICE
kamrans (10) [Avatar] Offline
#2
Re: issues in modularity
Forgot to mention in my previous post that I simply extended the code in the osgi-in-actionchapter01greeting-examplemodularity by adding a org.foo.farewell.Farewell class.

Kamran
richard.hall (87) [Avatar] Offline
#3
Re: issues in modularity
Are you sure you packaged your bundles correctly? Perhaps they actually contain the class.
stuart.mcculloch (29) [Avatar] Offline
#4
Re: issues in modularity
Hi Kamran,

Can you attach your modified project?

I added a new farewell bundle with a Farewell class, kept the package private, and got:

Error starting program: java.lang.ClassNotFoundException: org.foo.hello.client.Client
java.lang.ClassNotFoundException: org.foo.hello.client.Client
at org.apache.felix.framework.Felix.loadBundleClass(Felix.java:1483)
at org.apache.felix.framework.BundleImpl.loadClass(BundleImpl.java:872)
at org.foo.hello.main.Main.main(Main.java:27)
Caused by: org.osgi.framework.BundleException: Unresolved constraint in bundle
org.foo.hello.client [2]: package;
(&(package=org.foo.farewell)(version>=1.0.0)(!(version>=2.0.0)))
at org.apache.felix.framework.Felix.resolveBundle(Felix.java:326smilie
at org.apache.felix.framework.Felix.loadBundleClass(Felix.java:1476)
... 2 more

Which is what I'd expect - so I think it's a build/packaging issue.
kamrans (10) [Avatar] Offline
#5
Re: issues in modularity
Hi Stuart,

how can I attach my modified project? The Manning Sandbox just lets you post text and it doesn't let you attach a zip-file to it, right? (Sorry, I am new to using the Sandbox).

Regarding your error message:

1) It shows that I am definitely doing something differently

2) The error message that you produced is interesting. In fact what you get is a ClassNotFoundException for org.foo.hello.client.Client. I expected to see an error for not being able to access org.foo.farewell.Farewell since this class is in a private package and org.foo.hello.client.Client is trying to import and instantiate it.

Anyways, the best thing is for me to send you the whole modified chapter01greeting-examplemodularity example as a zip file, but how?

Thanks,
Kamran
stuart.mcculloch (29) [Avatar] Offline
#6
Re: issues in modularity
Hi Kamran,

When I post a reply the web GUI has an "Attach Files" button just below the message box. If you don't see this button you can send the files directly to me: mcculls at gmail dot com

Re. the CNFE... the main module (which starts the framework) attempts to load the Client class using the client classloader - loading the Client class triggers additional load requests for any classes the Client uses, like Greeting and Farewell. The client classloader cannot see the farewell package because it's not exported, so it cannot load Farewell - this then causes the initial load request to fail, hence the CNFE for Client. (Note the cause of this CNFE is recorded as being to due to an unresolved constraint, ie. the missing package)

However, if you attempted to start the client module using the OSGi API in the main module (ie. "consumer.start();") then you would get an exception about the missing import constraint. It's the difference between using the framework directly, and using it indirectly via the classloader API (which dictates what exceptions can be thrown).

Cheers, Stuart
kamrans (10) [Avatar] Offline
#7
Re: issues in modularity
No, in fact Farewell class is in its own bundle called provider2. Below is the full info about the created bundles:

Cheers,
Kamran


C:workspaceprojectsosgi-in-actionchapter01greeting-examplemodularityundles>dir
Volume in drive C is OS
Volume Serial Number is 3CD9-2697

Directory of C:workspaceprojectsosgi-in-actionchapter01greeting-examplemodularityundles

09/25/2009 10:56 AM <DIR> .
09/25/2009 10:56 AM <DIR> ..
09/25/2009 10:56 AM 6,013 consumer-1.0.jar
09/25/2009 10:56 AM 5,953 provider-1.0.jar
09/25/2009 10:56 AM 5,971 provider2-1.0.jar
3 File(s) 17,937 bytes
2 Dir(s) 133,428,461,568 bytes free

C:workspaceprojectsosgi-in-actionchapter01greeting-examplemodularityundles>jar tf consumer-1.0.jar
META-INF/MANIFEST.MF
META-INF/
META-INF/LICENSE
META-INF/NOTICE
org/
org/foo/
org/foo/hello/
org/foo/hello/client/
org/foo/hello/client/Client.class

C:workspaceprojectsosgi-in-actionchapter01greeting-examplemodularityundles>jar tf provider-1.0.jar
META-INF/MANIFEST.MF
META-INF/
META-INF/LICENSE
META-INF/NOTICE
org/
org/foo/
org/foo/hello/
org/foo/hello/Greeting.class

C:workspaceprojectsosgi-in-actionchapter01greeting-examplemodularityundles>jar tf provider2-1.0.jar
META-INF/MANIFEST.MF
META-INF/
META-INF/LICENSE
META-INF/NOTICE
org/
org/foo/
org/foo/farewell/
org/foo/farewell/Farewell.class
stuart.mcculloch (29) [Avatar] Offline
#8
Re: issues in modularity
Hi Kamran,

Here's the manifest from your provider2 bundle, which I got by using:

ant clean dist

jar xvf bundles/provider2-1.0.jar META-INF/MANIFEST.MF

===========================================================
Manifest-Version: 1.0
Export-Package: org.foo.farewell;version="1.0"
Tool: Bnd-0.0.337
Bundle-Name: provider2
Created-By: 1.6.0_13 (Sun Microsystems Inc.)
Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
Bundle-Version: 1.0
Bnd-LastModified: 1253892211816
Bundle-ManifestVersion: 2
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0
Include-Resource: META-INF/LICENSE=c:UsersstuartDocumentsHomeOSGi
InActionpublic runk/LICENSE,META-INF/NOTICE=c:UsersstuartDocumen
tsHomeOSGiInActionpublic runk/NOTICE
Import-Package: org.foo.farewell;version="[1.0,2.0)"
Bundle-SymbolicName: org.foo.farewell
Bundle-DocURL: http://code.google.com/p/osgi-in-action/
===========================================================

Notice that the farewell package is being exported from provider2, and it is imported by the client - this means the client has visibility of the farewell package, which is why you don't see any error or exception.

To make the farewell package private you need to edit "org.foo.farewell/build.properties" and change the line that says:

Export-Package: ${module};version="1.0"

to just:

Private-Package: ${module}

and rebuild (ie. "ant dist") - this will keep the farewell package private and you should then get the same error as I did, because no-one now exports the farewell package.
kamrans (10) [Avatar] Offline
#9
Re: issues in modularity
Thanks a lot Stuart, really appreciate your help!

This would 'however mean that:

1) The info for package access privileges are not concentrated in a single file (i.e. it appears both in the manifest.mf and build.properties). Which makes both the maintenance and debugging difficult.

2) The ant build modifies the packaging meta-data files without the author's knowledge. Although I admit there was a conflict in the export statements in manifest.mf and build.properties. But I would rather prefer an error message because of this conflict instead of my meta-data file being changed by ant behind the scenes. Most people would not unjar the generated jar file to look at the manifest (from now on I will!).

Having said that, this is just how ant works and is not a deficiency in OSGi.

Thanks again for your help!

Regards,
Kamran
stuart.mcculloch (29) [Avatar] Offline
#10
Re: issues in modularity
Are you using Eclipse by any chance?

In our build (which is only one of the ways to build OSGi bundles) the package access privileges are defined in one place: the build.properties file containing the customized bnd instructions for that particular module (we keep a common set of bnd instructions in common/build.properties)

When you use ant to build the module, the bnd tool generates the bundle manifest by following these instructions. So you could think of build.properties as the source, which bnd 'compiles' into the bundle's internal manifest - just like Java source is compiled into bytecode by javac.

The external manifest file is there to keep Eclipse happy, because PDE only supports bundle projects which have unpacked layouts, ie. it's as if the bundle had been unjar'd. Unfortunately, Eclipse also expects this top-level manifest to be the source (or recipe) used to build the bundle - this is also known as a "manifest-first" approach.

So if you modify the top-level manifest in Eclipse, while this will change the bundle that Eclipse generates (for example, when you launch the bundles using the Eclipse IDE) it won't affect the bundle built by ant. Rebuilding with ant will simply replace the external manifest with the bnd generated manifest, based on the build.properties instructions.

It's like editing a copy of some source in Eclipse, and then rebuilding with the original source. Your changes won't affect the bundle, because you've edited a copy, not the original code. In an ideal world where we had lots of time we'd write an Eclipse plug-in that would watch as you edit the manifest and make the appropriate changes to the build.properties. But this is outside the scope of our simple examples - we just want to provide a way to play with OSGi without requiring an IDE, while also letting people load the examples in Eclipse (with the above restrictions).

Thankfully there are people are working on the disconnect between Eclipse/PDE and other OSGi build systems - for example the Tycho project lets you choose between "pom-first" or "manifest-first" builds, and attempts to keep both Eclipse and Maven in sync. The bnd tool can also be used as an Eclipse plug-in, effectively replacing PDE and letting you use the same instructions to drive both ant and Eclipse.

To sum up, the problem is down to "dueling" build systems (ant vs. Eclipse/PDE) that use different recipes to build OSGi bundles (build.properties vs. external manifest). We provide a way to feed changes from ant to Eclipse ("ant pde") but not the other direction.
kamrans (10) [Avatar] Offline
#11
Re: issues in modularity
Hi Stuart,

I do use Eclipse. Your reply just answered all of my concerns. I was assuming that the manifest.mf file in META-INF is supposed to be the one that appears in the bundle. But now I understand that how the manifest file is generated is very related to your build environment.

Thanks a lot!! Perhaps it would be a good idea to talk a little bit about these build-time annoyances in the book.

Regards,
Kamran