Creating and installing a custom WSO2 Carbon feature - II

This is the second article I am going to write about creating and installing WSO2 Carbon features to an existing WSO2 product. Most of the content here is based on the excellent tutorial written by Amal Gunatilake on the same topic. You can find it here. You can read the first part of this article here

In this article let’s take a look at how to generate a feature from the carbon component we built earlier and add it to a repository. The composite feature is built by combining the features generated for server component and the UI component. We can use carbon-p2-plugin provided by WSO2 for generating features from components. Then we need to create a repository containing this composite feature so that it can be easily installed into a carbon based product.

Create the composite feature

Let’s create three sub projects inside our feature project (order-processor-features) for generating the features (org.wso2.carbon.orderprocessor.server.feature, org.wso2.carbon.orderprocessor.ui.feature and org.wso2.carbon.orderprocessor.feature). Also, we’ll add a properties file (feature.properties) with the copyright information that will prompt the user during the installation. You can download it from here.

Two of the sub projects will generate features from existing components (org.wso2.carbon.orderprocessor.server.feature and org.wso2.carbon.orderprocessor.ui.feature) and the other project (org.wso2.carbon.orderprocessor.ui.feature) will combine the above generated features. All of the sub projects above will only contain a single pom file. This file will run the carbon-p2-plugin to make a feature out of the components. Feature combining sub project will additionally run the maven-antrun-plugin to avoid copying source directories into the generated feature. Below are the three pom files used in the sub projects. Comments provide additional clarifications.

    <?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">
             
        <parent>
            <groupId>org.wso2.carbon</groupId>
            <artifactId>order-processor-features</artifactId>
            <version>1.0.0</version>
        </parent>
        
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>org.wso2.carbon.orderprocessor.server.feature</artifactId>
        
        <packaging>pom</packaging>
        
        <!-- This project is dependent on the server component --> 
        <dependencies>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.orderprocessor.server</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>

        <!-- Repository to download the carbon-p2-plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>wso2-nexus</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
                <releases>
                    <enabled>true</enabled>
                    <updatePolicy>daily</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </pluginRepository>
        </pluginRepositories>
        
        <build>
            <plugins>
                <plugin>
                    <!-- carbon-p2-plugin detials -->
                    <groupId>org.wso2.maven</groupId>
                    <artifactId>carbon-p2-plugin</artifactId>
                    <version>1.5.3</version>
                    <executions>
                        <execution>
                            <id>p2-feature-generation</id>
                            <phase>package</phase>
                            <goals>
                                <goal>p2-feature-gen</goal>
                            </goals>
                            <configuration>
                                <id>org.wso2.carbon.orderprocessor.server</id>
                                <!-- location of the properties file -->
                                <propertiesFile>../feature.properties</propertiesFile>
                                <adviceFile>
                                    <properties>
                                        <!-- This property is used to define whether the feature is a back-end (server),
                                        UI (console) or a common feature. This property is read by the feature manager.
                                        We are using server here as this is a server feature-->
                                        <propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
                                        <!-- This property defines whether the feature is a composite feature or not.
                                        Composite type features are shown in the feature manager UI. For the server feature
                                        and UI featrue we set this as false since they are not composite features -->
                                        <propertyDef>org.eclipse.equinox.p2.type.group:false</propertyDef>
                                    </properties>
                                </adviceFile>
                                <bundles>
                                    <!-- Server OSGI bundle -->
                                    <bundleDef>org.wso2.carbon:org.wso2.carbon.orderprocessor.server</bundleDef>
                                </bundles>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
