Skip to content

Add back enRoute Classic Tutorial on JAR Wrapping #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions _book/100-introduction.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
---
title: Guide
layout: default
title: Introduction about OSGi enRoute Classic
layout: prev-next-collection
summary: Is OSGi enRoute for You?
noindex: true
---

The enRoute Classic section is a collection of content helping to get you started into the OSGi mindset.

<div>
<table>

{% for book in site.book %}{%unless book.noindex%}<tr><td><a href="{{book.url}}">{{book.title}}</a></td><td>{{book.summary}}</td></tr>
{%endunless%}{% endfor %}

</table>
</div>


We _strongly_ believe that OSGi's Service Oriented Systems is the best paradigm available today for software development. But we are also frustrated when we see how hard it is for people to cross the chasm to reach that new paradigm. Out of this frustration, the OSGi enRoute project was born.

This OSGi Alliance initiative is about removing the barriers to adoption. It is about creating an environment where development of applications is almost as easy to get started with as Ruby on Rails applications without loosing the key advantages of OSGi/Java for projects that grow beyond their initial size.
Expand Down Expand Up @@ -38,7 +52,7 @@ We're here to prime the pump.

## How to Get Started?

If you're new to OSGi we suggest you follow the [quick start tutorial](200-quick-start.html) and then the more [complete tutorial](220-tutorial-base.html). If you're already into OSGi, you can check out the [data sheets](400-services.html).
If you're new to OSGi we suggest you follow the [tutorials](/book/150-tutorials.html). If you're already into OSGi, you can check out the [services catalog](/book/400-services.html).

[enroute-doc]: https://github.com/osgi/osgi.enroute.site
[enroute-doc]: https://github.com/bndtools/bndtools.github.io/tree/master/_book

7 changes: 5 additions & 2 deletions _book/150-tutorials.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Tutorials
layout: default
layout: prev-next-collection
summary: List of tutorials.
---

This section is an entry to the hopefully growing collection of tutorials that OSGi enRoute provides. If you want to develop an additional tutorial, please submit a PR.
Expand Down Expand Up @@ -86,7 +87,9 @@ The Maven Bnd Repository Plugin provides full bi-drectional access to the local

Quite often you need to use a dependency (a JAR file) which is not yet an OSGi bundle. To use this dependency in an OSGi project you need to learn how to _wrap_ a JAR to become a Bundle. Wrapping a JAR means that we need add the required OSGi manifest headers but also _design_ the contents of the bundle. bnd and bndtools provide tooling to make this process relatively simple.

