I have a sling Servlet (and various other components) running inside an OSGi bundle inside AEM / Apache Felix.
eg:
#SlingServlet(
label = "XXXX - SSO Post Servlet",
metatype = true,
methods = {"POST"},
name = "XXXX.core.components.SlingPostServlet",
paths = {"/services/SSOPost"}
)
public class SlingPostServlet extends SlingAllMethodsServlet {
//etc
My components work as expected, maven is able to build, bundle and deploy the entire project fine.
My issue is that updates to my components are not activated until I restart the entire AEM instance. I have tried refreshing OSGi packages, restarting the bundle, and as many likely UI actions to achieve this effect as I can think of, but no luck.
Any ideas? I'm hoping its a simple config issue/ button I am not aware of.
Thanks.
The bundle is started but the event might not be active. It should get activated when the service is actually used. We can use the #Component(immediate=true) annotation to activate the component when the bundle gets started
Try deleting the old jar first, and then deploy the new jar. This works for me most of the times, but not always.
Related
I want to use Sling scheduler as a bundle in my Eclipse Equinox Environment and now trying to just run the examples, both whiteboard or via API without success. After lots of debugging I have now been able to make it work but I had to make a change in the scheduler bundle in QuartzScheduler and change the reference to MetricRegistry to add optional cardinality:
#Reference(cardinality=ReferenceCardinality.OPTIONAL)
MetricRegistry metricsRegistry;
which otherwise makes the service fail to start on Equinox.
Running tests in the bundle it seems that this is also never resolved even with Felix, but in that case the service still starts. I should also note that MetricRegistry doesn't appear to be a service and I can't understand why it would be instantiated via #Reference. Actually changing the line to:
MetricRegistry metricsRegistry = new MetricRegistry();
will correctly retrieve the metricsRegistry in all cases, Felix or Equinox.
Have I uncovered a bug or there is something I don't understand?
In Apache Sling a MetricRegistry instance is registered from the org.apache.sling.commons.metrics bundle, see MetricsServiceImpl#activate. You should deploy this bundle in your OSGi container.
Is there any approach via we can maintain and control OSGi bundles' state manually via code?
I have a requirement where in I need to download, copy and install/activate/deactivate/delete OSGi bundles in run time environment.
Any help/references will be appreciated.
Thanks!
You install a bundle with BundleContext.install by supplying a URL or an InputStream. As result you get a Bundle. In Bundle you can then call start(), stop() and uninstall(). You get the BundleContext inside the Activator of any already existing bundle.
http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/BundleContext.html
I'm having a problem I simply can't get my head around.
I'm creating a jsf application where I (as administrator) can upload a jar file, and that way around update the application.
Through this tutorial: http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html I have managed to classload the jar file. The first issue is that I can only class load as "Object" and not cast to an other class type. I get a ClassCastException.
JarClassLoader jcl=new JarClassLoader(url);
Class cl= jcl.retreiveClass(jcl.getMainClassName());
Object ob=cl.newInstance(); //I would like to make this a RouteBuilder object instead of Object
Concretely I'm using Apache Camel, where I can add routes to an existing "core" (CamelContext). What's happening is that I have the core of apache camel running in my web app, and I can then add routes runtime. It's a route I want to package as a jar and load into the app runtime (I want to develop and test the route in my local environment, and then afterwords upload it to the production application). A concrete route is just a simple java class that extends RouteBuilder. I want to upload the jar, classLoad (URLClassLoader) the main class (maybe the whole jar? - does that make sense?), and convert it to a RouteBuilder. This seems to be impossible. I have chosen to upload the jar file to a folder outside my war, so that the routes do not get erased when I restart the webapp (is this smart or should this be done in an other way?). Is that a problem regarding name spaces? Furthermore, I haven't been able to find out whether I need to traverse my entire jar file and classload ever single class inside. Any comments on that?
To me it seems like I have some fundamental misconceptions on how extending / updating a java application is done. I simply can't find any good examples/explanations on how to solve my problem and therefore I conclude that I don't get this on a conceptual level.
Could someone elaborate on how to extend a running jsf application (I guess the same issues are relevant in native java apps), explain how to upload and class load a jar at runtime, and how to cast loaded classes to other class types than Object?
Thanks
Lasse
If you are interested in loading Routes without stopping your application you could consider using an OSGi container like Karaf. Karaf provides support for Apache Camel routes out-of-the-box: http://camel.apache.org/karaf.html
All class loading is managed by the OSGi container and you just need to run some commands to update things. I am not sure if this could work with your JSF application but it worths to take a look.
Here's the scenario:
I have a bundle 'BundleA' installed and started in an OSGi container. A new version of BundleA is available. BundleA is provisioned using Felix Bundle Repository. The new version of BundleA declares a new package level requirement on a package from 'BundleB'.
Before I update BundleA (using OBR's deploy()) I stop BundleA because I want all threads to stop running and the deactivator provides this ability.
When I perform a deploy() on BundleA, BundleB is also installed, as expected.
I then programmatically start() BundleA again, and BundleA starts. But BundleB is 'resolved', not 'active'. I can manually start BundleB and it works as expected.
Is this expected, related to a way I am programmatically calling OSGi API, or did something go wrong?
That's the expected default behavior.
You can enable automatic activation of bundles as soon as any class from them is loaded. In order to do so, you need to set the Bundle-ActivationPolicy: lazy header.
In Eclipse that's the checkbox "Activate this plug-in when one of its classes is loaded" in the Manifest editor on the Overview page.
The OSGi framework does not automatically start bundles. (It will restart previously started bundles on framework launch however.) The framework does not know anything about start dependencies between bundles and bundles should not require a certain start order. As Gunnar mentioned, you can use activation policy to trigger lazy activation but that will not do anything if you have not called start on the bundle with the lazy activation policy.
I have a server side application and want to embed an osgi framework into for dynamic bundle loading.
Suppose I want to expose a QuoteImpl implementing IQuote(instantiated as part of the server container bootstrap/Spring) to be used by different Bundles.
Q1. Is there a clean way of exposing server-application instances to Bundles ? (btw because of legacy it is not possible to make server code into bundle :) and donot want to make entire application osgi'ed.
Tried exposing via a service and bundle to cast into an IQuote. Not sure I am doing it well but fails with unresolved compilation problems as IQuote resides in the core app projects as opposed to the bundle project. any ideas?
Yes the way to do this is with a service. The "host" application would publish the service and the bundles inside OSGi would consume the service in the normal way.
The key to get this working is that the service API (i.e. the package containing IQuote) must be exported by the host application through the system bundle exports. You can control this by setting the org.osgi.framework.system.packages.extra property when you create the embedded OSGi framework. I wrote a blog post on this subject that should help you get started (look for the heading "Exposing Application Packages").
You state that you have compilation problems. To fix those it's necessary to know how you have structured your projects and build system.
This is how I embedded Equinox OSGi runtime in my Java class. I suppose you could do the same. https://github.com/sarxos/equinox-launcher/blob/master/src/main/java/com/github/sarxos/equinox/Launcher.java