FriendDependencies

From APIDesign

(Difference between revisions)
Jump to: navigation, search
(NetBeans Friends Support)
Current revision (08:42, 11 November 2011) (edit) (undo)
(No Class Error!?)
 
(15 intermediate revisions not shown.)
Line 1: Line 1:
-
Concept of '''friends''' is almost essential for [[Modularity]]. Not all exported [[API]]s are stable enough, not all of them are ready for public consumption. In such case one needs to create a [[module]], define its [[API]], but restrict list of '''friends''' that may access it.
+
Concept of '''friends''' is almost essential for [[modularity]]. Not all exported [[API]]s are stable enough, not all of them are ready for public consumption. In such case one needs to create a [[module]], define its [[API]], but restrict list of '''friends''' that may access it.
== [[NetBeans]] Friends Support ==
== [[NetBeans]] Friends Support ==
-
The [[NetBeans Runtime Container]] has first class support for '''friends'''. Inside manifest one can enumerate the names of modules that may access given [[API]]. Surprisingly, this list of '''friends''' is an [[API]] of the module itself. In case you change the list, you are changing the module [[API]] and you need to properly [[netbeans:VersioningPolicy|version]] such change.
+
The [[NetBeans Runtime Container]] has first class support for '''friends''' concept. Every module can, inside its manifest, enumerate the programatic names of modules that may access given [[API]]. Surprisingly, this list of '''friends''' is an [[API]] of the module itself. In case you change the list, you are changing the module [[API]] and you need to properly [[netbeans:VersioningPolicy|version]] such change.
-
Recently we had to deal with a bug [http://netbeans.org/bugzilla/show_bug.cgi?id=201021 201021] - suddenly one module was getting {{JDK|java/lang|NoClassDefFoundError}} when trying to access a ''LexerUtils'' class from another module. The ''LexerUtils'' class existed since the creation of its module, so it was a mistery for all of us. How could a class not be found, if it exists for ages?
+
=== No Class Error!? ===
 +
 
 +
Recently we had to deal with a bug [http://netbeans.org/bugzilla/show_bug.cgi?id=201021 201021] - suddenly one module was getting {{JDK|java/lang|NoClassDefFoundError}} when trying to access a ''LexerUtils'' class from another module. The ''LexerUtils'' class existed since the creation of its module, so it was a mystery for all of us. How could a class not be found, if it exists for ages?
''Is the installation corrupted?'' was our first question. No, it was not. We received the same report from multiple users. Thus we could rule out random corruption error. Something in our shared infrastructure must have been broken.
''Is the installation corrupted?'' was our first question. No, it was not. We received the same report from multiple users. Thus we could rule out random corruption error. Something in our shared infrastructure must have been broken.
-
''Is there are problem in initialized?'' is a second question to ask. Sometimes, when a class throws an exception from one of its static initializers, it becomes unavailable for the [[JVM]]. Later, if any other class references the broken one, a {{JDK|java/lang|NoClassDefFoundError}} is generated at very unexpected places. However this was not the problem either. There was no other exception in the log files!
+
''Is there a problem in an initializer?'' is a second question to ask. Sometimes, when a class throws an exception from one of its static initializers, it becomes unavailable to the [[JVM]]. Later, if any other class references the broken one, a {{JDK|java/lang|NoClassDefFoundError}} is generated at very unexpected places. However this was not the problem either. There was no other exception in the log files!
-
A complete mistery.
+
A complete mystery.
=== Friends are [[API]]! ===
=== Friends are [[API]]! ===
-
It turns out that one new module (let's call it '''uses.lexer.utils''') needed to access this '''friend''' [[API]] and his developer just added it to the list of friends:
+
It turned out that one new module (let's call it '''uses.lexer.utils''') needed to access this '''friend''' [[API]] and his developer just added it to the list of friends:
-
<source lang="properties">
+
<source lang="bash">
OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-SpecificationVersion: 1.1
OpenIDE-Module-SpecificationVersion: 1.1
Line 23: Line 25:
</source>
</source>
-
Everything used to work in a local instalation, but in a highly [[distributed deployment]] environment, we soon received bug reports.
+
Everything used to work in a local instalation, but in a highly [[Incremental deployment]] environment, we soon received bug reports.
Line 32: Line 34:
Remember, when you expand the list of friends, that you are changing the [[API]] of the module and you need to release new version of it:
Remember, when you expand the list of friends, that you are changing the [[API]] of the module and you need to release new version of it:
-
<source lang="properties">
+
<source lang="bash">
OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-SpecificationVersion: '''1.2'''
OpenIDE-Module-SpecificationVersion: '''1.2'''
Line 38: Line 40:
</source>
</source>
-
The '''uses.lexer.utils''' then needs to requests '''provides.lexer.utils''' in version '''1.2'''. List of [[FriendDepenedencies|friends]] is your [[API]]!
+
The '''uses.lexer.utils''' then needs to requests '''provides.lexer.utils''' in version '''1.2'''. List of [[FriendDependencies|friends]] is your [[API]]!
== Notes ==
== Notes ==
-
Btw. removing someone from list of '''friends'' is basically incompatible change in your [[API]] and you should produce incompatible version of your module.
+
Btw. removing someone from list of '''friends''' is basically incompatible change in your [[API]] and you should produce incompatible version of your module.
Can this happen in [[OSGi]]? Well, [[OSGi]] by itself does not have support for '''friends''' now, so no. But [[Equinox]] provides an extended functionality to support this concept and yes, you'd run into same issues there.
Can this happen in [[OSGi]]? Well, [[OSGi]] by itself does not have support for '''friends''' now, so no. But [[Equinox]] provides an extended functionality to support this concept and yes, you'd run into same issues there.
[[Category:APITypes]]
[[Category:APITypes]]

Current revision

Concept of friends is almost essential for modularity. Not all exported APIs are stable enough, not all of them are ready for public consumption. In such case one needs to create a module, define its API, but restrict list of friends that may access it.

Contents

NetBeans Friends Support

The NetBeans Runtime Container has first class support for friends concept. Every module can, inside its manifest, enumerate the programatic names of modules that may access given API. Surprisingly, this list of friends is an API of the module itself. In case you change the list, you are changing the module API and you need to properly version such change.

No Class Error!?

Recently we had to deal with a bug 201021 - suddenly one module was getting NoClassDefFoundError when trying to access a LexerUtils class from another module. The LexerUtils class existed since the creation of its module, so it was a mystery for all of us. How could a class not be found, if it exists for ages?

Is the installation corrupted? was our first question. No, it was not. We received the same report from multiple users. Thus we could rule out random corruption error. Something in our shared infrastructure must have been broken.

Is there a problem in an initializer? is a second question to ask. Sometimes, when a class throws an exception from one of its static initializers, it becomes unavailable to the JVM. Later, if any other class references the broken one, a NoClassDefFoundError is generated at very unexpected places. However this was not the problem either. There was no other exception in the log files!

A complete mystery.

Friends are API!

It turned out that one new module (let's call it uses.lexer.utils) needed to access this friend API and his developer just added it to the list of friends:

OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-SpecificationVersion: 1.1
OpenIDE-Module-Friends: old.friend.one, old.friend.two, '''uses.lexer.utils'''

Everything used to work in a local instalation, but in a highly Incremental deployment environment, we soon received bug reports.


The problem is that some users managed to update only the uses.lexer.utils module but still kept the old version of provides.lexer.utils. The result? A code from uses.lexer.utils tried to access LexerUtils class, but the access to that class was rejected as the old version of provides.lexer.utils did not know that uses.lexer.utils is a friend!

Version Friends List

Remember, when you expand the list of friends, that you are changing the API of the module and you need to release new version of it:

OpenIDE-Module-Module: provides.lexer.utils
OpenIDE-Module-SpecificationVersion: '''1.2'''
OpenIDE-Module-Friends: old.friend.one, old.friend.two, uses.lexer.utils

The uses.lexer.utils then needs to requests provides.lexer.utils in version 1.2. List of friends is your API!

Notes

Btw. removing someone from list of friends is basically incompatible change in your API and you should produce incompatible version of your module.

Can this happen in OSGi? Well, OSGi by itself does not have support for friends now, so no. But Equinox provides an extended functionality to support this concept and yes, you'd run into same issues there.

Personal tools
buy