[Go to the JAR Wrapping section](https://bnd.bndtools.org/chapters/390-wrapping.html) of the bnd manual.
[Go to the JAR Wrapping Tutorial](/tutorial_wrap/050-start.html)

Or alternativly [visit the JAR Wrapping section](https://bnd.bndtools.org/chapters/390-wrapping.html) of the bnd manual.

{: style='clear:both;' }

Expand Down
3 changes: 2 additions & 1 deletion _book/180-examples.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Example Projects
layout: default
layout: prev-next-collection
summary: Some example projects.
---

This section is an entry to the hopefully growing collection of examples that OSGi enRoute provides. If you want to develop an additional example, please submit a PR.
Expand Down
3 changes: 1 addition & 2 deletions _book/210-doc.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
title: About OSGi
summary: Provides an introduction into OSGi and explains how OSGi enRoute uses OSGi
noindex: true
layout: default
layout: prev-next-collection
---

Provides an introduction into OSGi and explains how OSGi enRoute uses OSGi.
Expand Down
3 changes: 2 additions & 1 deletion _book/400-services.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Service Catalog
layout: default
layout: prev-next-collection
summary: Services available in OSGi.
---

This is the OSGi enRoute Base Profile service catalog. The following services are currently available and documented.
Expand Down
1 change: 1 addition & 0 deletions _book/450-osgi-specs.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: OSGi Specifications
summary: Provides an overview of the OSGi Specifications with links
layout: prev-next-collection
---

OSGi technology is a set of
Expand Down
3 changes: 2 additions & 1 deletion _book/680-appnotes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: App Notes
layout: default
layout: prev-next-collection
summary: Application notes are documenting a design or a tool in a way that is useful for people that implement application.
---
Application notes are documenting a design or a tool in a way that is useful for people that implement application. They often show how to do things with the whole system.

Expand Down
3 changes: 2 additions & 1 deletion _book/700-links.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Where to Find Stuff
layout: default
layout: prev-next-collection
summary: List of interesting links
---

## Where to Find Stuff
Expand Down
3 changes: 2 additions & 1 deletion _book/710-videos.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Videos
layout: default
layout: prev-next-collection
summary: Some video tutorials or presentations.
---

<div>
Expand Down
8 changes: 0 additions & 8 deletions _book/800-known-issues.md

This file was deleted.

2 changes: 1 addition & 1 deletion _book/900-faq.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Frequently Asked Questions
layout: default
layout: prev-next-collection
---


Expand Down
6 changes: 6 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ collections:
output: true
doc:
output: true
faq:
output: true
tutorial_base:
output: true
tutorial_rsa:
Expand All @@ -38,6 +40,10 @@ collections:
output: true
tutorial_maven:
output: true
tutorial_wrap:
output: true
videos:
output: true

defaults:
-
Expand Down
2 changes: 2 additions & 0 deletions _data/sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ nav:
external: true
- title: enRoute classic
links:
- name: Introduction
url: "/book/100-introduction.html"
- name: About OSGi
url: "/book/210-doc.html"
urlprefix: "/doc/"
Expand Down
65 changes: 65 additions & 0 deletions _faq/class-not-found-exception.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: What is NoClassDefFoundError?
summary: Explains the consequences of the class loading architecture
---

A very common question for new users of OSGi is as follows:

> “My bundle throws a NoClassDefFoundError on 'org.example.FooBar' even
> though FooBar is on the classpath. What's going on??”

In OSGi, it doesn't even make sense to say that something is “on the
classpath” because **there is no global classpath in OSGi**. Instead,
each bundle has its own isolated class loader. The loader inside each
bundle can *only* load classes that are either inside the bundle, or
*explicitly imported* from another bundle.

The preferred way to import from other bundles is to use
`Import-Package`. You must import **every** package used by your bundle,
with the exception of packages that are already part of your bundle and
packages that begin with “java.” (for example `java.net`, `java.util`
etc... these packages are treated specially by the JRE).

If this sounds like a lot of work, don't worry! Many developers use
[Bnd] to build their bundles, or a tool based on it such as [Bndtools]
or [Maven Bundle Plugin]. All of these tools automatically generate the
`Import-Package` header for your bundle, by inspecting all of the
dependencies in your class files.

Note that if your bundle imports a package, there must be another bundle
installed in the OSGi Framework that exports the same package using the
`Export-Package` header. At runtime the Framework matches each import
with a corresponding export. If it can't find a matching export then
your bundle will fail to resolve. This happens early in the lifecycle of
a bundle, before any code is loaded, so as long as your imports are
correct then you should never see errors like ClassNotFoundException or
NoClassDefFoundError.

### Differences between ClassNotFoundException and NoClassDefFoundError

Both the `ClassNotFoundException` and `NoClassDefFoundError` may be seen
when using Java libraries that try and load classes reflectively. This
typically involves a Java library using `Class.forName` to load a class.

#### ClassNotFoundException

A `ClassNotFoundException` is generated by a call to `Class.forName()`
with a `String` that contains a class not available on the bundle's
class path. Unless the bundle has a
[Import-Package](Import-Package "wikilink") or
[Require-Bundle](Require-Bundle "wikilink") for the package in question
(or a [DynamicImport-Package](DynamicImport-Package "wikilink")), the
runtime will not be able to find the appropriate `.class`.

#### NoClassDefFoundError

A `NoClassDefFoundError` is generated when a class has been found, but
one of its dependencies (typically, that involved in a static
initialiser block) cannot be. For example, if class `A` refers to `B`,
and `B` refers to `C`, then a client looking up A may work, but B (or C)
could be missing. This would generate the error message
`NoClassDefFoundError: A`.

[Bndtools]: http://bndtools.org
[Maven Bundle Plugin]: http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html
[Bnd]: http://bnd.bndtools.org
21 changes: 21 additions & 0 deletions _faq/ds-inheritance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Why does DS Annotations not support inheritance?
summary: It seems logical to inherit the annotations for the bind methods and activate from a super class. This FAQ explains why it is not officially supported so far.
---

Felix Meschberger answered this question very eloquently on a question on the Bndtools list:

> You might be pleased to hear that at the Apache Felix project we once had this feature in our annotations. From that we tried to standardize it actually.
>
> The problem, though, is that we get a nasty coupling issue here between two implementation classes across bundle boundaries and we cannot express this dependency properly using Import-Package or Require-Capability headers.
>
> Some problems springing to mind:
>
> Generally you want to make bind/unbind methods private. Would it be ok for SCR to call the private bind method on the base class ?(It can technically be done, but would it be ok).
> What if we have private methods but the implementor decides to change the name of the private methods — after all they are private and not part of the API surface. The consumer will fail as the bind/unbind methods are listed in the descriptors provided by/for the extension class and they still name the old method names.
> If we don’t support private method names for that we would require these bind/unbind methods to be protected or public. And thus we force implementation-detail methods to become part of the API. Not very nice IMHO.
Note: package private methods don’t work as two different bundles should not share the same package with different contents.
>
> We argued back then that it would be ok-ish to have such inheritance within a single bundle but came to the conclusion that this limitation, the explanations around it, etc. would not be worth the effort. So we dropped the feature again from the roadmap.

This all said, if you still want to try to shoot yourself in the foot: Bnd already supports this with -dsannotations-options: inherit.
21 changes: 21 additions & 0 deletions _faq/unable-to-resolve-missing-false.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Unable to resolve org.example.foo.api version=1.0.0.201603042130 missing requirement false
summary: When the resolver fails to resolve and says the missing requirement is false.
---

The resolve error indicates that the only exporter is the API project but that this project says it should not resolve because in enRoute we highly recommend to include the API package in the provider so a resolution does not just consist of APIs without implementations. If you look in your bnd.bnd file in the org.example.foo.api project then you'll see the following lines:

Require-Capability: \
compile-only

This is a requirement that cannot be resolved. Adding the package to the provider will then make the provider the preferred exporter.

This model (exporting the API from the provider) is explained extensively in the [Base Tutorial][1]. For a more information you can also look in the [bnd manual about versioning][2].

You should there have some org.example.foo.provider bundle that provides the implementation and this should export the API. Exporting it is simple, just drag the package and drop it on the Contents Export list of the provider's `bnd.bnd` file. See the Base tutorial for details.

That said, in the OSGi we now have implementation capabilities and the next OSGi enRoute setup will use those. It is slightly cleaner but also a bit less practical. For now, just export the API from the provider it is the last amount of trouble.


[1]: /tutorial_base/300-api.html
[2]: http://bnd.bndtools.org/chapters/170-versioning.html
15 changes: 15 additions & 0 deletions _faq/unable-to-resolve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Can't Resolve!
summary: What to do when you cannot resolve a bndrun file
---

If you run in the problem that you can't resolve and have a problem understanding, here are some tips.

First, try to resolve ONLY the provider (i.e. is the only requirement in the bndrun file) and see what it says. Likely the provider has a problem. You could also add the bundle that is reported as the last item in the diagnostic information from the resolver in the blacklist in your bndrun file. For example:

-runblacklist.eval: \
osgi.identity;filter:=‘(osgi.identity=com.example.foo.provider)

The resolver will then probably provide the next thing it cannot resolve. Which unfortunately is often quite logical and simple :-(

The resolver is pretty bad in telling what the culprit is. The reason is that it uses back-tracking. So the diagnostics are basically the last thing that was tried.
9 changes: 9 additions & 0 deletions _faq/what-does-osgi-stand-for.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: What does OSGi stand for?
summary: Is it an acronym or a name?
---

It doesn't stand for anything any more, it's just OSGi. Note the
lower-case i when writing the name.


64 changes: 64 additions & 0 deletions _tutorial_wrap/050-start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: JAR Wrapping Tutorial
layout: prev-next-collection
noindex: true
---

This tutorial is under review. Feedback appreciated (PRs on [Github](https://github.com/bndtools/bndtools.github.io/tree/master/_tutorial_wrap))
{: .note }

## Why to wrap JAR files?

OSGi developers face a challenge when using third-party libraries that are not supplied as OSGi bundles. Though an increasing number of libraries are available from their original sources as OSGi bundles, and a large number are available as wrapped OSGi bundles from external repositories, it is still sometimes necessary to build such a wrapper ourselves. This tutorial details an approach to OSGi bundle production using bnd/bndtools/gradle.

## What you learn in this tutorial.

In this quick start we learn how to _wrap_ a JAR to become a Bundle. Wrapping a JAR means that we need add the required OSGi manifest headers but also _design_ the contents of the bundle. Modularity is not about fences, modularity is about what you put inside those fences and what passages you allow. The bnd tool provides an overwhelming amount of instructions and features to create the Bundle you want; this tutorial tries to shine light on what forces are in play and what tools are available.

This tutorial teaches the wrapping from the perspective of a Bndtools user. For any command line zealots this should not be too hard to map to `vi` since all we do is write a `bnd.bnd` file in Bndtools, which is also usable in for example Maven. The key advantage of Bndtools is that it shows you the missing packages interactively. If you want to stay on the command line, then you could take a look at [bnd Wrapping](https://bnd.bndtools.org/chapters/390-wrapping.html).

In the coming chapters it is assumed you have a workspace ready. If you've no clue what we're talking about suggest you follow the [Quick Start] tutorial first.

**A disclaimer.** This wrapping tutorial is about learning to use wrapping bundles inside the OSGi enRoute tool chain, it is not about learning Java, Git, nor Eclipse. It is assumed that you have basic experience with these tools and that you have at least followed the [Quick Start] tutorial.

If you're just interested in the end result, you can look at the (archived) [osgi.enroute.examples.wrapping.dom4j.adapter] project.

If you have any questions about this wrapping tutorial, please discuss them in the [Forum].

## Sections

<div>
<table>
<colgroup>
<col style="width:50%">
<col style="width:50%">
</colgroup>
<tbody>
{% for qs in site.tutorial_wrap %}{%unless qs.noindex%}<tr><td><a href="{{qs.url}}">{{qs.title}}</a></td><td>{{qs.summary}}</td></tr>
{%endunless%}{% endfor %}
</tbody>
</table>
</div>


## End

So, you've finished this wrapping tutorial! What's next?

Well, first, since we're still in beta, we'd love feedback. Our most favorite feedback is a pull request on the documentation. We, and others like you, highly appreciate these kind of contributions.

If you've become interested in what bnd can do for you, then you could look at the [wrapping with bnd] chapter in the bnd manual.

However, running into real problems is the best way to learn a technology. If you run into problems, use the [Forum] to ask questions and get answers.

[forum]: https://bnd.discourse.group/
[Quick Start]: /qs/050-start
[wrapping with bnd]: https://bnd.bndtools.org/chapters/390-wrapping.html
[-conditionalpackage]: https://bnd.bndtools.org/instructions/conditionalpackage.html
[133 Service Loader Mediator Specification]: https://blog.osgi.org/2013/02/javautilserviceloader-in-osgi.html
[semanticaly versioned]: https://bnd.bndtools.org/chapters/170-versioning.html
[135.3 osgi.contract Namespace]: https://blog.osgi.org/2013/08/osgi-contracts-wonkish.html
[BSD style license]: https://dom4j.sourceforge.net/dom4j-1.6.1/license.html
[supernodes of small worlds]: https://en.wikipedia.org/wiki/Small-world_network
[OSGiSemVer]: https://www.osgi.org/wp-content/uploads/SemanticVersioning.pdf
[osgi.enroute.examples.wrapping.dom4j.adapter]: https://github.com/osgi/osgi.enroute.examples/tree/485624f6cb66df91f668d6eb9a5c8e491312c8c4/osgi.enroute.examples.wrapping.dom4j.adapter
Loading