Jump to: navigation, search

OpenDaylight dlux:Add new application

DLUX works as a Karaf based UI platform, where you can create a new Karaf feature of your UI component and install that UI applications in DLUX using blueprint. This page will help you to create and load a new application for DLUX. You don't have to add new module in DLUX repository, your application can reside outside DLUX repository.

You should use angularJS and requireJS to write your application code. Each application consists of two parts, each packaged as maven jar -

1. Application module contains all of the JS, HTML code and it is packaged as a maven jar.

2. Application bundle has a configuration file blueprint.xml, which is read by Karaf container and initiate the deployment of application in DLUX. Application bundle embeds the content of above created Application module jar to make sure browser can access the files. Only Application bundle gets deployed in Karaf.

We separate out Application module and bundle as two different parts of an application in DLUX repository. You can have them together as well, then you don't have to embed content of module inside bundle. You can configure maven in such a manner that one project has content for both of them.

Some basic prior knowledge of Karaf is required to fully understand this document. You can learn about Karaf at http://karaf.apache.org/manual/latest/developers-guide/index.html and You can read about blueprint at http://aries.apache.org/modules/blueprint.html

Create new module

For your application, first step would be to create a new module for your code. We have defined a module structure for existing DLUX applications under modules directory. Follow this wiki to add a new module of your code - * How to add a new js module

Add a new OSGi blueprint bundle

The OSGi Blueprint Container specification allows us to use dependency injection in our OSGi environment. Each DLUX application module registers itself via blueprint configuration. Each application will have its own blueprint.xml to place its configuration.

1. Create a maven project with following structure to place blueprint configuration -

        SampleAppModule
            - src
                - main
                   - resources
                       - OSGI-INF
                           - blueprint
                               - blueprint.xml
            - pom.xml

