Carbon 5.0 Deployment Framework – My Notes

Carbon 5  will be the next generation WSO2 Carbon Platform with a complete new architecture written from scratch. Carbon Kernel is the base of this platform and for all the WSO2 products.

The Carbon Deployment Framework is core a module at kernel for managing the deployment of artifacts in a carbon server.

C5-DeploymentEngine

The above picture illustrates the high level view of this framework. The framework consists of following parts.

  1. Scheduler : is responsible for the scheduling the deployment task periodically.
  2. Repository Scanner : is what does the scanning of deployer directories for artifact updates.
  3. DeployerServiceListener : is an OSGi service component, which will listen to deployer registrations/unregistrations from other components (CustomDeployers) and add/remove them to/from DeploymentEngine at run-time.

The deployment engine will operate at scheduled mode by default, where a scheduler task will run periodically and calls the repository scanner to scans the available deployer directories and find any new artifacts to be deployed, artifact to be updated, and artifact to be undeployed . Then it will call the relevant deployer of those artifacts to do the deployment/undeployment process.
The deployment scan interval is 15 seconds by default. It can be configured using the carbon.xml by changing the following property : DeploymentConfig -> UpdateInterval.
The default repository location for the deployment engine is $CARBON_HOME/repository/deployment/server.

How to write a new Deployer and plug with Deployment Framework

The Deployer SPI provide a way to implement your own deployer which will be used for the deployment of different type of artifacts in carbon. A deployer will process a particular artifact type and deploy it to a run-time configuration. A developer who wants write a deployer to process an artifact in carbon and add it to a runtime configuration, should implement this.

public interface Deployer {

    /**
     * Initialize the Deployer
     *
     * This will contain all the code that need to be called when the deployer is initialized
     */
    void init();

    /**
     * Process a deployable artifact and add it to the relevant runtime configuration
     *
     * @param artifact the Artifact object to deploy
     * @return returns a key to uniquely identify an artifact within a runtime
     * @throws CarbonDeploymentException - when an error occurs while doing the deployment
     */
    Object deploy(Artifact artifact) throws CarbonDeploymentException;

    /**
     * Remove a given artifact from the relevant runtime configuration
     *
     * @param key the key of the deployed artifact used for undeploying it from the relevant runtime
     * @throws CarbonDeploymentException - when an error occurs while running the undeployment
     */
    void undeploy(Object key) throws CarbonDeploymentException;

    /**
     * Updates a already deployed artifact and update its relevant runtime configuration
     *
     * @param artifact the Artifact object to deploy
     * @return returns a key to uniquely identify an artifact within a runtime
     * @throws CarbonDeploymentException - when an error occurs while doing the deployment
     */
    Object update(Artifact artifact) throws CarbonDeploymentException;

    /**
     * Returns the deploy directory location associated with the deployer.
     * It can be relative to CARBON_HOME or an abosolute path
     *      Eg : webapps, dataservices, sequences  or
     *           /dev/wso2/deployment/repository/  or
     *           file:/dev/wso2/deployment/repository/
     *
     * @return deployer directory location
     */
    URL getLocation();

    /**
     * Returns the type of the artifact that the deployer is capable of deploying
     *      Eg : webapp, dataservice
     * @return ArtifactType object which contains info about the artifact type
     */
    ArtifactType getArtifactType();

}

The above is the interface to implement. Lets look at a real example.
As an example on how to write your own deployer and register it with Carbon Deployment Engine, lets look at a simple example deployer which process xml files. This deployer will process xml files found under “xmls” in the default carbon server repository, which is $CARBON_HOME/repository/deployment/server.

1. Create a simple maven project with the following dependecies

<dependency>
    <groupId>org.wso2.carbon</groupId>
    <artifactId>org.wso2.carbon.deployment</artifactId>
    <version>5.0.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.scr.annotations</artifactId>
    <version>1.9.6</version>
</dependency>

2. Implement the Deployer interface. For example like below

public class XMLDeployer implements Deployer {
    private static final Log log = LogFactory.getLog(XMLDeployer.class);
    private ArtifactType artifactType;
    private URL repository;

