Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Virgo » OSGI bundle dependencies
OSGI bundle dependencies [message #671393] Tue, 17 May 2011 17:55 Go to next message
rshelley  is currently offline rshelley Friend
Messages: 59
Registered: April 2010
Member
I'm having some trouble with OSGI bundle dependencies and I can't tell if it's something wrong with my idea of bundles, or if I'm just not configured properly.

I have two bundles, BundleA (a WAR) and BundleB (a JAR). Both bundles are Maven projects, so BundleB has a compile dependency on BundleA (for the interface).

BundleA defines an interface and exports the package for the interface (I can see the exported package in Virgo).

BundleB imports the package from BundleA and has an implemented service based upon the interface in BundleA.

The goal is to have BundleA define some interfaces it supports, and BundlesB/C/D/... implement those services so they can be registered into BundleA as they are loaded.

However, BundleB gets a ClassNotFoundException for the interface that's defined in BundleA (even though the package is exported from A and imported by B). BundleB can't include the interface's Class files either because it's a JAR and doesn't include other JARs from dependencies.

Am I just not thinking about the bundles correctly, or is something just not configured properly?

My goal is to have a core application that listens for specific services to come and go. When they are loaded, I want to add those services to a list of active services the core application can work with, and I want those services to be well defined by the core application (so if a UserLookupService is registered, the core application knows what methods can be called on it).

Should the interface come from the service being registered, or should it come from my core application that defines the scope of the services being registered?
Re: OSGI bundle dependencies [message #671405 is a reply to message #671393] Tue, 17 May 2011 18:50 Go to previous messageGo to next message
Brad Chen is currently offline Brad ChenFriend
Messages: 7
Registered: April 2011
Junior Member
If I understand the concept of OSGi correctly, this design leads to cyclic dependency between bundles. BundleB uses BundleA for the interface, and BundleA uses BundleB for the implementation. To solve the problem, you could introduce an API bundle for the public interfaces shared by the bundles, so that BundleA and BundleB don't need to depend on each other.
Re: OSGI bundle dependencies [message #671410 is a reply to message #671405] Tue, 17 May 2011 19:12 Go to previous messageGo to next message
rshelley  is currently offline rshelley Friend
Messages: 59
Registered: April 2010
Member
I tried that too... I tried creating a client bundle, lets call it BundleC... I then set BundleA (web bundle) to import the package exported from BundleC, and BundleB (jar) also importing the package exported from BundleC... I still get no love.

In my original example, I don't have BundleA depending on BundleB. I have BundleA defining the interface to which BundleB implements. BundleA doesn't know about BundleB, but it waits listening for bundles to be registered that use the interface defined in BundleA. Maybe this is the wrong approach, but I haven't really seen a great example of how all this SHOULD work, just minimalist examples where everyone says "this isn't the right way, just quickest for the tutorial." In some cases, they include a JAR in a JAR (the client JAR with the interfaces in the implementation's JAR) and that kinda seems odd since (I thought) the point of exporting packages was to make it so other bundles can import and use them (so BundleA could export the interface and BundleB could use it without having to include the interface in BundleB's JAR).
Re: OSGI bundle dependencies [message #671418 is a reply to message #671410] Tue, 17 May 2011 19:33 Go to previous messageGo to next message
Brad Chen is currently offline Brad ChenFriend
Messages: 7
Registered: April 2011
Junior Member
Do you mind posting a few lines of code? Being able to see how services are published in BundleB, and how bundle manifests are set up would really help.

If you are looking for examples, Virgo's GreenPages is a good start. OSGi in Action from Manning (http://www.manning.com/hall/) also has good examples on setting up an OSGi project with movable parts.

[Updated on: Tue, 17 May 2011 19:36]

Report message to a moderator

Re: OSGI bundle dependencies [message #671421 is a reply to message #671393] Tue, 17 May 2011 19:53 Go to previous messageGo to next message
rshelley  is currently offline rshelley Friend
Messages: 59
Registered: April 2010
Member
Sure, I can absolutely provide some code

BundleA - WebShell - Web Bundle (WAR)
MANIFEST.MF
Virgo Screenshot of Bundle: http://screencast.com/t/kfq6r79u0z
Manifest-Version: 1.0
Unversioned-Imports: *
Bundle-ClassPath: .,WEB-INF/classes,WEB-INF/lib
Import-Library: org.springframework.spring;version="[3.0.0.RELEASE,3.0
 .0.RELEASE]"
Web-ContextPath: /webshell
Import-Bundle: com.springsource.javax.ws.rs;version="[1.0.0,1.0.0]",co
 m.springsource.javax.servlet;version="2.5.0",org.eclipse.virgo.web.dm
 ;version="2.1.1.RELEASE"
Bundle-Version: 0.1
Bundle-Activator: com.disney.ace.webshell.internal.WebShellActivator
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.disney.ace.webshell
Import-Package: com.disney.ace.webshell.directory,
 javax.servlet;version="[2.5.0,2.5.0]",j
 avax.servlet.http;version="[2.5.0,2.5.0]",javax.ws.rs,javax.ws.rs.cor
 e,org.apache.log4j,org.osgi.util.tracker,org.osgi.framework
Export-Package: com.disney.ace.webshell.directory


BundleA - WebShell - DiscoveryService Interface (JAR in WAR)
Java Interface
package com.disney.ace.webshell.directory;

public interface IDirectoryService {

	public String getService(String service, String method, String version);
}


BundleB - MockDirectoryService - JAR
MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Vendor: Disney Interactive Media Group
Bundle-SymbolicName: com.disney.ace.webshell.directory.mock
Bundle-Name: Mock Directory Service
Bundle-Version: 0.1.0
Import-Package: 
 org.apache.commons.logging;version="[1.1.1,1.1.1]",
 com.disney.ace.webshell.directory;version="[0.0.0,0.1.0]"
Import-Library: org.springframework.spring;version=
 "[3.0.0.RELEASE,3.0.0.RELEASE]"
Require-Bundle: com.disney.ace.webshell


BundleB - MockDirectoryService - Java
Java Implementation of DirectoryService
package com.disney.ace.webshell.directory.impl;

import com.disney.ace.webshell.directory.IDirectoryService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

@Service
public class MockDirectoryServiceImpl implements IDirectoryService {

	private static Log logger = LogFactory.getLog(MockDirectoryServiceImpl.class);

	public String getService(String service, String method, String version){
		return service + " - " + method + " - " + version;
	}

}


[b]BundleB - MockDirectoryService - Spring/b]
Spring OSGI context
...
	<context:component-scan base-package="com.disney.ace.webshell.directory" />
		
	<!-- Exports the service implementation to other bundles by its service interface -->
	<osgi:service ref="mockDirectoryServiceImpl" interface="com.disney.ace.webshell.directory.IDirectoryService" />
...
	


BundleB - Exception loading bundle in Virgo
region-dm-18                 o.s.osgi.extender.internal.activator.ContextLoaderListener        Application context refresh failed (OsgiBundleXmlApplicationContext(bundle=MockDirectoryService-0.1.0-SNAPSHOT, config=osgibundle:/META-INF/spring/*.xml)) org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean#0': Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Class[]' for property 'interfaces'; nested exception is java.lang.IllegalArgumentException: Cannot find class com.disney.ace.webshell.directory.IDirectoryService

Caused by: java.lang.ClassNotFoundException: com.disney.ace.webshell.directory.IDirectoryService


And for the record, I've tried dropping GreenPages into Virgo and it's always failed loading...

Thanks for your help. I really appreciate it!
Re: OSGI bundle dependencies [message #671454 is a reply to message #671421] Wed, 18 May 2011 00:07 Go to previous message
rshelley  is currently offline rshelley Friend
Messages: 59
Registered: April 2010
Member
I think I may have discovered major parts of the problem.

1) Maven's build process was overwriting my MANIFEST.MF and putting it's own (virtually empty) one in place. I had to futz with the POM to get it to work right. This was confusing because the right manifest was in place in the target/classes/META-INF folder, but was incorrect when checking the JAR itself. Here's my new <build> definition:
	<build>
		<resources>
            <!-- standard Maven folder -->
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                	<include>**/*.xml</include>
                	<include>META-INF/MANIFEST.MF</include>
                </includes>
            </resource>
        </resources>
        
		<plugins>
            <plugin>
                <groupId>com.springsource.bundlor</groupId>
                <artifactId>com.springsource.bundlor.maven</artifactId>
                <version>1.0.0.M2</version>
                <configuration>
                    <outputManifest>${basedir}/src/main/resources/META-INF/MANIFEST.MF</outputManifest>
                    <failOnWarnings>false</failOnWarnings>
                    <removeNullHeaders>true</removeNullHeaders>
                </configuration>
                <executions>
                    <execution>
                        <id>bundle-manifest</id>
                        <phase>package</phase>
                        <goals>
                            <goal>manifest</goal>
                            <goal>transform</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
				</configuration>
			</plugin>
		</plugins>
	</build>


2) It doesn't seem to like unversioned exports. I used the source code from the book you recommended to compare mine and after much back-and-forth, I finally have a manifest that's exporting and importing. I was also using Bundlor's Import-Template and a bunch of optional stuff that I could simplify out just to get things to work. Here's my new simplified manifest:
Manifest-Version: 1.0
Unversioned-Imports: *
Bundle-Classpath: .
Built-By: rshelley
Bundle-Name: client
Bundle-Version: 0.1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.disney.ace.webshell.directory
Import-Package: com.disney.ace.webshell.directory;version="[0.1.0,0.1.
 0]"


At this point, I have another bundle that is successfully importing the interface. That bundle is also registering a service (as per Virgo's bundle info). I have not yet got to the "using of the service" part, but I'm a couple of steps closer.
Previous Topic:Spring transactions with aspectj on Virgo
Next Topic:StackOverflowError during import resolution
Goto Forum:
  


Current Time: Mon Dec 22 18:31:02 GMT 2014

Powered by FUDForum. Page generated in 0.12868 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software