2. In pom.xml, you have to add a maven plugin to unpack your module code under generated-resources of this project. For reference, I added pom.xml of one of existing DLUX bundle -

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.opendaylight.dlux</groupId>
        <artifactId>bundles</artifactId>
        <version>0.3.0-SNAPSHOT</version>
        <relativePath>../</relativePath>
    </parent>
    <groupId>org.opendaylight.dlux</groupId>
    <artifactId>dlux.topology</artifactId>
    <packaging>bundle</packaging>
    <dependencies>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.osgi.compendium</artifactId>
            <version>${apache.felix.osgi.compendium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.opendaylight.dlux</groupId>
            <artifactId>loader</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.opendaylight.dlux</groupId>
            <artifactId>dlux.topology.resources</artifactId>
            <version>${topology.resources.version}</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>target/generated-resources</directory>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <!--loader Resources-->
                    <execution>
                        <id>unpack-loader-resources</id>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <phase>generate-resources</phase>
                        <configuration>
                            <outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
                            <groupId>org.opendaylight.dlux</groupId>
                            <includeArtifactIds>dlux.topology.resources</includeArtifactIds>
                            <excludes>META-INF\/**</excludes>
                            <excludeTransitive>true</excludeTransitive>
                            <ignorePermissions>false</ignorePermissions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Import-Package>org.osgi.service.http,
                            org.osgi.framework;version="1.0.0",
                            org.opendaylight.dlux.loader,
                            org.slf4j
                        </Import-Package>
                        <Export-Package></Export-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <scm>
        <connection>scm:git:ssh://git.opendaylight.org:29418/dlux.git</connection>
        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/dlux.git</developerConnection>
        <tag>HEAD</tag>
        <url>https://wiki.opendaylight.org/view/OpenDaylight_dlux:Main</url>
    </scm>
</project>

Your bundle will eventually gets deployed in karaf as feature, so your bundle should contain all your module code. If you want to combine module and bundle project, that should not an issue either.

3. Create a blueprint.xml configuration file under src/main/resources/OSGI-INF/blueprint, like described in maven project structure. Below is the content of the blueprint.xml taken from topology bundles's blueprint.xml. any new application should create a blueprint.xml in following format -


<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
	<reference id="httpService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"/>
    <reference id="loader" availability="mandatory" activation="eager" interface="org.opendaylight.dlux.loader.DluxModuleLoader"/>

    <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.opendaylight.dlux.loader.DluxModule">
      <property name="httpService" ref="httpService"/>
      <property name="loader" ref="loader"/>
      <property name="moduleName" value="topology "/>
      <property name="url" value="/src/app/topology"/>
      <property name="directory" value="/topology"/>
      <property name="requireJs" value="app/topology/topology.module"/>
      <property name="angularJs" value="app.topology"/>
       <property name="cssDependencies">
            <list>
                <value>http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css</value>
                 <value>src/app/topology/topology-custom.css</value>
            </list>
        </property>
    </bean>
</blueprint>

In above configuration, there are two references with id httpService and loader. These two beans will already be initialized by dlux-core, so any new application can use them. Without these two bean references, a new application will not be able to register.

Next is the initialization of your application bean, which will be an instance of class org.opendaylight.dlux.loader.DluxModule. There are 5 properties that you should provide in this bean besides the references of httpService and loader. Lets talk about those bean properties in little more detail.

moduleName : Name of your module. This name should be unique in DLUX.

url: This is the url via which requireJS in DLUX will try to load your module js/html files. Also, this is the url that browser will use to load the static HTML, JS or CSS files. requireJS in DLUX has a base path of "src", so all the url should start with /src so requireJS and browser can correctly reach to the file name.

directory: In your bundle's pom.xml, you unpack your module code. This is the directory where your actual static files will resides. Above mentioned url is registered with httpService, so when browser makes a call to that url, it will be redirected to the directory mentioned here. So, in above example, all the topology files are present under /topology directory and browser/requireJS can access those files with uri /src/app/topology.

requireJS: This is the path to your requireJS module. If you notice closely, you will see the initial path of requireJS app/topology in above example matches with the last part of url. this path will be be used by requireJS. As mentioned above, we have kept "src" as base path in requireJS, that is the exact reason url start with /src.

angularJS:name of your angularJS module.

cssDependencies: If the application has any external/internal css dependency, then those can be added here. If you create your own css files, just point to those css files here. Use the url path that you mentioned above, so browser can find your css file.

OSGi understands blueprint.xml, once you will deploy your bundle in Karaf (you can create a new feature for your application also), Karaf will read your blueprint.xml and it will try to register your application with dlux. Once successful, if you refresh your DLUX UI, you will see your application in left hand navigation bar of DLUX.

Add a new Karaf Feature for your application

At this point, you have written your JS code, created a bundle which Karaf can understand. Next step is deploy and test your bundle.

There are couple of ways to test your bundle. Prerequisite is DLUX core feature is already enabled in Karaf.

1. Easiest way to test your newly created bundle is to copy your bundle jar and place it under deploy directory of your Karaf based controller.

2. Install your bundle from Karaf Console.

root@karaf> bundle:install -s <<path url like mvn:org.opendaylight.dlux/dlux.topology/0.3.0>>

In production environment, you may want to create own Karaf feature, which may deploy one or more bundles. All the Karaf based features in DLUX are defined in file features.xml present under features/src/main/resources/. A usual feature definition can have dependency on other feature and one or more bundles such as


<feature name="odl-dlux-node" version='${project.version}' description="Enable nodes in Opendaylight dlux">
        <feature>odl-dlux-core</feature>
        <bundle>mvn:org.opendaylight.dlux/dlux.node/${project.version}</bundle>
 </feature>

If you are updating code in DLUX repository, you can update existing features.xml. If your project is outside, you can create a new feature there that includes your application bundle there and have dependency on odl-dlux-core

Redeploy application bundle

You might want to redeploy your application for new version or just to test your JS/ CSS changes, while development. Easiest way to do so would be to build your module and bundle and then redeploy your bundle in running Karaf distribution.

1. Go to the Karaf console and find your bundle ID. You can find your bundle id via running command -

  bundle:list 

2. Uninstall Your existing bundle via running command-

  bundle:uninstall  <<ID>>

For more details on bundle uninstall, take a look at http://karaf.apache.org/manual/latest/commands/bundle-uninstall.html

3. Reinstall via running command like -

  bundle:install -s <<url like mvn:org.opendaylight.dlux/dlux.topology/0.3.0>>