Avisi Blog

Creating a Dynamic Plugin with DotCMS and Maven

Geschreven door Mitchel Kuijpers | 11 September 2013

Avisi recently started using dotCMS. We are currently moving our old website from Wordpress to DotCMS. On the old website there is a Twitter feed which we got from a Wordpress Plugin. For DotCMS we had to create our own widget because their given Twitter plugin makes use of the old Twitter API.

 

Getting the DotCMS jar in Maven

I will walk you through our process of creating a twitter plugin.

 

In DotCMS you have Dynamic Plugins which are basically just OSGI plugins. If you follow their walkthrough you have to fiddle with Ant. At Avisi we use Maven so I created a plugin with Maven. The first step to get this working is making the DotCMS jar available for maven. If you download the the Community Edition and unpack it you can find the jar at

 

dotserver/dotCMS/WEB-INF/lib/dotcms_X.X.X.jar

 

To use this jar with maven you have to install this jar locally:

mvn install:install-file -Dfile=dotcms_X.X.X.jar -DgroupId=com.dotcms \
-DartifactId=dotcms -Dversion=X.X.X -Dpackaging=jar

 

Creating the pom.xml

The next step was creating a pom.xml for our maven project with the following dependencies:


<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>[3.0,)</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.http.bundle</artifactId>
<version>2.2.0</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>4.2.1</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.dotcms</groupId>
<artifactId>dotcms</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>

 

The code for the Dynamic Plugin

To show a twitter feed we shall make a ViewTool that will be accessible from velocity templates.


package nl.avisi.dotcms.plugin.twitter;

import org.apache.velocity.tools.view.tools.ViewTool;

import java.util.List;

import twitter4j.*;
import twitter4j.conf.ConfigurationBuilder;

public class TwitterTool implements ViewTool {

private Twitter twitter;

@Override
public void init(Object initData) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(false)
.setOAuthConsumerKey("XXXXXXXXXX")
.setOAuthConsumerSecret("XXXXXXXXXX")
.setOAuthAccessToken("XXXXXXXXXX")
.setOAuthAccessTokenSecret("XXXXXXXXXXX");
TwitterFactory tf = new TwitterFactory(cb.build());
twitter = tf.getInstance();
}

public List search(String queryString, String count) throws TwitterException {
Query query = new Query(queryString);
query.setCount(Integer.parseInt(count));
QueryResult result = twitter.search(query);
return result.getTweets();
}

}

 

This is pretty simplistic example, but it does the job. The next step is configuring the ViewTool so it will become available in all your velocity templates under the key "avisiTwitterTool".

 

package nl.avisi.dotcms.plugin.twitter;

import org.apache.velocity.tools.view.context.ViewContext;
import org.apache.velocity.tools.view.servlet.ServletToolInfo;

public class TwitterToolInfo extends ServletToolInfo {

@Override
public String getKey () {
return "avisiTwitterTool";
}

@Override
public String getScope () {
return ViewContext.APPLICATION;
}

@Override
public String getClassname () {
return TwitterTool.class.getName();
}

@Override
public Object getInstance ( Object initData ) {

TwitterTool viewTool = new TwitterTool();
viewTool.init( initData );

return viewTool;
}

}

 

The next step is actually activating the Dynamic Plugin, this can be done by creating a BundleActivator which will register and unregister our new TwitterViewTool:

 

package nl.avisi.dotcms.plugin.twitter;

import com.dotmarketing.osgi.GenericBundleActivator;

import org.osgi.framework.BundleContext;

public class Activator extends GenericBundleActivator {

@Override
public void start ( BundleContext bundleContext ) throws Exception {
//Initializing services...
initializeServices(bundleContext);

//Registering the ViewTool service
registerViewToolService( bundleContext, new TwitterToolInfo() );
}

@Override
public void stop ( BundleContext bundleContext ) throws Exception {
unregisterViewToolServices();
}

}

 

This is all the necessary code to get a TwitterViewTool in dotCMS.

 

Package the Dynamic plugin

To actually get this code working as a Dynamic Plugin we need to make some changes in the pom.xml. This is necessary because the jar we create will become an OSGI plugin, a jar that's get's packaged as an OSGI plugin is called a bundle. To make a bundle from our jar we need to create a MANIFEST.MF file that contains all the information that the OSGI container needs to load our Dynamic Plugin. Luckily we get some help from maven in creating this file in the form of a maven plugin, I added the following to my pom.xml

 

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Bundle-Activator>nl.avisi.dotcms.plugin.twitter.Activator</Bundle-Activator>
<Private-Package>
nl.avisi.dotcms.plugin.twitter
</Private-Package>
<DynamicImport-Package>*</DynamicImport-Package>
<Import-Package>
org.osgi.service.http,
org.apache.felix.http.api,
org.apache.velocity.tools,
org.apache.velocity.tools.view,
org.apache.velocity.tools.view.tools,
com.google.common.cache,
com.google.common.collect
</Import-Package>
<Export-Package></Export-Package>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

 

The most important part of this configuration are the bundle activator property that lists our Activator class and the Import-Package property that lists all the dotCMS classes we want to use. You can view the complete pom.xml here.

 

Loading the Dynamic Plugin in DotCMS

Congratulations, you've just created your first Dynamic Plugin for dotCMS with maven. Go ahead and load the plugin in your dotCMS instance and start creating awesome widgets with your Twitter Feeds. Below is a little code snippet you can use to render tweets:

 

<ul class="list-group avisi-footer-content">
#foreach($tweet in $avisiTwitterTool.search($query, $numberOfResults))
<li class="list-group-item">
#set($url = "http://twitter.com/#!/${tweet.User.ScreenName}/status/$tweet.Id")
<a href="$url">$tweet.Text</a> <br />
<span class="text-muted">@$tweet.User.ScreenName</span>
</li>
#end
</ul>

Happy coding!