My OSGi bundle is giving me strange behaviour. Some times it gets Active in first go and some time I need to restart Karaf again and again to see whether my bundle is active or not. Even I cann't see any exception. And all other bundles are active. Can anyone suggest me what can be the cause. I checked its headers they are just ok, we are importing all the packages and exporting none. As is the case for my bundle. Even I hit start command many times. But it is not getting Active state.
Installation order of your bundles might not be aligned to their dependency orders. Try creating your own feature.xml file, where you can set the installation order of your bundles during startup. You can find more detail at https://karaf.apache.org/manual/latest/provisioning
And do not forget to add the features you have created to $KARAF_ROOT/etc/org.apache.karaf.features file in order to make your features installed automatically during startup.
Related
I lost the original build file, but it is still there working nicely in the container. I would like to avoid rebuilding, as some edge conditions might come to play. I would expect it is possible to back up the working binary, so I could deploy new version and safely rollback if unfortunate. However, I can't find the folder where these are stored, or any commands that would magically extract the bundle.
There is a folder $FUSE_HOME/data/repository with a maven-like structure, and it seems to contain most of the installed bundles, but apparently not all, specifically not the version I am after.
Under the 'data/cache' directory you will see the bundles and the bundle numbers. Do a 'osgi:list' on the karaf shell and find the number of your bundle. Underneath the bundle+number directory you will find the deployed bundle creatively named 'bundle.jar'.
The spring boot edit starters context menu for downloading content to pom.xml automatically is not visible in my eclipse, although Spring Tool Suite is properly installed. Also. the Boot Dashboard for Development Tools will not show up.
Error: java.io.IOException: Unable to resolve plugin
"org.springframework.ide.eclipse.boot.dash".
What could this be, how do I solve this?
This is usually a hard-to-debug issue and probably caused by some incompatibilities among installed plugins. You can try to start up Eclipse/STS with the -clean option, this causes the runtime to re-evaluate bundle resolution (among other things), and in some rare cases that helps. But it doesn't help if there is a real underlying incompatibility. And that is hard to identify from the outside, we would need a lot more details to debug this.
I would recommend to download a ready-to-use STS distribution and go from there. It contains a full Eclipse JEE package plus the Spring IDE plugins pre-installed. I know that starting from a fresh install might cause additional work if you need additional third-party plugins being installed again, but it would at least give you a good starting point. And if the problem arises again after installing certain plugins, we would at least have a potentially reproducible path towards the issue that we could use to track down the issue on our end.
You may follow these steps -
Right click "pom.xml"
Select "Spring" item
Click "Add Starters"
For your reference,
I've developed a project that has a bundle whose only purpose is to write a file to a certain location on all of the containers running it.
This file will change often, but does not really constitute an increase in version number. I also don't want to have 100 versions of this bundle in my repository. So I have left it as a snapshot. This question would also apply if I was doing active development on a project for fuse fabric.
Once built, I deploy the bundle to my fabric's maven proxy with:
mvn deploy:deploy-file -Dfile=target/file-1.0-SNAPSHOT.jar -DartifactId=file -DgroupId=com.some.id -Dversion=1.0.0 -Dtype=bundle -Durl=http:// username:password#hostname:port/maven/upload
I can then add my bundle to a profile with:
mvn:com.some.id/file/1.0.0
This works the first time.
Then I make a change to the file, rebuild the bundle, and deploy with exactly the same command. I remove the bundle from the profile and add it back in. The maven proxy on the fabric server has the new bundle in it if I check $FUSE_HOME/data/maven/proxy/com/some/id/file/1.0.0/
But on all of the containers running the profile on a separate server, the bundle is not updated. I assume because the version has not changed. However, fabric should be smart enough to tell the difference, as the md5 should be different.
For now I can change the version number and my problem is solved, or clear the maven proxy by hand. But in production I will not be able to clear the proxy on every server, nor can I expect someone to come up with a unique version for the bundle every time they make a small change to this file (which should happen often).
I have already tried adding updatePolicy=always to the fabric maven configuration, but I believe that only affects repositories that it is pulling from, not the proxy.
Any advice on the best way to solve this problem is welcome.
If you are using containers, your old artefacts must be cached in
$FUSE_HOME/instances/CONTAINER_NAME/data/maven/agent/
Delete the old artefacts from here and stop/start your container.
I am working on a custom feature and did install it the Identity Server. After some fixes I wanted to re-install the feature, so what I did was 1) uninstall the feature, 2) restart server (graceful) 3) install the feature. The repository points to my local p2-repos which is generated in the build of maven.
The Identity Server does NOT accept the new feature. It is NOT showing any error in the console, neither in the web-admin. But when I test the feature I can see in the console and my debug outputs that the install-manager did not renew the jars.
My workaround now is to delete the whole server and do the install-process each time I want to try my code.
Can anyone confirm this bug?
If your feature is correctly installed, you can see your new jars in /repository/components/plugins directory. If not, Please copy all OSGI (jar files) in your feature in to /repository/components/dropins directory and restart the server. Also. you can use OSGI console to check whether bundles are properly activated.
Just start server with --DosgiConsole option. then you would promote a OSGI console. you can check whether new bundles are active or not.
When a bundle is updated (say to fix a bug), what happens to other bundles that are currently using the one being updated?
Say that there are two bundles service and dao. Say that classes in service bundle are using classes in dao bundle when I issue command to update dao layer. Will the class in service layer using dao code get an exception?
Thanks for your response.
I meant to say updated with the same version.
until a bundle refresh occurs which includes the dependent bundle.
Bundle refresh operation is invoked by the user updating the bundle, right? Say that when user invokes refresh to update dao bundle, a class in bundle service invoked a method on a class in dao layer... what happens in this scenario?
I found this blog post helpful:
http://solutionsfit.com/blog/2008/08/27/osgi-what-modularity-can-do-for-you-part-1/
From the post:
If we simply replace the bundle with a bundle that includes the fix, the container will unregister the old bundle and register the new bundle. The proxy can then handle the reference shuffling and resume the service invocation. This interaction will be almost instantaneous. Your customers will be completely oblivious to what has happened and you just saved your company a substantial amount of money (do I hear bonus?).
In this blog post, the call to authorizePayment() was put on hold until the updated bundle is available. What happens if the control is within the authorizePayment() method when bundle refresh happens?
Bundles have 2 kind of dependencies:
Services, and
Connections between
class loaders, keyed by the package
names. Those connections are called
wires.
Services are easy to withdraw because that is intrinsic to their design. Wires are harder because they are intricately woven in your objects and those objects are not aware of the dynamics. So when you install a new bundle, the old bundles stay as they are, your objects are not updated and the updated bundle still provides its wires as a zombie.
When you call refreshPackages the framework looks at those dependencies and finds the bundles that refer to those zombies. Every zombie is then stopped. The contract for a bundle is that it should cleanup. We help the bundle by doing a lot of cleanup for you, but some things are very bad, e.g. storing references in statics of other bundles or forgetting to stop threads that were started. Other bundles that depend in other ways on those bundles get notified of the bundle stopping so they can also clean up any references. After the bundles are stopped, the bundles are unresolved and then resolved again against the new bundles.
For real OSGi bundles the cleaning up is natural and not really visible in your code (as it should be). It is well supported by the tools like Declarative services, iPOJO, dependency manager, Spring, Blueprint, etc. The magic is focus on the µservices model and not dong class loading hacks.
Why are we not refreshing automatically? Well, we once did but refreshing is disruptive. In many cases you need to update multiple bundles. Having this disruption after each update would be unnecessary painful. That is, after an install or update you should ALWAYS do a refresh but you can bracket a number of installs/updates.
When you update a bundle, using the OSGi 'update' command, it is most likely to have other dependent bundles that are relying on it and already capturing a set of loaded classes from the old version of this bundle. A situation that typically conforms to the problem you described in your question.
In order to avoid possible inconsistency between the different versions of the classes enfolded by this bundle, the OSGi container decides to temporarily hide the new version of the updated bundle's classes from the outside world. You can think of it as kind of keeping the updated classes in isolation from the other bundles -momentarily-.
The point here is that the OSGi container can’t just start loading classes from the new version of the target bundle, because the dependent bundles would end up seeing old versions of the classes they already loaded, mixed with new versions of the same classes that were loaded after the update, which would incorporate an inconsistency that would result in an uncontrollable mess. The same goes for the bundle Uninstall, the bundle is removed from the installed list of bundles, but it is not removed from memory. It shall be kept around so that dependent bundles can continue to load classes from it.
So you can think of the 'update' command, as introducing a new version of the same bundle, to be only supplied to dependent bundles that are yet to come, -which are not yet there at the time of the update-. While the old version -that existed before the update-, remains in memory in order to assure backward compatibility and avoid any possible disruption to existing bundles that have already started to depend on the updated bundle.
Note, that the old versions are only kept in memory, which means that a restart to the server will result in eradicating all these old versions and bring the latest version to the table. This makes perfect sense, because there will be no need for backward compatibility, simply because all bundles are now starting at the same time..
What happens next, is that you have to explicitly invoke the 'refresh' command on specific bundles, -those which are depending on the updated bundle-, or instead you can choose to run the 'refresh' command without specifying a specific bundle, meaning that all bundles will be blindly refreshed. The 'refresh' command forces the rebuilding of the dependency tree of the target bundles, and coerce their class loaders to start loading their required classes from scratch.
Only then dependent bundles will start to see the changes you have made to the code of the classes living in the bundle that has been updated.
The rule is that
Existing resolved bundles already importing an older version of a class won’t be automatically rewired to the new bundle unless they’re refreshed.
When a bundle is updated, a new revision (the bits of the bundle) is installed. If another bundle is wired to the prior revision of the updated bundle, that is, another bundle imported some package exported by the prior revision or another bundle required the bundle at the prior revision, then the OSGi framework will retain the prior revision of the updated bundle to service future class load requests from the dependent bundle until a bundle refresh occurs which includes the dependent bundle.
The purpose of this is to minimize or delay perturbing dependent bundles when a dependency is updated. A management agent may want to update several bundles and, at the end, do a bundle refresh to "modernize" the dependencies. Once the bundle refresh is done, there are no wires to the prior revision of the updated bundle and the OSGi framework is now free to discard the prior revision.
So in your example, generally no exception will result. But of course it depends upon what the code in question is actually doing and how their bundle manifests are written.