0

I don't know if what I am doing is the OSGi and Maven way, so first some background:

I have two bundles web and client. In the client bundle, I want to access a service that the web bundle registers. I have already checked that I can implement BundleContextAware in the client bundle and if the web bundle's ArtifactId is project.web then the following works:

public void setBundleContext(BundleContext bc) {
    bc.getServiceReferences(clazz, "(Bundle-SymbolicName=project.web)")

What I would like to is not hard-code the symbolic name of the web bundle. The symbolic name comes from the artifactId declared in pom.xml, I believe by some gemini-blueprint magic. So my current thought is

  • create a property web.artifactId in parent pom
  • in web bundle's pom use <artifactId>${web.artifactId}</artifactId>
  • somehow access that property in client bundle's BundleContextAware.setBundleContext

How do I do this last step? I guess it might be possible to generate a java file at run-time that assigns the property value to some known identifier, so I can use WebBundleInfo.ARTIFACT_ID; but I don't know how to do that and wonder if that is an overkill.

Another thought is if there is a way that the client bundle can use System.getProperty to access this value? I saw some references to accessing a property file but I am not very keen on it -- neither on reading a property file, nor on generating it.

So my questions are: - Is this is a good way to share a bundle's symbolic-name like this? - Is there a away to automatically make some properties created in pom file available to the run-time execution environment? - I guess I could figure out how to generate such a source file, but is that a good way to solve this? Is there a way to generate such a file without a source file, i.e. from some text in the pom.xml itself? Further, is it possible to overwrite the existing file only if it has changed so as to avoid recompilation, because that will end up in a new snapshot version after every compile?

nadirsaghar
  • 557
  • 1
  • 4
  • 20
Miserable Variable
  • 28,432
  • 15
  • 72
  • 133

1 Answers1

2

The easiest way to set variables at compile time is to make sure they end up in the manifest of the bundle. Like you say, the Bundle-SymbolicName already does. For the client bundle, you should probably create a new, custom header that contains your variable. Then, from your client bundle, you could do something like this:

public void setBundleContext(BundleContext bc) {
  String filter = (String) bc.getBundle().getHeaders().get("MyCustomHeader");
  bc.getServiceReferences(clazz, filter);
}

That being said, could you explain a bit more about what you're trying to do (at a higher level) because I fail to see why you're not just using OSGi services and dependencies (using Declarative Services, Blueprint, or some other dependency injection framework)?

Marcel Offermans
  • 3,313
  • 1
  • 15
  • 23
  • This seems to be what I am looking for. How do I get something to end up in the bundle manifest? There are many bundles in the container, of which I want a contract between the web and client bundle and have the client bundle get reference to a service registered by the web bundle. In the java code in client bundle, I don't want to hard-code the symbolic name of the web bundle. – Miserable Variable Jun 10 '13 at 20:37
  • Assuming you're using the Apache Felix "maven-bundle-plugin", you can add your custom header to the instructions in your pom.xml: (someKey=someValue) – Marcel Offermans Jun 10 '13 at 20:57
  • Perfect. I used `${web.artifactId}` in web bundle and `${web.artifactId}` in maven-bundle-plugin instructions. Can you please comment if this is a bad thing to get to other bundles by their names? – Miserable Variable Jun 10 '13 at 21:07
  • Bundles have a symbolic name to uniquely identify them. In general though, in OSGi it is considered bad practice to directly depend on specific bundles (or their names). That creates a direct coupling between two bundles, and does not allow you to easily substitute one bundle with another (without also changing the consumer itself). So if you can prevent that, that would be good. You are aware that you can also publish a service with certain properties, and that you can use those properties again to select a service, if are multiple implementing the same interface. – Marcel Offermans Jun 10 '13 at 21:46
  • I was vaguely aware but didn't realize I could use that. Thanks for suggestion. – Miserable Variable Jun 10 '13 at 22:42