I want to deploy all the configuration files of the bundles deployed in karaf be placed in the karaf etc
folder. I want that when the bundles conf files are change are notice by the karaf.
I have a distribution which consist of several features an example of a feature of the XML.I already tried several things eg I add the conf file into the feature as below, but this dose not work.
<feature name="gc-backbone-mqtt" version="${linksmart.gc.version}">
<feature version="${linksmart.gc.version}">gc-backbone-router</feature>
<bundle>mvn:org.eclipse.paho/org.eclipse.paho.client.mqttv3/1.0.0</bundle>
<feature version="${linksmart.gc.version}">gc-type-tunnelled</feature>
<configfile finalname="/etc/mqttBackboneProtocol.cfg">mvn:eu.linksmart.gc/backbone.mqtt.impl/${linksmart.gc.version}/mqttprotocol.properties</configfile>
<bundle>mvn:eu.linksmart.gc/backbone.mqtt.impl/${linksmart.gc.version}</bundle>
</feature>
Some of the things I have tried:
http://karaf.922171.n3.nabble.com/OSGi-bundle-configuration-file-td4025438.html
I don't want to copy the file with a specific path as is shown here:
have anyone an idea how to do this?
UPDATE
To achieve that the configuration file get deployed in the etc
folder so the bundle can be reconfigured externally, I have done it in 3 steps:
Building the configuration file: ( Works )
To make the config file addressable by Maven I added the following part in the bundle pom. In this way the config file is deploy on the repository:
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>src/main/resources/mqttprotocol.properties</file>
<type>cfg</type>
<classifier>configuration</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Deploy the file in the karaf etc
( Works )
To deploy the config file in the karaf etc
folder I added the <configfile>
in the feature file as following:
features.xml
<feature name="gc-backbone-mqtt" version="${linksmart.gc.version}">
<feature version="${linksmart.gc.version}">gc-backbone-router</feature>
<bundle>mvn:org.eclipse.paho/org.eclipse.paho.client.mqttv3/1.0.0</bundle>
<bundle>mvn:org.apache.felix/org.apache.felix.fileinstall/3.2.8</bundle>
<configfile finalname="/etc/MQTTBackboneProtocol.cfg">mvn:eu.linksmart.gc/network.backbone.protocol.mqtt.impl/${linksmart.gc.version}/cfg/configuration</configfile>
<feature version="${linksmart.gc.version}">gc-type-tunnelled</feature> <bundle>mvn:eu.linksmart.gc/network.backbone.protocol.mqtt.impl/${linksmart.gc.version}</bundle>
</feature>
Capture configuration change: ( not working )
To capture the change of a config file I add the code you suggested (@Donald_W). The problem is that I get just notifications of files are on the folder deploy
but not in etc
. I debug this code and I find out that for the files in etc
are called specifically the "listeners" of those files. I don't know then how I can become a listener of a file deployed in the etc
You can use the Felix File Installer which is built into Karaf, which will give you callbacks when files change under etc
.
Once you publish a service which implements ArtifactInstaller
into the OSGi service registry it will be detected by the FileInstaller
- ie the Whiteboard pattern .
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.fileinstall</artifactId>
<version>3.4.2</version>
<scope>provided</scope>
</dependency>
Sample code (using iPojo but Blueprint / DS would work just as well) would be:
package com.example.deployer.internal;
import org.apache.felix.fileinstall.ArtifactInstaller;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Provides;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Instantiate()
@Component(name = "propsDeployer")
@Provides(specifications = ArtifactInstaller.class)
public class PropsDeployer implements ArtifactInstaller {
Logger logger = LoggerFactory.getLogger(JsonDeployer.class);
@Override
public void install(File artifact) throws Exception {
logOutput("Installing",artifact);
}
@Override
public void update(File artifact) throws Exception {
logOutput("Updating",artifact);
}
@Override
public void uninstall(File artifact) throws Exception {
logger.info("Uninstalling artifact: {}", artifact.getName());
}
@Override
public boolean canHandle(File artifact) {
return artifact.getName().endsWith(".props");
}
private void logOutput(String action, File artifact) throws IOException {
logger.info(action + " artifact: {}", artifact.getName());
Properties props = new Properties();
FileReader in = null;
try {
in = new FileReader(artifact.getCanonicalFile());
props.load(in);
} finally {
if (in != null) {
in.close();
}
}
// Do whatever you want here:
for(Object key: props.keySet()) {
logger.info(action + " Property received: {} {}",key,props.get(key));
}
}
}
Should give you output like this:
2015-04-27 20:16:53,726 | INFO | ime/karaf/deploy | PropsDeployer | 101 - com.example.scratch.deployer - 1.0.0.SNAPSHOT | Updating artifact: my.json
2015-04-27 20:16:53,728 | INFO | ime/karaf/deploy | PropsDeployer | 101 - com.example.scratch.deployer - 1.0.0.SNAPSHOT | Updating Property received: myprop myval
2015-04-27 20:16:53,728 | INFO | ime/karaf/deploy | PropsDeployer | 101 - com.example.scratch.deployer - 1.0.0.SNAPSHOT | Updating Property received: hello world
You'll need a unique file extension. .cfg will be captured by the ConfigurationAdmin service which you say you don't want to use.
Something like .props
(as above) would do the trick.
As an aside, you really should look at using ConfigurationAdmin
. It's incredibly powerful. There are commands built into karaf for managing the configuration, and any changes you make will persist back to the .cfg
files.
Eureka!
As I mentioned in the UPDATE the step 1 (build configuration file with maven) and 2 (deploy the conf file etc
) was working but the bundle and the configuration file were not connected. Apparently the reason was that the configuration file was install with another PID as the service which was registering to it. To solve this I registered the ManageService
to the PID of the configurated file deployed. In my case looks as following:
Hashtable <String, Object> properties = new Hashtable<String, Object>();
properties.put(Constants.SERVICE_PID, "MQTTBackboneProtocol");
context.registerService (ManagedService.class.getName(),this , properties);
Where this
is the class which implements the ManageService
and the PID must be the same as is deployed configuration in the etc
, in this case "MQTTBackboneProtocol"
due to the feature definition indicate the configuration file as:
<configfile finalname="/etc/MQTTBackboneProtocol.cfg">mvn:eu.linksmart.gc/network.backbone.protocol.mqtt.impl/${linksmart.gc.version}/cfg/configuration</configfile>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.