I have a C++ program that loads a JVM and launches an OSGi framework. The OSGi framework is Equinox, more precisely org.eclipse.osgi_3.8.1.v20120830-144521.jar.
The Launcher
The OSGi launcher is called from C++ using JNI and it goes like this (details left out for brevity):
// Create OSGi framework.
final ServiceLoader<FrameworkFactory> frameworkFactoryLoader =
ServiceLoader.load(FrameworkFactory.class);
final FrameworkFactory frameworkFactory =
getFrameworkFactory(frameworkFactoryLoader);
final Map<String, String> osgiConfig = ...
final Framework osgiFramework = frameworkFactory.newFramework(osgiConfig);
// Start the framework.
osgiFramework.start();
// Install some bundles.
final BundleContext frameworkBundleContext = osgiFramework.getBundleContext();
final Bundle bundle1 =
installBundle(frameworkBundleContext, "reference:" + bundle1URI, null);
installBundle(frameworkBundleContext, "reference:" + bundle2URI, 5);
installBundle(frameworkBundleContext, "reference:" + bundle3URI, 10);
...
// Explicitly starting a particular bundle.
bundle1.start();
...
// Raise the framework start level so bundles are started
// at the desired start levels.
final FrameworkStartLevel frameworkStartLevelObject =
bundleAdapt(systemBundle, FrameworkStartLevel.class);
frameworkStartLevelObject.setStartLevel(10, ...left-out...);
The helper function for installing a bundle goes like this:
private Bundle installBundle(final BundleContext frameworkBundleContext,
final String bundleURI,
final Integer desiredStartLevel) {
final Bundle bundle = frameworkBundleContext.installBundle(bundleURI);
if (desiredStartLevel != null) {
// Set the level at which the bundle should start.
// (Otherwise, it will start at the default level.)
final BundleStartLevel bundleStartLevel =
bundleAdapt(bundle, BundleStartLevel.class);
bundleStartLevel.setStartLevel(desiredStartLevel);
}
}
Now, all bundles are resolved and are either in the RESOLVED, ACTIVE or STARTED state.
Starting with osgi.clean=true
If I start the OSGi framework with option osgi.clean=true in the osgiConfig map and change the bundles installed from run to run that is nicely reflected in the framework.
If I e.g. start the framework with bundleX and bundleY and call
frameworkBundleContext.getBundles();
then I see exactly
The system bundle (ACTIVE)
bundleX (RESOLVED)
bundleY (RESOLVED)
If I shut down the program and retry this time with bundleX and bundleZ then I see (no surprise)
The system bundle (ACTIVE)
bundleX (RESOLVED)
bundleZ (RESOLVED)
Starting without osgi.clean
If I start the OSGi framework without setting osgi.clean in the osgiConfig map then installed bundles stick around from run to run and new bundles are not resolved.
So assume that I run one time with osgi.clean=true loading bundleX and bundleY and then shut down the program.
Now, when I and restart without osgi.clean and install only bundleZ, then I see:
The system bundle (ACTIVE)
bundleX (RESOLVED)
bundleY (RESOLVED)
bundleZ (INSTALLED) (i.e. not resolved yet)
So bundleX and bundleY survived from one run to another without having to be installed the 2nd time.
On the other hand, bundleZ does not resolve automatically. To get it to the RESOLVED state I need to do this:
final FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
frameworkWiring.resolveBundles(null);
Question: Should I use osgi.clean or not?
It seems that using osgi.clean=true gives me a fresh start every time, whereas not using it means that bundle state survives from run to run. I guess the caching makes OSGi start faster but it does not seem to be a big deal for me (as I install the bundles using the "reference:" prefix which means the jars are not copied to the cache, only a reference to the original file location is kept).
However, my application is a multi process application running against the same OSGi configuration area. Is it a problem running with osgi.clean=true all the time in this situation?
Also, if somebody could point me to a good explanation of exactly what osgi.clean means and how caching in OSGi (Equinox) works I would appreciate it.
Ignore osgi.clean. Also please ignore start levels. The step you're missing is actually starting your bundles!
Each call to installBundle gives you a Bundle object. After installing all the bundles, you should then call start() on each of the returned bundle objects.
Any other way that you have been using to start bundles has been down to pure luck, i.e. because those bundles might once have been started and cached in that state. The same state would probably not be repeatable if you installed the application on another machine. So actually take control of your bundles and start them yourself.
You usually don't need to worry about the difference between INSTALLED and RESOLVED. Installed can simply mean "not resolved yet", e.g. because the bundle's exports weren't needed. If there are any resolving problems such as missing dependencies, then you will find out about them as BundleException when calling the start method.
Related
I'm on Talend ESB Runtime.
I encountered problems while starting ./trun. Nothing on the screen appeared after start. The process is launched but I can't get anything else...
Anyway I tryed to deployed a job, and there is something weird in the log about org.osgi.framework.bundleException in tesb.log.
And Karaf.log is OK
Here tesb.log :
tesb.log
karaf.log :
karaf.log
log in repository data :
timestamplog
I don't know how to investigate, because logs are poor and JVM is equal between Talend ESB and the runtime...
Can you help me please?
You only showed a small snippet of the log. From this I can already see that at least one bundle can not be resolved. This means that this bundle can not be used. In the snippet the bundle seems to be a user bundle but I am pretty sure you have other such log messages that show that one of the main bundles of karaf can not be loaded.
If you want to check for the cause of the problem look into these messages and search for non optional package that are not resolved. Usually this leads to a missing bundle.
If you simply want to get your system running again you can simply reset karaf by using
./trun clean
Remember though that you then have to reinstall all features again.
I'm trying to figure out what the org.osgi.framework.storage.clean=onFirstInit really means in the context of the Felix framework.
According to the OSGi specification:
org.osgi.framework.storage: A valid file path in the file system to a
directory... The framework is free to use this directory as it sees
fit, for example, completely erase all files and directories in it...
org.osgi.framework.storage.clean: Specifies if and when the storage
area for the framework should be cleaned. If no value is specified,
the framework storage area will not be cleaned.
Since according to the specification the framework is free to use this directory as it sees fit, it is unclear what is meant when the OSGi specification states that the storage area should be cleaned. Cleaning could mean something different for each OSGi implementation.
The Apache Felix documentation states:
onFirstInit flushes the bundle cache when the framework instance is
first initialized.
Specific to the Felix documentation:
What does it mean to "flush the bundle cache"? Is flushing the same as deleting the storage directory and then rebuilding it from scratch? So it would be the same as rm -rf felix-cache while the Felix container is shut down so that when it starts up it rebuilds the cache as if this was the first time the container was started?
What does it mean when it says "when the framework instance is first initialized"? Does this mean the first time the framework is initialized only on the first time the container is started? Or does it mean the first time the framework is initialized every time the container is restarted?
What does it mean to "flush the bundle cache"?
It means deleting the directory specified by org.osgi.framework.storage
Is flushing the same as deleting the storage directory and then rebuilding it from scratch?
Yes
So it would be the same as rm -rf felix-cache while the Felix container is shut down so that when it starts up it rebuilds the cache as if this was the first time the container was started?
Yes
What does it mean when it says "when the framework instance is first initialized"?
Bundles can be initialized multiple times. This statement indicates that the directory should only be deleted the first time after the JVM starts not subsequent times the system bundle is initialized.
Does this mean the first time the framework is initialized only on the first time the container is started? Or does it mean the first time the framework is initialized every time the container is restarted?
It means the first time the framework is initialized every time the container is restarted
I am using Karaf 3.0.1 and have two fragment bundles A and B that attach to a host bundle C. I am able to install A, then B, then C, and start C and everything works fine.
When I stop and start Karaf though, the host usually has a failure and does not start successfully. Both fragments are listed as "Resolved" and show as being attached to the host and the host shows it is attached to the fragments, but the host has a state of "Failure". The exception in the log file is:
20140507 07:35:39.011 [ERROR] FelixStartLevel | 19:org.apache.aries.blueprint.core |
org.apache.aries.blueprint.container.BlueprintContainerImpl | Unable to start
blueprint container for bundle <host bundle name>
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to load
class <class from 2nd fragment> from recipe BeanRecipe[name='<bean ID from second
fragment blueprint XML>']
If I deploy only a single fragment, then I'm able to restart Karaf and the host starts fine. But with two fragments, Karaf will restart ok perhaps once or twice, but then fails and never successfully starts again. I played with start levels and having the host have a higher/later start level doesn't help at all.
I read When is an OSGi fragment attached to host? that seems to make it clear that start-levels don't affect resolution order and saw the suggestion to use Provide/Require-Capability headers. I tried that and see the same behavior, although again with a single fragment it works fine.
What else might I do to get this to work? Might there be a bug in Karaf/Felix regarding multiple fragments for the same host on restart?
Yes, I'd rather not use fragments but am porting a fairly complex Java EE app to OSGi and this is the approach that works given the code-base I have, but if I can't depend on things starting correctly when Karaf starts, this won't be workable.
Thanks,
Kevin
I'm trying to implement scheduler to my application. I use spring and quartz support.
I have test my component and run perfectly.
My Main method is:
public class Main {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("application-context.xml");
}
}
I use wrapper-windows-x86-32-3.5.7, I configure the wrapper.conf, and run from console using DemoApp.bat wrapper.
It works.
But When I want to install the service, I got error message Startup failed: Timed out waiting for a signal from the JVM.
After 5 times repetition, I got error message
JVM did not exit on request, terminated
There were 5 failed launches in a row, each lasting less than 300 seconds. Giving up.
Thanks for help.
Because it is working fine for you running in a console, but not as a service. This is most likely a problem with the environment of the SYSTEM user. The most common cause is not being able to locate the java binary. The cause should be fairly obvious if you look in the wrapper.log file.
The default location of the java binary is:
wrapper.java.command=java
This will cause it to be found on the PATH. To use a JAVA_HOME location, try the following:
wrapper.java.command=%JAVA_HOME%/bin/java
Then make sure you have declared the JAVA_HOME variable as a SYSTEM WIDE variable, not jsut for your current user account.
Cheers,
Leif
We are using Karaf-4 as OSGI container. We have several bundles associated with a feature. When any bundle fails in a feature, we want to identify programmatically. We tried BundleTracker and BundleListener, but we are not getting notification when a bundle fails after waiting in "GracePeriod" state.
We are able to view the status of failure bundle using "list" command in karaf console. We want to achieve this programmatically through notification rather than we execute "list" command in the karaf console.
You can use the BundleService as an OSGi service. The method getInfo gives you among other the BundleState. For failed bundles you can then call getDiag to get the detailed status.
Actually this is what the diag command does internally.