blob: 32ee40ced7487bd09ffa431664b05cf5b152e997 [file] [log] [blame] [view]
---
title: Apache Celix Framework
---
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
# Apache Celix Framework
The Apache Celix framework is the core of Apache Celix applications and provides supports for deployments of
dynamic, extensible modules known as bundles.
An instance of an Apache Celix framework can be created with the celix framework factory or by configuring
[Apache Celix containers](containers.md) using the `add_celix_container` Apache Celix CMake command.
## Framework factory
A new instance of an Apache Celix framework can be created using the C/C++ function/method:
- `celix_frameworkFactory_createFramework`
- `celix::createFramework`
When an Apache Celix framework is destroyed it will automatically stop and uninstall all running bundles.
For C, an Apache Celix framework needs to be destroyed with the call `celix_frameworkFactory_destroyFramework` and
for C++ this happens when the framework goes out of scope.
### Example: Creating an Apache Celix Framework in C
```C
//src/main.c
#include <celix_bundle_activator.h>
int main() {
//create framework properties
celix_properties_t* properties = properties_create();
properties_set(properties, "CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "debug");
//create framework
celix_framework_t* fw = celix_frameworkFactory_createFramework(properties);
//get framework bundle context and log hello
celix_bundle_context_t* fwContext = celix_framework_getFrameworkContext(fw);
celix_bundleContext_log(fwContext, CELIX_LOG_LEVEL_INFO, "Hello from framework bundle context");
//destroy framework
celix_frameworkFactory_destroyFramework(fw);
}
```
```cmake
#CMakeLists.txt
find_package(Celix REQUIRED)
add_executable(create_framework_in_c src/main.c)
target_link_libraries(create_framework_in_c PRIVATE Celix::framework)
```
### Example: Creating an Apache Celix Framework in C++
```C++
//src/main.cc
#include <celix/FrameworkFactory.h>
int main() {
//create framework properties
celix::Properties properties{};
properties.set("CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "debug");
//create framework
std::shared_ptr<celix::Framework> fw = celix::createFramework(properties);
//get framework bundle context and log hello
std::shared_ptr<celix::BundleContext> ctx = fw->getFrameworkBundleContext();
ctx->logInfo("Hello from framework bundle context");
}
```
```cmake
#CMakeLists.txt
find_package(Celix REQUIRED)
add_executable(create_framework_in_cxx src/main.cc)
target_link_libraries(create_framework_in_cxx PRIVATE Celix::framework)
```
## Apache Celix launcher
If the Apache Celix framework is the main application, the Apache Celix launcher can be used to create the framework
and wait for a framework shutdown.
The Apache Celix launcher also does some additional work:
- Handles command arguments (mainly to print to embedded and runtime framework properties).
- Tries to read a "config.properties" file from the current workdir and combines this with the optional provided
embedded properties to the Apache Celix Launcher.
- Configures a framework shutdown for the `SIGINT` and `SIGTERM` signal.
- Configures an "ignore" signal handler for the `SIGUSR1` and `SIGUSR2` signal.
- Calls the `curl_global_init` to initialize potential use of curl. Note that the `curl_global_init` is not thread safe
or protected by something like pthread_once.
- Destroys the Apache Celix Framework after shutdown.
### Example: Creating an Apache Celix Framework with the Apache Celix Launcher
```C
//src/launcher.c
#include <celix_bundle_activator.h>
int main(int argc, char** argv) {
return celix_launcher_launchAndWait(argc, argv, NULL);
}
```
```cmake
#CMakeLists.txt
find_package(Celix REQUIRED)
add_executable(create_framework_with_celix_launcher src/launcher.c)
target_link_libraries(create_framework_with_celix_launcher PRIVATE Celix::framework)
```
## Installing and starting bundles in an Apache Celix framework
Bundles can be installed and started using the Apache Celix framework bundle context or - when using the Apache Celix
launcher - with a "config.properties" file.
Bundles are installed using a path to a zip file. If the path is a relative path, the framework will search for the
bundle in the directories configured in the framework property `CELIX_BUNDLES_PATH`.
The default value of `CELIX_BUNDLES_PATH` is "bundles".
Another option is to use framework properties to configure which bundles to install and start.
This can be done by using the CELIX_AUTO_START_0 till CELIX_AUTO_START_6 framework properties.
(note that bundles configured in CELIX_AUTO_START_0 are installed and started first).
For a more complete overview of possible framework properties see `celix_constants.h`
If the Apache Celix launcher is used, the framework properties can be provided with a "config.properties"
file using the Java Properties File Format.
Framework properties to install and start bundles:
- CELIX_AUTO_START_0
- CELIX_AUTO_START_1
- CELIX_AUTO_START_2
- CELIX_AUTO_START_3
- CELIX_AUTO_START_4
- CELIX_AUTO_START_5
- CELIX_AUTO_START_6
### Example: Installing and starting bundles in C
```C
//src/main.c
#include <celix_bundle_activator.h>
int main() {
//create framework properties
celix_properties_t* properties = properties_create();
properties_set(properties, "CELIX_BUNDLES_PATH", "bundles;/opt/alternative/bundles");
//create framework
celix_framework_t* fw = celix_frameworkFactory_createFramework(NULL);
//get framework bundle context and install a bundle
celix_bundle_context_t* fwContext = celix_framework_getFrameworkContext(fw);
celix_bundleContext_installBundle(fwContext, "FooBundle.zip", true);
//destroy framework
celix_frameworkFactory_destroyFramework(fw);
}
```
### Example: Installing and starting bundles in C++
```C++
//src/main.cc
#include <celix/FrameworkFactory.h>
int main() {
//create framework properties
celix::Properties properties{};
properties.set("CELIX_BUNDLES_PATH", "bundles;/opt/alternative/bundles");
//create framework
std::shared_ptr<celix::Framework> fw = celix::createFramework(properties);
//get framework bundle context and install a bundle
std::shared_ptr<celix::BundleContext> ctx = fw->getFrameworkBundleContext();
ctx->installBundle("FooBundle.zip");
}
```
### Example: Installing and starting bundles using the Apache Celix Launcher
```C
//src/launcher.c
#include <celix_bundle_activator.h>
int main(int argc, char** argv) {
return celix_launcher_launch(argc, argv, NULL);
}
```
```cmake
#CMakeLists.txt
find_package(Celix REQUIRED)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/config.properties CONTENT "
CELIX_BUNDLES_PATH=bundles;/opt/alternative/bundles
CELIX_AUTO_START_3=FooBundle.zip
")
add_executable(create_framework_with_celix_launcher src/launcher.c)
target_link_libraries(create_framework_with_celix_launcher PRIVATE Celix::framework)
```
## Framework `celix_condition` Services
In a dynamic framework such as Apache Celix, it can sometimes be challenging to ascertain when the framework or
certain parts of a dynamic service-based application are ready for use. To address this issue, Apache Celix provides
services known as `celix_condition` services.
A `celix_condition` service is a registered marker interface with a "condition.id" service property.
The service's availability signifies that the condition identified by the "condition.id" has been met.
The `celix_condition` service is an adaptation of the
[OSGi 8 Condition Service Specification](https://docs.osgi.org/specification/osgi.core/8.0.0/service.condition.html).
The Apache Celix framework will provide the following `celix_condition` services for the respective states:
- Celix condition "true", which is always available.
- Celix condition "framework.ready". This service will be registered when the framework has successfully and fully
started, which includes installing and starting all configured bundles and services, and ensuring the event queue is
empty after all configured bundles have been started. Note that the "framework.ready" condition is not part of the
OSGi condition specification.
- Celix condition "framework.error". This service will be registered when the framework has not started successfully.
This can occur if any of the configured bundles fail to start or install. Note that the "framework.error" condition
is not part of the OSGi condition specification.
Contrary to the OSGi specification, the Apache Celix framework does not provide a public API for adding or removing
framework listeners. Instead, framework condition services can be used. This has the advantage of ensuring no
framework state changes can be missed, because the state indicating condition services will be available
until the framework is stopped.
## Framework bundle cache
The Apache Celix framework uses a bundle cache directory to store the installed bundles, their state and for a
persistent bundle storage. The bundle cache directory is created in the directory configured in the framework
property `CELIX_FRAMEWORK_CACHE_DIR` (default is ".cache"). A bundle cache consists of a bundle state property file,
a resource bundle cache and a persistent storage bundle cache.
The resource bundle cache is used to store and access the bundle resources (e.g. the content of the bundle zip file)
and should be treated as read-only. The resource bundle cache can be accessed using `celix_bundle_getEntry`
or `celix::Bundle::getEntry`.
The persistent storage bundle cache can be used to store persistent data for a bundle and can be treated as
read-write. The persistent storage bundle cache can be accessed using `celix_bundle_getDataFile` or
`celix::Bundle::getDataFile`.
If a framework is started with only a `Celix::shell` and `Celix::shell_tui bundle`, the following directory structure
is created:
```bash
% find .cache
.cache/
.cache/bundle1
.cache/bundle1/bundle_state.properties
.cache/bundle1/storage
.cache/bundle1/version1.0
.cache/bundle1/version1.0/libshelld.so.2
.cache/bundle1/version1.0/libshell.so.2
.cache/bundle1/version1.0/META-INF
.cache/bundle1/version1.0/META-INF/MANIFEST.MF
.cache/bundle2
.cache/bundle2/bundle_state.properties
.cache/bundle2/storage
.cache/bundle2/version1.0
.cache/bundle2/version1.0/libshell_tuid.so.1
.cache/bundle2/version1.0/META-INF
.cache/bundle2/version1.0/META-INF/MANIFEST.MF
```
The entry `.cache/bundle1/version1.0` is the resource bundle cache and the entry `.cache/bundle1/storage` is the
persistent storage bundle cache for the `Celix::shell` bundle.
## Framework configuration options
The Apache Celix framework can be configured using framework properties.
The framework properties can be provided in the following ways:
- Using the Apache Celix launcher with a "config.properties" file.
- Creating a framework using the framework factory and providing a celix_properties_t*.
- Setting environment variables with the prefix "CELIX_".
Note that the config properties and environment variables are only read once when the framework is created.
So changing the environment variables after the framework is created will not have any effect.
The following framework properties are supported:
| Framework Property | Default Value | Description |
|--------------------------------------------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CELIX_FRAMEWORK_CACHE_DIR | ".cache" | The directory where the Apache Celix framework will store its data. |
| CELIX_FRAMEWORK_CACHE_USE_TMP_DIR | "false" | If true, the Apache Celix framework will use the system temp directory for the cache directory. |
| CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE | "false" | If true, the Apache Celix framework will clean the cache directory on create. |
| CELIX_FRAMEWORK_FRAMEWORK_UUID | "" | The UUID of the Apache Celix framework. If not set, a random UUID will be generated. |
| CELIX_BUNDLES_PATH | "bundles" | The directories where the Apache Celix framework will search for bundles. Multiple directories can be provided separated by a colon. |
| CELIX_LOAD_BUNDLES_WITH_NODELETE | "false" | If true, the Apache Celix framework will load bundle libraries with the RTLD_NODELETE flags. Note for cmake build type Debug, the default is "true", otherwise the default is "false" |
| CELIX_FRAMEWORK_STATIC_EVENT_QUEUE_SIZE | "100" | The size of the static event queue. If more than 100 events in the queue are needed, dynamic memory allocation will be used. |
| CELIX_FRAMEWORK_AUTO_START_0 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_FRAMEWORK_AUTO_START_1 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_FRAMEWORK_AUTO_START_2 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_FRAMEWORK_AUTO_START_3 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_FRAMEWORK_AUTO_START_4 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_FRAMEWORK_AUTO_START_5 | "" | The bundles to install and start after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_AUTO_INSTALL | "" | The bundles to install after the framework is started. Multiple bundles can be provided separated by a space. |
| CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL | "info" | The default active log level for created log services. Possible values are "trace", "debug", "info", "warning", "error" and "fatal". |
| CELIX_ALLOWED_PROCESSING_TIME_FOR_SCHEDULED_EVENT_IN_SECONDS | "2" | The allowed processing time for scheduled events in seconds, if processing takes longer a warning message will be logged. |
| CELIX_ALLOWED_PROCESSING_TIME_FOR_GENERIC_EVENT_IN_SECONDS | "5" | The allowed processing time for generic events in seconds, if processing takes longer a warning message will be logged. |