    @Override
    public void init() {
        log.info("Initializing the XMLDeployer");
        artifactType = new ArtifactType("xml");
        try {
            repository = new URL("file:xmls");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
    @Override
    public String deploy(Artifact artifact) throws CarbonDeploymentException {
        log.info("Deploying : " +artifact.getName() + " in : " +
                 artifact.getFile().getAbsolutePath());
        return artifact.getName();
    }
    @Override
    public void undeploy(Object key) throws CarbonDeploymentException {
        log.info("Undeploying : " + key);
    }
    @Override
    public Object update(Artifact artifact) throws CarbonDeploymentException {
        log.info("Updating : " +artifact.getName() + " in : " +
                 artifact.getFile().getAbsolutePath());
        return artifact.getName();
    }
    @Override
    public URL getLocation() {
        return repository;
    }
    @Override
    public ArtifactType getArtifactType() {
        return artifactType;
    }
}

3. Write an OSGi declarative service component which is used to register the above Deployer instance.

@Component(
        name = "XMLDeployerServiceComponent",
        immediate = true
)
public class XMLDeployerServiceComponent {
    private Log log = LogFactory.getLog(XMLDeployerServiceComponent.class);
    private XMLDeployer xmlDeployer = new XMLDeployer();
    private ServiceRegistration registration;
    @Activate
    public void start(ComponentContext ctxt) {
        registration = ctxt.getBundleContext().
                registerService(Deployer.class.getName(), xmlDeployer, null);
    }
    @Deactivate
    public void stop(ComponentContext ctxt) {
        registration.unregister();
    }
}

4. Once the above are in your project, we need to add the maven scr plugin and bundle plugin section to generate the components level metadata for scr annotations and bundle info. An example section on the pom file will like below

<plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.3.5</version>
        <extensions>true</extensions>
        <configuration>
            <instructions>
                <Bundle-Vendor>Sampe Inc</Bundle-Vendor>
                <Bundle-SymbolicName>org.sample.xml</Bundle-SymbolicName>
                <Private-Package>
                    org.sample.xml.deployer.internal
                </Private-Package>
                <Export-Package>
                    !org.sample.xml.deployer.internal,
                    org.sample.xml.deployer.*; version="${project.version}",
                </Export-Package>
                <Import-Package>
                    org.apache.commons.logging.*;version="${commons.logging.import.version.range}",
                    org.osgi.framework.*;version="${osgi.framework.import.version.range}"
                    org.wso2.carbon.deployment.exception.*;version="${carbon.kernel.package.import.version.range}"
                    org.wso2.carbon.deployment.spi.*;version="${carbon.kernel.package.import.version.range}"
                </Import-Package>
            </instructions>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-scr-plugin</artifactId>
        <version>1.9.0</version>
        <executions>
            <execution>
                <id>generate-scr-scrdescriptor</id>
                <goals>
                    <goal>scr</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

5. Build your deployer compoenent, which will generate an OSGi bundle. Now this bundle can be installed into a running carbon server instance using OSGI bundle install commands. By default carbon uses equinox osgi runtime. So once you start the carbon server you will see the commend console of equinox as below.

wso2@work:/media/data/wso2/carbon-kernel/distribution/target/wso2carbon-kernel-5.0.0-SNAPSHOT$ s
JAVA_HOME environment variable is set to /home/wso2/bin/java/jdk1.7.0_40
CARBON_HOME environment variable is set to /media/data/wso2/carbon-kernel/distribution/target/wso2carbon-kernel-5.0.0-SNAPSHOT
osgi>
osgi>

6. Then using the install command you can install the bundle as below. Once you install and start the bundle successfully, you will see the log message of the XMLDeployer instance getting initialized.

osgi> install file:/media/data/wso2/samples/sample-deployer/target/org.sample.xml.deployer-1.0.0-SNAPSHOT.jar
Bundle id is 36
RegisteredServices   null
ServicesInUse        null
LoaderProxy          org.sample.xml; bundle-version="1.0.0.SNAPSHOT"
Fragments            null
ClassLoader          null
Version              1.0.0.SNAPSHOT
LastModified         1390824613943
Headers               Bnd-LastModified = 1390813852361
 Build-Jdk = 1.7.0_40
 Built-By = wso2
 Bundle-Activator = org.sample.xml.deployer.internal.XMLDeployerBundleActivator
 Bundle-ManifestVersion = 2
 Bundle-Name = org.sample.xml.deployer
 Bundle-SymbolicName = org.sample.xml
 Bundle-Vendor = WSO2 Inc
 Bundle-Version = 1.0.0.SNAPSHOT
 Created-By = Apache Maven Bundle Plugin
 Export-Package = org.sample.xml.deployer;uses:="org.wso2.carbon.deployment.spi,org.apache.commons.logging,org.wso2.carbon.deployment,org.wso2.carbon.deployment.exception";version="1.0.0.SNAPSHOT"
 Import-Package = org.apache.commons.logging;version="[1.1,2)",org.osgi.framework;version="[1.7,2)",org.wso2.carbon.deployment;version="[5.0,6)",org.wso2.carbon.deployment.exception;version="[5.0,6)",org.wso2.carbon.deployment.spi;version="[5.0,6)"
 Manifest-Version = 1
 Service-Component = OSGI-INF/org.sample.xml.deployer.XMLDeployer.xml
 Tool = Bnd-1.43.0

7. Once you install and start the bundle successfully, you will see the log message of the XMLDeployer instance getting initialized as below. If this log appears, then the deployer is registered with the deployment framework successfully.

osgi> start 36
[2014-01-27 17:40:39,874]  INFO {org.sample.xml.deployer.XMLDeployer} -  Initializing the XMLDeployer

8. Testing of this deployer can be done by creating a directory named “xmls” under $CARBON_HOME/repository/deployment/server/ and adding a new xml file under this location. Then once the deployment engine scans this directory and find the new artifact, it will call the deploy method of the deployer instance. This will basically print the following log at the console. Similarly, the update and un-deployment of the deployer can also be tested by updating or removing the sample xml file.

[2014-01-27 17:56:15,205]  INFO {org.sample.xml.deployer.XMLDeployer} -  Deploying : sample.xml in : /media/wso2/carbon-kernel/distribution/target/wso2carbon-kernel-5.0.0-SNAPSHOT/repository/deployment/server/xmls/sample.xml
Advertisements

About kishanthan

I’m currently working as a Software Engineer at WSO2, an open source software company. I hold an Engineering degree, majoring in Computer Science & Engineering field, from University of Moratuwa, Sri Lanka.
This entry was posted in Carbon5, WSO2 and tagged , , , , . Bookmark the permalink.

One Response to Carbon 5.0 Deployment Framework – My Notes

  1. Pingback: Carbon 5 Kernel Architecture | Kishanthan's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s