felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Richard S. Hall" <he...@ungoverned.org>
Subject Re: Fragment bundles and Bundle-Classpath of host
Date Thu, 15 Mar 2012 13:20:57 GMT
Well, given your last message I was going to suggest that this was an 
issue with your imports in your fragment, but it seems that you 
discovered this below. Yeah, I don't know how bnd supports creating 
fragments, but you definitely shouldn't have to include what is on the 
class path of the host bundle, because you get that by default.

-> richard

On 3/15/12 05:14 , Christopher BROWN wrote:
> I've just found a "hack" solution that avoids having to export the
> "freemarker.template.*" package from the main bundle's bundle
> classpath.
>
> I tweaked the Import-Package directive in the fragment bundle (the
> ".bnd" file, to be specific) so that it imports
> "freemarker.template.*;resolution:=optional" (adding optional
> resolution).  It works, but it just seems like a hack.  I'm guessing
> there should be some way to tell ".bnd" to accept the bundle classpath
> without requiring that it be duplicated into the fragment.  Maybe I'm
> wrong, maybe it doesn't exist, or maybe it does (and I just don't know
> where to find documentation for that feature).
>
> I tried:
> http://www.aqute.biz/Blog/2007-02-19
> ...but it discussed adding to the bundle-classpath with fragments, not
> referring to classes on the host's bundle classpath.
>
> Thanks,
> Christopher
>
>
>
> On 15 March 2012 09:58, Christopher BROWN<brown@reflexe.fr>  wrote:
>> Hello,
>>
>> So, I have the bundle "B" which contains lib/freemarker.jar ("F" for
>> short) in the Bundle-Classpath, and a fragment for testing "T" which
>> declares "B" as the fragment host.
>>
>> When I don't have the export directive in the manifest of "B", when I
>> try to USE (compiling and BND usage is OK) it, I get this output for
>> my JUnit test runner:
>> ________________________________________
>>
>> Failed to load "viewer.system.themes.freemarker.TestFM_T001" from
>> bundle system.themes-freemarker [11]
>> (java.lang.ClassNotFoundException: *** Class
>> 'viewer.system.themes.freemarker.TestFM_T001' was not found. Bundle
>> system.themes-freemarker [11] does not import package
>> 'viewer.system.themes.freemarker', nor is the package exported by any
>> other bundle or available from the system class loader. ***).
>> Failed to load "viewer.system.themes.freemarker.TestFM_T002" from
>> bundle system.themes-freemarker [11]
>> (java.lang.ClassNotFoundException: *** Class
>> 'viewer.system.themes.freemarker.TestFM_T002' was not found. Bundle
>> system.themes-freemarker [11] does not import package
>> 'viewer.system.themes.freemarker', nor is the package exported by any
>> other bundle or available from the system class loader. ***).
>> Failed to load "viewer.system.themes.freemarker.TestFM_T003" from
>> bundle system.themes-freemarker [11]
>> (java.lang.ClassNotFoundException: *** Class
>> 'viewer.system.themes.freemarker.TestFM_T003' was not found. Bundle
>> system.themes-freemarker [11] does not import package
>> 'viewer.system.themes.freemarker', nor is the package exported by any
>> other bundle or available from the system class loader. ***).
>> ________________________________________
>>
>> As I said, I use BND (version 0.0.384) -- incidentally, I'm using
>> Felix 3.2.2 as I'm deferring the upgrade to 4.x until I have time to
>> get the hang of compiling from source using Java 6 -- and for
>> information, here's the ".bnd" files".
>>
>> First, for bundle "B" (note the commented-out #Export directive which
>> I enable to make it work) ; also the Bundle-Classpath.
>> ________________________________________
>>
>> Bundle-Version:   0.6.0
>> Bundle-RequiredExecutionEnvironment: JavaSE-1.6
>> Bundle-Activator: viewer.system.themes.freemarker.FmBundleActivator
>> Private-Package:  viewer.system.themes.freemarker.*
>> Import-Package:
>> org.osgi.framework;version="1.5",org.osgi.*,org.slf4j,fr.reflexe.viewer.api.*;version="[0.6,2.0)",javax.el.*;resolution:=optional,javax.servlet.*;resolution:=optional,javax.swing.*;resolution:=optional,javax.xml.*;resolution:=optional,com.sun.org.apache.*;resolution:=optional,org.apache.commons.logging.*;resolution:=optional,org.apache.log.*;resolution:=optional,org.apache.log4j.*;resolution:=optional,org.apache.tools.ant.*;resolution:=optional,org.apache.xml.*;resolution:=optional,org.apache.xpath.*;resolution:=optional,org.dom4j.*;resolution:=optional,org.jaxen.*;resolution:=optional,org.jdom.*;resolution:=optional,org.mozilla.*;resolution:=optional,org.python.*;resolution:=optional,org.slf4j.spi.*;resolution:=optional,org.w3c.dom.*;resolution:=optional,org.xml.*;resolution:=optional,org.zeroturnaround.javarebel.*;resolution:=optional
>> #Export-Package:   freemarker.*;version=2.3.19
>> Bundle-ClassPath: ., lib/freemarker.jar
>> Include-Resource: lib=lib
>> -removeheaders: Include-Resource, TODAY, EXEC_LOG_LEVEL, TEST_LOG_LEVEL
>> ________________________________________
>>
>>
>> Then, for fragment "T" which declares "B" as its host:
>> ________________________________________
>>
>> Bundle-Version: 0.6.0
>> Bundle-RequiredExecutionEnvironment: JavaSE-1.6
>> Private-Package: viewer.system.themes.freemarker.*
>> Import-Package:
>> org.osgi.framework;version="1.5",org.osgi.*,org.slf4j,fr.reflexe.viewer.api.*;version="[0.6,2.0)",javax.el.*;resolution:=optional,javax.servlet.*;resolution:=optional,javax.swing.*;resolution:=optional,javax.xml.*;resolution:=optional,com.sun.org.apache.*;resolution:=optional,org.apache.commons.logging.*;resolution:=optional,org.apache.log.*;resolution:=optional,org.apache.log4j.*;resolution:=optional,org.apache.tools.ant.*;resolution:=optional,org.apache.xml.*;resolution:=optional,org.apache.xpath.*;resolution:=optional,org.dom4j.*;resolution:=optional,org.jaxen.*;resolution:=optional,org.jdom.*;resolution:=optional,org.mozilla.*;resolution:=optional,org.python.*;resolution:=optional,org.slf4j.spi.*;resolution:=optional,org.w3c.dom.*;resolution:=optional,org.xml.*;resolution:=optional,org.zeroturnaround.javarebel.*;resolution:=optional,freemarker.template.*,junit.framework,viewer.system.test.*;version="[0.6,2.0)"
>> -removeheaders: Include-Resource, TODAY, EXEC_LOG_LEVEL, TEST_LOG_LEVEL
>> Fragment-Host: system.themes-freemarker; bundle-version="0.6.0"
>> ________________________________________
>>
>> If it's any use, I can provide the resulting MANIFEST.MF files (but
>> they're a bit big, due to all the packages in freemarker.jar, when I
>> enable the export directive).
>>
>> If I drop (for the .bnd file for the test fragment) the Import-Package
>> value "freemarker.template.*", BND chokes with this message:
>>       [bnd] Unresolved references to [freemarker.template] by class(es)
>> on the Bundle-Classpath[Jar:dot]:
>> [viewer/system/themes/freemarker/MockStringModel.class]
>>       [bnd] /Users/cbr/dev/build/temp/Viewer/0.6.0/bnd-tmp/themes-freemarker/fragment/system.themes-freemarker-test-fragment.bnd:
>> bnd failed
>>
>> That's why I added the "import" in the fragment, but I can't see how
>> to avoid this (in other words, tell BND that it's OK, it'll magically
>> find the freemarker packages when the fragment is merged with the host
>> which has all that stuff in private packages available from the bundle
>> classpath).
>>
>> For completeness, here's the source code for the class that BND
>> complains about in the above error message:
>> ________________________________________
>>
>> package viewer.system.themes.freemarker;
>>
>> import java.util.ArrayList;
>> import java.util.List;
>> import freemarker.template.TemplateModelException;
>> import freemarker.template.TemplateScalarModel;
>>
>> public class MockStringModel implements TemplateScalarModel
>> {
>>   private final String _value;
>>
>>   static List<TemplateScalarModel>  args(String... args)
>>   {
>>     List<TemplateScalarModel>  list = new
>> ArrayList<TemplateScalarModel>(args.length);
>>     for (String arg : args)
>>     {
>>       list.add(new MockStringModel(arg));
>>     }
>>     return list;
>>   }
>>
>>   MockStringModel(String value)
>>   {
>>     assert value != null;
>>     _value = value;
>>   }
>>
>>   @Override
>>   public String getAsString() throws TemplateModelException
>>   {
>>     return _value;
>>   }
>> }
>> ________________________________________
>>
>> As you can see, the class (from my test fragment bundle) DIRECTLY
>> refers to classes from FreeMarker in order to create a mock object
>> required by a test case, specifically:
>>
>> ________________________________________
>>
>> public void test001_PlainFunctionAdapter() throws Exception
>> {
>>   MockFunction tf = new MockFunction("fn");
>>   MockDataContext td = new MockDataContext();
>>   FunctionAdapter fa = new FunctionAdapter((ITemplateFunction)tf, td);
>>
>>   assertEquals(tf.getName(TEMPLATE_SYSTEM_NAME), fa.getName());
>>   assertEquals(0, fa.getUsageCount());
>>   assertEquals("fn( [foo, bar] )", fa.exec(MockStringModel.args("foo", "bar")));
>>   assertEquals(1, fa.getUsageCount());
>> }
>> ________________________________________
>>
>> If I drop the use of "MockStringModel" and comment out the direct
>> references to FreeMarker, it works.  I use a similar approach for
>> other bundles, with bundle classpaths and so on; the problem only
>> occurs here because of the mock object's direct use of classes on the
>> bundle classes (I need it here to build callback-style test cases).
>>
>> Thanks,
>> Christopher
>>
>>
>>
>> On 14 March 2012 14:06, Richard S. Hall<heavy@ungoverned.org>  wrote:
>>> On 3/14/12 05:00 , Neil Bartlett wrote:
>>>> It certainly is possible to use fragments this way, it fact it's almost
>>>> the sole purpose of fragments. So there must be something else going on.
>>>> Please show what kind of error messages you're seeing.
>>>
>>> Agree with Neil. Fragment classes are loaded by the same class loader as the
>>> classes in the host to which they are attached, so they should have the same
>>> visibility to other classes.
>>>
>>> ->  richard
>>>
>>>
>>>> Rgds Neil
>>>>
>>>> Sent from my iPhone
>>>>
>>>> On 14 Mar 2012, at 08:35, Christopher BROWN<brown@reflexe.fr>    wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> The software I'm creating uses Felix to separate one API bundle (a set
>>>>> of "official" interfaces) from various implementation bundles.
>>>>> Generally, to discourage customers (who aren't OSGi experts) from
>>>>> creating dependencies on JARs upon which we require, as we want to be
>>>>> able to keep them as hidden implementation details that we're free to
>>>>> change over time.  There's only a few JARs we've " promoted" or shared
>>>>> as proper bundles.
>>>>>
>>>>> Our testing strategy involves binding fragment bundles with tests, and
>>>>> I hit a problem, given the approach outlined above. In short, although
>>>>> the fragment bundle is in the same package, it doesn't seem possible
>>>>> to share access to the Bundle-Classpath without exporting from the
>>>>> host and importing it from the Fragment. It's therefore available to
>>>>> world+dog as an unwanted side effect, and yet I thought Fragments were
>>>>> supposed to share classloader access with the host..?
>>>>>
>>>>> Is there another way to do this without having to export "private
>>>>> dependency JARs"?
>>>>>
>>>>> Thanks,
>>>>> Christopher
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Mime
View raw message