I Followed this tutorial for my Restlet server in the Google App Engine: http://wiki.restlet.org/docs_2.0/13-restlet/21-restlet/318-restlet/303-restlet.html It works fine with the GWT client.
Now i'm trying to build a jse2 desktop client with OSGi and Restlet.
The code for the Restlet client in the OSGi bundle stay's the same as the tutorail provided.
When i start the OSGi Felix framework i also start the org.restlet.jar bundle who's exporting the restlet framework packages and i start a bundle with this code given in the toturail:
ClientResource cr = new ClientResource("localhost:8888/contacts/123");
// Get the Contact object
ContactResource resource = cr.wrap(ContactResource.class);
Contact contact = resource.retrieve();
The ContactResoure interface is in the same package as the bundle activator but i still get this strange message: java.lang.IllegalArgumentException: interface nl.nhl.minor.crm.desktop.restlet.ContactResource is not visible from class loader
Is this problem related to OSGi or to Restlet? And how can I solve this problem?
The manifest files for the OSGi bundles are created by the maven bundle plugin.
The correct way of loading a class is easy:
ClientResource cr = new ClientResource("http://127.0.0.1:8888/contacts/123");
Class<ContactResource> clazs = (Class<ContactResource>) cr.getClass().getClassLoader().loadClass("your.package.name.ClassName");
cr.wrap(clazs);
This solution give you a other problem, the class isn't imported by the org.restlet bundle.
See import package without edit the manifest file in org.restlet for my question about that problem.
Related
I'm exploring how OSGI is implemented for the last couple of weeks. I know that each bundle uses its own class loader to load its classes. As part of my investigation, I understood that parent of every bundle's class loader is null i.e boot class loader.
System.out.println("ClassInBundle class is loaded by "+ClassInBundle.class.getClassLoader());
System.out.println("ClassInBundle parent class is "+ClassInBundle.class.getClassLoader().getParent());
Output for above code which is in bundle samplebundle is
ClassInBundle class is loaded by com.sample.bundle.samplebundle [34]
ClassInBundle parent class is null
and for imports in a bundle, it maintains a map of packagename=>classloader so that it can delegate requests to the correct class loader
Bundle SB = felix.getBundleContext().getBundle(0);
List<BundleWire> sbwires=SB.adapt(BundleWiring.class).getRequiredWires(null);
List<BundleWire> li=bundle.adapt(BundleWiring.class).getRequiredWires(null);
for(BundleWire i : li){
System.out.println(i);
}
The output for the above code is
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (osgi.wiring.package=com.test.packag) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework)(version>=1.8.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework.wiring)(version>=1.2.0)(!(version>=2.0.0))) -> [org.apache.felix.framework [0](R 0)]
[com.sample.bundle.samplebundle [34](R 34.0)] osgi.ee; (&(osgi.ee=JavaSE)(version=1.6)) -> [org.apache.felix.framework [0](R 0)]
As you can see in the first line of above output, the package com.test.packag is added as FelixConstants.FRAMEWORK_SYSTEMPACKAGES and the bundle samplebundle is wired to system bundle[0] for com.test.packag.
So, I wanted to understand how system bundle[0] can access system packages which are loaded by different class loader(App class loader). Not only that all the core classes of OSGI like Bundle, BundleActivator, Felix are also loaded by App class loader. So, I tried debugging the Felix code to understand whether the system bundle is delegating the loadClass() requests to App class loader. Unfortunately, while debugging I observed m_wiring variable of BundleWiringImpl class, I noticed that classloader of system bundle is null(which is not possible because boot class loader only loads java.* packages).
please correct my understanding if I'm wrong.
My questions here are
what is the class loader of system_bundle[0] and what is its parent class loader?
if the parent of the system_bundle class loader is not App class loader, is system bundle also maintaining the map of package=>classloader to load classes which are loaded by app class loader?
what exactly is the hierarchy of class loaders(bundle class loaders, system class loader, boot class loader, and app class loader)?
Thank you.
Normally the OSGi Framework (aka the System Bundle) is loaded by the application loader and therefore has visibility of everything else on the application loader, and its parents i.e. the extension loader and the boot loader.
It actually depends on how you write your launcher. You can embed OSGi into any standard Java application simply by instantiating a FrameworkFactory and using it to launch a Framework. When you do this, the OSGi framework is just another library on the classpath and it has visibility of the same set of classes as your own code.
You can make things as simple or as fancy as you like. For example you could embed an OSGi Framework into a Servlet deployed in a J2EE application server... in that case the system bundle will have visibility to all the types available in the Web Application, as controlled by the contents of WEB-INF. You could even embed an OSGi Framework into a bundle deployed to another OSGi Framework... OSGi inception!
In all these cases, the Framework can choose what set of packages to export. These packages become available to be imported by bundles inside that Framework. By default the packages exported are the standard set of JavaSE packages for the relevant JavaSE version, but you can augment with additional application-level packages.
We use WebSphere 8.5 (NON-Liberty Profile… just straight-up WAS) and we have a Spring 3.2 web app that is accessing an OSGI service which is using the blueprint component model via an SCA service bridge. We did this this way because to our understanding, this was the only way to be able to access the OSGI services layer from within our current architecture. If anyone might know of another/better way, I'm also all-ears on this as well.
From within this blueprint managed service, we'd like to have a reference to another service. This other service(and any service references within it) we'd like to have managed by the declarative services component model.
My question is… is this possible? Does anyone know if this mixing of these two component models from within WAS 8.5 is do-able in any way, shape, or form??
And if it is possible, might anyone be able to point me in the right direction on how to approach this?
Edit - Dec 5th
So the approach I decided to take was to first, build a small proof-of-concept application that uses three different OSGI bundles all using blueprint. Then once I have this working, take one of the blueprint managed services, and attempt to convert it to a ds managed service.
Here's what I've got so far:
I have ran through and created the tutorial located here. I currently have the CounterApp OSGI bundle Application containing the following bundles as application content:
CounterServiceBundle
CounterWebBundle
CounterWorldBundle
As is stated in the tutorial, all of the above are tied together using the blueprint component model via the blueprint.xml files.
So it all breaks down as follows:
From within the doGet method of the CounterWebBundle's CounterServlet I have a Greet service being used in the following manner:
Greet greet;
try {
InitialContext ic = new InitialContext();
greet = (Greet) ic.lookup("osgi:service/"+Greet.class.getName());
String greetText = greet.getText();
String output = "greet.getText()="+greetText;
response.getOutputStream().println(output);
} catch (NamingException e) {
e.printStackTrace(System.out);
}
This "greet" service is defined in the blueprint xml as "GreetBeanService". Now, within its implementation class it has references to two other services, "CounterBean" and "WorldRef".
Here is the blueprint.xml file to clarify:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="CounterBean" class="com.ibm.ws.eba.counter.CounterImpl"
init-method="init"></bean>
<service id="CounterBeanService" ref="CounterBean"
interface="com.ibm.ws.eba.counter.Counter" />
<bean id="GreetBean" class="com.ibm.ws.eba.counter.GreetImpl"
init-method="init">
<property name="counter" ref="CounterBean"/>
<property name="worldBean" ref="WorldRef"/>
</bean>
<service id="GreetBeanService" ref="GreetBean"
interface="com.ibm.ws.eba.counter.Greet" />
<reference id="WorldRef" interface="com.ibm.ws.eba.world.World" />
</blueprint>
So the thing is this:
I'm aiming to convert the "WorldRef" service to a DS managed service with a component.xml file and the following added to the MANIFEST.MF header Service-Component: OSGi-INF/component.xml of the implementation Class, not the API Class if I'm understanding correctly.
Would this be all I would need to do for the conversion? Or do I also need to add an Activator for the Class? Also, would I need to add 'activate' and 'deactivate' methods in the API implementation Class?
Also I'm of the understanding that I have to somehow include the service component runtime, as a separate bundle and include it in the "CounterApp" application, how exactly would I do this? Do I have to create a separate bundle project consisting of the following bundle/jars
org.eclipse.equinox.util
org.eclipse.equinox.ds
org.eclipse.osgi.services
where I would then re-export all of the exported interfaces from all of these jars?
Or do I have to define some sort of service to export that exposes the SCR?
Edit - Dec 6th
I went ahead and created a new DS OSGI bundle/jar containing all of the above mentioned jar files required to provide the equinox DS implementation, then just passed on the exports of each jar in this new bundle. I then added this DS bundle to my CounterApp application and imported each of these DS bundle exports into the bundle containing the WorldRef service.
This is where I appear to be getting hung up:
The OSGI framework is loading the bundle containing the WorldRef service but the service is not being added to the registry, which suggests that the component.xml file defining the service isn't being read, which, intern suggests that the SCR is not running because it is what reads that file to my understanding.
So still stuck on the ability to get the SCR running. I am under a very tight deadline (I know… who isn't, right?
I am trying to extend ProfileImages servlet from /libs/foundation/src/impl/src/main/java/com/day/cq/wcm/foundation/pro file/impl/ProfileImages.java
and bundling as an OSGI service.
I have the following annotations
#Component(immediate=true)
#SlingServlet(
resourceTypes = {"nt:file"},
methods = {"GET"},
selectors = {"adjust","adjust.small"},
extensions = {"res", "jpg", "png", "gif"}
)
I see my service in bundles and Services in OSGI console. However it is not doing as ProfileImages servlet used to do
ProfileImages create the thumbnail if we invoke the following URL
http://mydomain.com:4502/content/dam/geometrixx/portraits/scott_reynolds.jpg.prof.thumbnail.100.100.jpg
If my servlet is invoke, I should get the same response
http://mydomain.com:4502/content/dam/geometrixx/portraits/scott_reynolds.jpg.adjust.small.100.100.jpg
However I am getting is 404 which is from the DefaultGetServlet
It seems that Sling servet is not able to resolve my servlet
One thing I need to know is how to get my service updated in
Apache Sling Servlet Resolverorg.apache.sling.servlets.resolver
My servlet is doing the same thing as the following service in sling servlet resolver
Service ID 843 Types:
org.apache.sling.api.resource.ResourceProvider
Description: ServletResourceProvider for Servlets at
[/libs/foundation/components/primary/nt/file/prof/thumbnail.gif.servl
et, /libs/foundation/components/primary/nt/file/prof.gif.servlet,
/libs/foundation/components/primary/nt/file/prof/thumbnail.res.servle
t, /libs/foundation/components/primary/nt/file/prof.jpg.servlet,
/libs/foundation/components/primary/nt/file/prof.png.servlet,
/libs/foundation/components/primary/nt/file/prof/thumbnail.png.servle
t,
/libs/foundation/components/primary/nt/file/prof/thumbnail.jpg.servle
t, /libs/foundation/components/primary/nt/file/prof.res.servlet]
My service should be listed in sling resolver with id and something like
...../adjust.small.jpg.servlet, ..../adjust.res.servlet
I am using CRXDE web version for development
Is there any configurations I have to do to get my service in over resource resolver?
Your servlet can not be resolved because it is not registered with the Declarative Services Runtime.
The #Component and #SlingServlet annotations are not evaluated at runtime, they are part of the Apache Felix SCR Plugin Project which provides a maven plugin and ant task to create "OSGi Declarative Services" descriptors.
http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin.html
For registering your Servlet as an OSGi Service an OSGI-INF/serviceComponents.xml file is required.
So I'm afraid you won't get around using a build lifecycle tool to build your OSGi bundle before uploading to CQ5, if you are planning to use the scr annotations.
Else you have to create your service component file manually.
I have a modular application which uses OSGi framework. Here I'm using org.eclipse.equinox.common_3.4.0 OSGi container. So now the application is already running with all the osgi bundles installed and active and I am displaying all the active OSGi bundles on the UI, by looping though a hash map, based on some action.
Now the requirement is, while the application is already running, I want to instal a new OSGi bundle, from a file system, by giving this new bundle to the application's OSGi container so that it will start this bundle.
How do I achieve this ?
I have tried reading the OSGi bundle as a JarInputstream and read the bundle activator fully qualified class path and tried to instantiate this using Class.forName("") and type casted to BundleActivator interface. But while starting it, it is taking bundle context as a argument to start method.
Is there way where I can just give the OSGi bundle to the container pragmatically so that it will take care of installing and starting the bundle and then my UI will automatically picks up this new bundle name in the display.
Assuming you have the file to load, you can install the bundle like:
void install( BundleContext context, File file) throws Exception {
Bundle b = context.installBundle( file.toURI().toString() );
b.start();
}
And you can uninstall it (if the file is gone):
void uninstall( BundleContext context, File file) throws Exception {
Bundle b = context.getBundle( file.toURI().toString() );
b.uninstall();
}
You get the BundleContext from your activate or Declarative services component's activate method. These are the recommended methods but in dire cases you can also use:
BundleContext context = FrameworkUtil.getBundle( this.getClass() ).getBundleContext();
Though handy it bypasses some mechanism that you might want to use in the future so getting the context in the recommended way is much better
I'm in the process of upgrading my application the latest release of Eclipse Equinox 3.7 and associated libraries. I'm excited to have the generic support in OSGi 4.3 and digging the new Bundle.adapt() concepts. I've run into one stumbling block.
Previously, I've used PackageAdmin.getBundle(Class) to find out which bundle loaded which classes. I have to do this due to some RMI object serialization usage.
QUESTION: Is there an way to accomplish the same result, mapping Class to Bundle, using the new BundleWiring API?
I realize that PackageAdmin is probably not going away anytime soon, but I hate deprecation warnings.
Kinda embarrassed that I didn't find this the first time I looked through the document. Answering my own question for completeness.
From the core specification PDF ...
Section 3.9.9 - Finding an Object’s Bundle
There are scenarios where a bundle is required in code that has no access to a Bundle Context. For this
reason, the framework provides the following methods:
Framework Util – Through the FrameworkUtil class with the getBundle(Class) method. The
framework provides this method to allow code to find the bundle of an object without having the
permission to get the class loader. The method returns null when the class does not originate from
a bundle.
Class Loader – An OSGi framework must ensure that the class loader of a class that comes from a
bundle implements the BundleReference interface. This allows legacy code to find an object’s
bundle by getting its class loader and casting it to a BundleReference object, which provides
access to the Bundle. However, this requires the code to have the permission to access the class
loader. The following code fragment shows how to obtain a Bundle object from any object.
ClassLoader cl = target.getClassLoader();
if ( cl instanceof BundleReference ) {
BundleReference ref = (BundleReference) cl;
Bundle b = ref.getBundle();
...
}
In an OSGi system, not all objects belong to the framework. It is therefore possible to get hold of a
class loader that does not implement the BundleReference interface, for example the boot class path
loader.