file: ./order-processor-features/org.wso2.carbon.orderprocessor.server.feature/pom.xml
    <?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">
        
        <parent>
            <groupId>org.wso2.carbon</groupId>
            <artifactId>order-processor-features</artifactId>
            <version>1.0.0</version>
        </parent>
        
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>org.wso2.carbon.orderprocessor.ui.feature</artifactId>
     
        <!-- UI feature is dependent on ui component and ui component is dependent
        on stub. So we need to add both the projects as dependencies -->
        <dependencies>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.orderprocessor.stub</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.orderprocessor.ui</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>

        <!-- Repository to download the carbon-p2-plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>wso2-nexus</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
                <releases>
                    <enabled>true</enabled>
                    <updatePolicy>daily</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </pluginRepository>
        </pluginRepositories>
        
        <build>
            <plugins>
                <plugin>
                    <groupId>org.wso2.maven</groupId>
                    <artifactId>carbon-p2-plugin</artifactId>
                    <version>1.5.3</version>
                    <executions>
                        <execution>
                            <id>p2-feature-generation</id>
                            <phase>package</phase>
                            <goals>
                                <goal>p2-feature-gen</goal>
                            </goals>
                            <configuration>
                                <id>org.wso2.carbon.orderprocessor.ui</id>
                                <propertiesFile>../feature.properties</propertiesFile>
                                <adviceFile>
                                    <properties>
                                        <!-- We are using console here as this is an UI feature -->
                                        <propertyDef>org.wso2.carbon.p2.category.type:console</propertyDef>
                                        <propertyDef>org.eclipse.equinox.p2.type.group:false</propertyDef>
                                    </properties>
                                </adviceFile>
                                <bundles>
                                    <!-- We have to include both ui and stub OSGI bundles as the UI bundle
                                    depends on the stub -->
                                    <bundleDef>org.wso2.carbon:org.wso2.carbon.orderprocessor.stub</bundleDef>
                                    <bundleDef>org.wso2.carbon:org.wso2.carbon.orderprocessor.ui</bundleDef>
                                </bundles>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
file: ./order-processor-features/org.wso2.carbon.orderprocessor.ui.feature/pom.xml
    <?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">
        
        <parent>
            <groupId>org.wso2.carbon</groupId>
            <artifactId>order-processor-features</artifactId>
            <version>1.0.0</version>
        </parent>
        
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>org.wso2.carbon.orderprocessor.feature</artifactId>
        
        <packaging>pom</packaging>

        <!-- Composite feature is dependent on ui feature and server feature.
        So we need to add both the projects as dependencies -->
        <dependencies>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.orderprocessor.ui.feature</artifactId>
                <version>1.0.0</version>
                <type>zip</type>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.orderprocessor.server.feature</artifactId>
                <version>1.0.0</version>
                <type>zip</type>
            </dependency>
        </dependencies>

        <!-- Repository to download the carbon-p2-plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>wso2-nexus</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
                <releases>
                    <enabled>true</enabled>
                    <updatePolicy>daily</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </pluginRepository>
        </pluginRepositories>
         
        <build>
            <plugins>
                <plugin>
                    <groupId>org.wso2.maven</groupId>
                    <artifactId>carbon-p2-plugin</artifactId>
                    <version>1.5.3</version>
                    <executions>
                        <execution>
                            <id>p2-feature-generation</id>
                            <phase>package</phase>
                            <goals>
                                <goal>p2-feature-gen</goal>
                            </goals>
                            <configuration>
                                <id>org.wso2.carbon.orderprocessor</id>
                                <propertiesFile>../feature.properties</propertiesFile>
                                <adviceFile>
                                    <properties>
                                        <!-- This property is set to true as this is a composite feature -->
                                        <propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
                                    </properties>
                                </adviceFile>
                                <includedFeatures>
                                    <!-- Information about which features to include -->                           
                                    <includedFeatureDef>org.wso2.carbon:org.wso2.carbon.orderprocessor.ui.feature</includedFeatureDef>
                                    <includedFeatureDef>org.wso2.carbon:org.wso2.carbon.orderprocessor.server.feature</includedFeatureDef>
                                </includedFeatures>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                
                <!-- maven-antrun-plugin has been used to remove the unnecessary src,
                main, resources folders when creating the jar -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>clean_target</id>
                            <phase>install</phase>
                            <configuration>
                                <tasks>
                                    <delete dir="src/main/resources"/>
                                    <delete dir="src/main"/>
                                    <delete dir="src"/>
                                </tasks>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
