dev@glassfish.java.net

Re: Why we use DynamicImport-Package?

From: Richard S. Hall <heavy_at_ungoverned.org>
Date: Thu, 28 Aug 2008 09:27:17 -0400

Sahoo wrote:
> [Subject has been changed to reflect the topic being discussed]
>
> Richard S. Hall wrote:
>> Sahoo wrote:
>>> Richard S. Hall wrote:
>>>> If that is the case, then I am in agreement with you, it doesn't
>>>> make sense that it could not load private classes from the bundle.
>>>>
>>>> Still, I do have some concerns about loading from exported
>>>> packages. Does this mean that it uses DynamicImport-Package or is
>>>> it just analyzing the bundle export metadata?
>>> DynamicImport-Package.
>>
>> Hmm. Well, that is not what I would recommend,
>
> I was anticipating a reply regarding use of DynamicImport-Package.
> Thanks for raising it. I should have mentioned that we used
> DynamicImport-Package in special circumstances only. None of our
> server implementation bundles use DynamicImport-Package. Then, who
> uses DynamicImport-Package? In a nutshell, it is used by a special
> OSGi bundle that's only used in the context of deployed applications -
> these applications are not OSGi bundles. More details given below:
>
> As discussed in V3/OSGi one-pager [1], we have two kinds of artifacts
> deployed in the server runtime, viz: a) several OSGi bundles
> implementing the GlassFish runtime as well additional user supplied
> OSGi bundles, b) applications (typically Java EE applications)
> deployed in the server runtime. These applications are not OSGi
> bundles, so they can *not* directly interact with OSGi runtime unless
> we convert them to OSGi bundles. Although there are a lot of
> similarities between Java EE deployment artifacts (ear/war/jar) and
> OSGi bundles, there are significant differences as well. Converting
> Java EE applications to OSGi bundles was considered, but the
> technique/principles are not solid enough to be put in production yet.
> So, it is still in experimental mode. We are going to work with OSGi
> EEG on specifying this first.
>
> In the short term, the approach that has been taken so far is that
> OSGi platform provides a basic runtime for GlassFish bundles.
> GlassFish bundles provide the necessary runtime to the applications.
> So, it can be thought of as a runtime inside a runtime. In addition to
> managing the lifecycle of deployed applications, one of the key
> functionalities provided by GlassFish runtime to the deployed
> applications is to create a class loader hierarchy for every
> application. While creating such a class loader, we have to be not
> only compliant with the class loading requirements of the Java EE
> platform, we also have to be backward compatible with earlier versions
> of GlassFish. The class loader hierarchy (as in class loading
> delegation hierarchy) for applications looks something like this (I
> have removed some elements that are not needed for this discussion):
>
> archive class loader [H]
> -> common class loader [D]
> -> public API class loader [C]
> -> classloader that loads Felix
> -> extension class loader [B]
> -> null (a.k.a. bootstrap class
> loader) [A]
>
> Description of each element of the above delegation chain is given below:
>
> A & B are JRE supplied class loaders.
>
> C. public API class loader:
> It is this class loader that makes available all the META-INF/services
> resources and service implementation classes that are discovered using
> the extender pattern. It also makes available all classes
> exported by OSGi bundles installed in the runtime. This typically
> includes,
> but not limited to, Java EE APIs and other GlassFish APIs that we want
> applications to have access to. Currently, our server OSGi bundles
> pretty much expose
> every package for public use. This should be fixed as described in
> https://glassfish.dev.java.net/issues/show_bug.cgi?id=5385.
> This class loader is implemented as a simple delegation pattern: it
> basically delegates to an OSGi Bundle which
> has following import statement:
> DynamicImport-Package: *
>
> We let OSGi framework ensure that the class space for such a bundle is
> consistent. We felt this simple technique helps us in providing a
> consistent class space for applications in a dynamic environment like
> GFv3, where new capabilities can be added as post-installation
> activity. No other server implementation code uses this special OSGi
> bundle.
>
> D. common class loader:
> This is responsible for making available libraries and
> classes installed in following places (in the order mentioned below):
> glassfish_home/lib/, domain/classes/, domain/lib/. These are libraries
> which are plain old jar files. They are shared by all applications.
> This is needed for backward compatibility reasons.
>
> H. archive class loader:
> Responsible for loading classes from application archive (a
> .jar/.war/.ear file). It is created for every application,as Java EE
> spec mandates every archive to have a separate class space.
>
> Now that I have told where and how we use DynamicImport-Package, let's
> get back to the some of the issues raised by you. See reply below...

Interesting details. Thanks.

>> because this will limit what it can see, for example, it could not
>> deal with two different versions of the same package since this
>> approach actually creates a wire to the exporter. Although this might
>> not be a current use case, you never know about future use cases.
> If we were able to map an application an OSGi bundle, could that OSGi
> bundle consume more than one version of same package? We don't
> constrain all our server OSGi bundles to use same version of the
> package. They don't use Require-Bundle, nor do they use
> DynamicImport-Package, so different bundles can use different package
> versions and we let OSGi framework figure out if there is any
> inconsistent class space. With my earlier explanation about where we
> use DynamicImport..., this should not be an issue any more, right?

A single bundle can never see different versions of the same package,
which is the result of the package wiring we are discussing. The issue I
was referring to was with respect to the extender bundle itself. From my
understanding, it creates instances of service implementations for other
bundles to use. If you ever had a situation where two different
application needed two different versions of the same service, then the
extender bundle would not be able to make this happen if it wires to the
service implementation package.

However, if I understand correctly, because [C] makes all exported
classes available to all applications then you do not expect them to
ever use different versions of the same service (it looks like you
assume that all applications use the same versions of every package). In
the short term then, this is probably not an issue, but if you converted
your applications to bundles, you would probably want to revisit [C],
which maybe you already anticipated.

>> Further, this means that the extender becomes dependent upon the
>> exporter so if the exporter is uninstalled or updated and then
>> refreshed, then the extender bundle will have to be refreshed too.
> Yes.
>>
>> Following the extender approach, you could probe for exported
>> packages too and then delegate to Bundle.loadClass() based on who
>> exports what, this won't create a wire to the exporting bundle.
>>
> I am confused. One of our primary requirement is to have a class
> loader hierarchy that provides a consistent class space, which means
> we can't violate any of the loader constraints. If we don't create
> wires, are we not going to violate temporal namespace consistency?
> e.g., at time t, if we used bundle b to load class C, then at time
> t+1, we must use the same bundle to load the same class, right? If we
> allow B to be uninstalled, then we won't be able to find C any more,
> thus violating the temporal consistency rule.

I am not sure I understand the issue that you are raising. If the
extender bundle needs to do clean up work when a bundle it is managing
is uninstalled, then it must listen for the appropriate events.

>> Just some thoughts.
>>
> Thanks for sharing them. I hope I have been able to share some of our
> implementation details with regards to use of OSGi. I would be glad to
> discuss it further if you want. That will be good exercise for GlassFish.

I think I have a better understanding now. I will file this message. :-)

-> richard

>
> Thanks,
> Sahoo
>
> [1]
> http://wiki.glassfish.java.net/attach/V3FunctionalSpecs/GFv3Prelude-OSGi-onepager-v0.2.txt
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>