Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Starting plugin development in Openfire

New Openfire Plugin

Install requirements

$ sudo pacman -S \
	intellij-idea-community-edition \
	jre8-openjdk \


$ export WORKSPACE_FOLDER=/home/fabio/Work/avantech


Getting the code

$ git clone --depth=1 openfire

Building the project

$ cd openfire
$ mvn verify
$ cd ..

A dumb plugin

Creating folders

$ mkdir -p example-plugin/src/web
$ mkdir -p example-plugin/src/java/br/com/example

Creating the pom.xml

$ cat > example-plugin/pom.xml <<'EOF'
<project xmlns="" xmlns:xsi=""

    <name>Example Plugin</name>
    <description>A start point to create a new plugin</description>

        <name>Example Organization</name>

            <name>Example Author</name>
            <organization>Example Organization</organization>

                <!-- FIXME: This temporarily overrides the provided plugin, to set appendAssemblyId and attach to true.
                     This change should be pushed down to the parent project, after the development to distribute plugins via Maven has settled. -->
                            <!-- This is where we use our shared assembly descriptor -->
                <!-- End of override -->
            <!-- Compiles the Openfire Admin Console JSP pages. -->


        <!-- Repository in which we deploy this project, when desired. -->
            <name>Ignite Realtime Repository</name>

        <!-- Where we obtain dependencies. -->
            <name>Ignite Realtime Repository</name>

        <!-- Typically used to retrieve Maven plugins used by this project from. This
             apparently is also used to obtain the dependencies _used by_ plugins
             (eg: openfire-plugin-assembly-descriptor) -->
            <name>Ignite Realtime Repository</name>

Creating the plugin.xml

$ cat > example-plugin/plugin.xml <<'EOF' 
<?xml version="1.0" encoding="UTF-8"?>
    <name>Example Plugin</name>
    <description>A start point to create a new plugin</description>
    <author>Example author</author>

Creating the plugin main class

$ cat > example-plugin/src/java/br/com/example/ <<'EOF' 

import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

  * This class initialize the ExamplePlugin
public class ExamplePlugin implements Plugin
    private static final Logger Log = LoggerFactory.getLogger( ExamplePlugin.class );

    public void initializePlugin( PluginManager manager, File pluginDirectory )
    {"Initializing Example Plugin");

    public void destroyPlugin()
    {"Destroying Example Plugin");

Verify if dumb plugin compile

$ cd example-plugin
$ mvn verify 


Setting up IDEA

  1. Execute idea
  2. Click on Import Project
  3. Select the Openfire directory
  4. Select Maven option and clik on Next
  5. Click on Next
  6. Click on Next
  7. Click on Next
  8. Check if JRE is select and click on Next
  9. Give Project name the value openfire and click on Finish
  10. Click on File > Project Structure
  11. Got to modules section
  12. Click on + sign in the top of second column
  13. Click on Import module
  14. Select example-plugin
  15. Select Maven option and clik on Next
  16. Click on Next
  17. Click on Next
  18. Click on Finish
  19. Click on Ok
  20. Click on Run > Edit Configurations
  21. Click on + sign and select Remote
  22. Change the Name from Unamed to Attach on Openfire
  23. Copy the content of Command line arguments for remote JVM, it will be something like -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Running Openfire

The only I could have breakpoints during development was adding manually the options -DpluginDirs, -Dexample-plugin.classes, -Dexample-plugin.webRoot. Even passing these options, depending the type of change made in source code, it will be necessary to restart Openfire.

$ cd openfire
$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \
	-Dlog4j.configurationFile=${WORKSPACE_FOLDER}/openfire/distribution/target/distribution-base/lib/log4j2.xml \
	-server \
	-DopenfireHome="${WORKSPACE_FOLDER}/openfire/distribution/target/distribution-base" \
	-DpluginDirs="${WORKSPACE_FOLDER}/example-plugin" \
	-Dexample-plugin.classes="target/classes" \
	-Dexample-plugin.webRoot="src/web" \
	-Dopenfire.lib.dir="${WORKSPACE_FOLDER}/openfire/distribution/target/distribution-base/lib" \
	-classpath "${WORKSPACE_FOLDER}/openfire/distribution/target/distribution-base/lib/startup.jar" \
	-jar "${WORKSPACE_FOLDER}/openfire/distribution/target/distribution-base/lib/startup.jar"

You should see an output like

Listening for transport dt_socket at address: 5005
Openfire 4.4.0 Alpha [Feb 21, 2019 5:05:11 PM]
Admin console listening at:
Successfully loaded plugin 'admin'.
Plugin 'example-plugin' is running in development mode.
Successfully loaded plugin 'example-plugin'.
Successfully loaded plugin 'search'.
Finished processing all plugins.

That is it. Have fun


This comment has been minimized.

Copy link

@abdurrahmanekr abdurrahmanekr commented Aug 8, 2019

Hi @fabiomontefuscolo, thanks for this post. This way the debug is successful, but I get a NoClassDefFoundError error when I try it on a plugin with dependency. You can get this error by installing this plugin: openfire-monitoring-plugin. I've been dealing with this for a week and there's no one I can get help with. How do I debug a plugin that has dependencies? Thanks for your help


This comment has been minimized.

Copy link

@abdurrahmanekr abdurrahmanekr commented Aug 8, 2019

And in the meantime, I used the plugin in the /plugins directory instead of running it in the main (/) directory.


This comment has been minimized.

Copy link
Owner Author

@fabiomontefuscolo fabiomontefuscolo commented Aug 13, 2019

@abdurrahmanekr it was very dirty, but I took all deps maven downloaded and uncompressed that in the classes folder.


This comment has been minimized.

Copy link

@parcool parcool commented Apr 21, 2020

why my jar has only two folder that and META-INF?


This comment has been minimized.

Copy link
Owner Author

@fabiomontefuscolo fabiomontefuscolo commented Apr 29, 2020

Hi @parcool. I think you should have two jars. One will have the word assembly in the name. You should use this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.