file: ./order-processor-features/org.wso2.carbon.orderprocessor.feature/pom.xml

Here is the updated pom.xml at the order-processor-features project root. Note that we have added all the sub projects.

    <?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">
        
        <parent>
            <artifactId>order-processor</artifactId>
            <groupId>org.wso2.carbon</groupId>
            <version>1.0.0</version>
        </parent>
        
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>order-processor-features</artifactId>
     
        <packaging>pom</packaging>
        
        <!-- We will update the pom later -->
        <!-- Inform maven about the sub-projects -->
        <modules>
            <module>org.wso2.carbon.orderprocessor.feature</module>
            <module>org.wso2.carbon.orderprocessor.server.feature </module>
            <module>org.wso2.carbon.orderprocessor.ui.feature</module>
        </modules>

    </project>
file: ./order-processor-features/pom.xml

Below is the current directory structure for your reference. I have only expanded order-processor-features sub project.

order-processor
    ├── order-processor-components
    ├── order-processor-features
    │   ├── feature.properties
    │   ├── org.wso2.carbon.orderprocessor.feature
    │   │   └── pom.xml
    │   ├── org.wso2.carbon.orderprocessor.server.feature
    │   │   └── pom.xml
    │   ├── org.wso2.carbon.orderprocessor.ui.feature
    │   │   └── pom.xml
    │   └── pom.xml
    ├── order-processor-repository
    └── pom.xml

Create the repository

Now let’s create the repository. This is done in order-processor-repository sub project. This project is also a single pom file which tells maven to create a repository with the feature created in the order-process-feature project. Let’s update the existing pom.xml inside the project to create a repository.

    <?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">
        
        <parent>
            <artifactId>order-processor</artifactId>
            <groupId>org.wso2.carbon</groupId>
            <version>1.0.0</version>
        </parent>
        
        <modelVersion>4.0.0</modelVersion>
     
        <artifactId>order-processor-repository</artifactId>
     
        <packaging>pom</packaging>

        <!-- Repository to download the carbon-p2-plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>wso2-nexus</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
                <releases>
                    <enabled>true</enabled>
                    <updatePolicy>daily</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </pluginRepository>
        </pluginRepositories>
        
        <build>
            <plugins>
                <plugin>
                    <groupId>org.wso2.maven</groupId>
                    <artifactId>carbon-p2-plugin</artifactId>
                    <version>1.5.3</version>
                    <executions>
                        <execution>
                            <id>2-p2-repo-generation</id>
                            <phase>package</phase>
                            <goals>
                                <goal>p2-repo-gen</goal>
                            </goals>
                            <configuration>
                                <metadataRepository>file:${basedir}/target/p2-repo</metadataRepository>
                                <artifactRepository>file:${basedir}/target/p2-repo</artifactRepository>
                                <publishArtifacts>true</publishArtifacts>
                                <publishArtifactRepository>true</publishArtifactRepository>
                                <!-- Feature we need to include in the repository -->
                                <featureArtifacts>
                                    <featureArtifactDef>
                                        org.wso2.carbon:org.wso2.carbon.orderprocessor.feature:1.0.0
                                    </featureArtifactDef>
                                </featureArtifacts>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
file: ./order-processor-repository/pom.xml

Here we have instructed maven to use ./order-processor-repository/target/p2-repo as the repository location.

Install the feature to an carbon product

Now let’s install our feature to a WSO2 product. I am going to use WSO2 Application Server. You can find instructions on how to run the Application Server here.

After running the product, go to the management console by following the link shown at the end of the command line. Login using your credentials (default user name is admin with the password admin). Now navigate to Configure -> features. You’ll see something similar to the following.


Feature Management

Click add repository. A dialog box called Add Repositroy appear. Give a name for the repository and select the location of the repository by choosing Local option. Click Add button. You’ll see the available features as below (Remember to remove the tick from Group features by category check box).


Available Features

Select org.wso2.carbon.orderprocessor under the features table and click install. After restarting the product, you’ll be able to see the link to our order processor in main navigation bar.

References

  1. How to create a feature from WSO2 Carbon component