Accessing osgi bundle classess from servlet - java

I have two projects.
An osgi bundle (eclipse plugin project).
A simple web application (deployable in tomcat).
I have started the felix container from tomcat with no problem by following the link below
http://felix.apache.org/documentation/subprojects/apache-felix-http-service.html#using-the-servlet-bridge
Now I am stuck how to call the classes of the bundle (already installed in the felix container) from a servlet. It is throwing class not found error as the bundle project is not in the classpath but in the following location
/WEB-IN/bundles.(I have to use this location for the bundles). So how it could be achieved?

The BundleContext of the framework bundle is put into the servlet context in ProvisionActivator:
servletContext.setAttribute(BundleContext.class.getName(), context);
This means that you can access the BundleContext via the servletContext (that is available in all of your ordinary servlets) like this:
BundleContext context = servletContext.getAttribute(BundleContext.class.getName());
You can access the classes inside the embedded OSGi container by:
Asking for the bundle that contains the class via the bundleContext
Getting the class with the bundle.loadClass("myClass") method. You will be able to use that class only if you cast to the interface available from the ordinary WAR or with reflection
This is the way to do it, however you should not use this method :). Design your solution in the way that in your bundles you register OSGi services that implement interface(s) coming from the WAR classpath. After that you should use the bundleContext object to retrieve the OSGi service objects.
Other good solution is if you implement the logic you need within bundles instead of classes coming from the WAR.

Related

RESTful service in Karaf without blueprint xml

I am new to Karaf, hence was looking for resources to create a project for RESTful web services using felix annotations and without the use of BundleActivator class(i mean by an actual class that needs to be written by me, but its ok if some compiler or maven plugin does the same for me) and blueprint xml file. So far I got success in the first part(BundleActivator part) which now after compilation auto creates my MANIFEST.MF with import and export statements, creates the relevant XML file for each component class, and packages it into a a nice jar bundle which works very well when I deploy it on Karaf container. But what is not working is the RESTful services. The bundle is deployed correctly, but the REST urls are not exposed and hence I am unable to access them.
Please help me in getting this done. I don't want to write an XML file which needs to be modified everytime there is an addition or deletion of a rest service.
Thanks
If you want to completely avoid blueprint then you should use cxf-dosgi. You simply annotate your rest service using jaxrs and publish it as an OSGi service with some special properties.
See the cxf-dosgi rest sample.
The example uses the standard DS annotation and the maven bundle plugin to create the DS component xml on the fly.
If you prefer to have blueprint at runtime then you can use the blueprint-maven-plugin. See this example.
I figured out a way to do so without using the CXF feature. That is, create a component class and in activate method get the object of ConfigurationAdmin and put the required context path against the jersy server process(using jersey publisher jar). Using this mehtod, I was able to deploy any rest/serlvet in Karaf without using blueprint.xml file. I hope this helps.

PAX-CDI: how to get reference to BeanManager in bundle without using CDI

There is a bundle A and threre is a class MyClass in bundle A. And we suppose that pax-cdi+weld is on.
Can can I get reference to BeanManager of the bundle A inside MyClass without using #Inject and other CDI annotations? Via osgi service? Or how?
You can look up the CdiContainer OSGi service and invoke getBeanManager().
With recent versions of Pax CDI CDI.current().getBeanManager() should work as well.
Having said that, the whole idea of Pax CDI is to make CDI work in OSGi just like in Java EE. Accessing the BeanManager is a bit of a design smell, unless you are developing a CDI extension.

exception while trying to deploy liferay portlet with spring

I'm trying to create a portlet with liferay 6.2 and using spring. If I create a bean without using constructor-arg or factory-method then everything works fine. But if I use either of these then I get exceptions when the portlet is deployed.
an example:
the exception I'm getting is:
01:28:21,884 ERROR [ContextLoader:323] Context initialization failed
java.lang.IncompatibleClassChangeError: class org.springframework.core.LocalVariableTableParameterNameDiscoverer$ParameterNameDiscoveringVisitor has interface org.springframework.asm.ClassVisitor as super class
I realize that this can be caused by having 2 versions of ams, but im using the spring jars that come with liferay.
You give an option yourself - duplicate classes. But without knowing how you build and what you're doing, there's hardly anything to do apart from asking you to make extra extra extra sure that you don't have duplicate resources on the classpath:
Check your deployed web application (once it's deployed to your application server) and its WEB-INF/lib folder for such duplicates. They might come in only during the buildprocess, e.g. they might not be in your IDE's workspace. Or Liferay might inject them (due to declared dependencies) during deployment.
You'll have to figure out how (and in which phase) those resources get there, then eliminate that option (e.g. through proper maven scope, e.g. "provided")

Passing arguments between parent application and OSGi Framework

I have to pass parameters between parent application and embeded OSGi. I use equinox and run OSGi by FrameworkFactory in my Launcher class, then I install and start bundles. It is possible to pass object reference or even some primitive type to bundle or service?
After launching the framework, you can get the system bundle context and access and call services registered by bundles in the framework. Care must be taken about the service types since the are likely loaded from bundles and thus the types are not directly visible to your launching code. But you can use reflection. Or you can put those types in the framework classloader and export them from the system bundle via org.osgi.framework.system.packages.extra framework property your launcher sets.

How do I use a Spring bean inside an OSGi bundle?

I have an application where I have to use Spring to load a bean based on some business conditions inside an OSGi bundle. This bean is not meant for export and is used for calculation inisde my bundle. Basically I have an actual service component, which is exported, and it has to use this Spring bean internally. But...
When I use Spring DM the extender loads the application context in a seperate thread. How to access the context file inside my bundle?
How to make sure extender thread finshes loading application context so that i can use it in my bundle?
I don't want to export the application context as services as Spring DM does, as it's only used inside my bundle for internal purposes.
Is there any way to do this?
You don't need Spring DM for what you are trying to accomplish.
It sounds like what you want to do is actually provide access to your context inside of your bundle and have some class do lookups via ctx.getBean(). If this is the case, just create the context in your bundle manually like you would if you were not in OSGi and make the calls. No Spring DM involved at all.
The one issue here is that you have to extend ClassPathXmlApplicationContext to provide the bundles classloader, as it will use the thread context classloader otherwise.
ApplicationContext ctx = new ClassPathXmlApplicationContext(myCtxPath)
{
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)
{
super.initBeanDefinitionReader(reader);
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
reader.setBeanClassLoader(getClassLoader());
}
}

Categories