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<br...@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<he...@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<br...@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-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org



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

Reply via email to