Openfire Logo

Plugin Development: Openfire 5.0.0's Jetty 12 upgrade

Overview

In Openfire 5.0.0, the embedded webserver (Jetty) was upgraded to version 12. Many plugins that are developed against older versions of Openfire are known to be compatible, and will continue to work. That, however, is not the case for all plugins. This guide describes the most common issues.

Note that many of the problems are caused by relatively simple package changes. Quite often, a class with the same (or very similar) name than the one that's no longer available can be found in another Java package.

New in Jetty 12 is that the Servlet layer has been separated away from the Jetty Core layer. The Servlet layer has been moved to the new Environments concept introduced with Jetty 12. Openfire 5.0.0 is using the Jakarta EE8 environment, which retains the javax.servlet packages known from earlier versions. The associated Jetty GroupId is org.eclipse.jetty.ee8, which is commonly used as a (part of) a Jetty java package name.

Update parent POM and Admin Console page (JSP) compilation

Most Openfire plugins inherit from the parent pom provided by the org.igniterealtime.org:plugins artifact. For version 5.0.0, this updates that Maven plugin used for compilation of the JSP pages that make up the admin console. Be sure to modify the Maven plugin that's defined in your pom.xml when you update parent plugin version to 5.0.0 (or later). The required changes are illustrated in the examples below.

Partial Plugin pom.xml content for older versions of Openfire
<project>
    <parent>
        <artifactId>plugins</artifactId>
        <groupId>org.igniterealtime.openfire</groupId>
        <version>4.9.2</version>
    </parent>

    <build>
        <plugins>
            <!-- Compiles the Openfire Admin Console JSP pages. -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-jspc-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Partial Plugin pom.xml content after updating to Openfire 5.0.0
<project>
    <parent>
        <artifactId>plugins</artifactId>
        <groupId>org.igniterealtime.openfire</groupId>
        <version>5.0.0</version>
    </parent>

    <build>
        <plugins>
            <!-- Compiles the Openfire Admin Console JSP pages. -->
            <plugin>
                <groupId>org.eclipse.jetty.ee8</groupId>
                <artifactId>jetty-ee8-jspc-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

New WebAppContext

When a plugin uses a org.eclipse.jetty.webapp.WebAppContext that is registered with Openfire's embedded webserver that serves public content through org.jivesoftware.openfire.http.HttpBindManager.addJettyHandler(org.eclipse.jetty.server.Handler) then migration to org.eclipse.jetty.ee8.webapp.WebAppContext may cause runtime class cast errors.

Two solutions are available in Openfire 5.0.0:

  1. In Openfire 5.0.0, an overloaded method org.jivesoftware.openfire.http.HttpBindManager#addJettyHandler(org.eclipse.jetty.ee8.nested.ContextHandler) was added. This can be used directly with your org.eclipse.jetty.ee8.webapp.WebAppContext instance.
  2. The original method org.jivesoftware.openfire.http.HttpBindManager#addJettyHandler(org.eclipse.jetty.server.Handler) can be invoked with the 'core' context handler that can be obtained through org.eclipse.jetty.ee8.nested.ContextHandler#get

By virtue of the new overloaded method described in the first option, it's likely that your implementation needs little change to register the context handler.

Known Error Details and Potential Solutions

This section provides further details on the errors observed and offers suggestions for addressing them.

Partially blank Admin Console pages

When a plugin-provided admin console page is mostly blank, then there might have been a problem during compilation of the JSP file that makes up the page.

If this problem occurs in relation to the upgrade to Openfire 5.0.0, then check the Maven configuration of your plugin. Ensure that both

  • the 'parent' pom that's being used is version 5.0.0 (or later)
  • the old JSPC compiler plugin has been replaced by the new one (note that both the groupId and artifactId have changed).

java.lang.VerifyError: Bad type on operand stack

Error found in openfire.log
java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/eclipse/jetty/servlet/ServletContextHandler.setGzipHandler(Lorg/eclipse/jetty/server/handler/gzip/GzipHandler;)V @6: invokespecial
  Reason:
    Type 'org/eclipse/jetty/server/handler/gzip/GzipHandler' (current frame, stack[2]) is not assignable to 'org/eclipse/jetty/server/handler/HandlerWrapper'
  Current Frame:
    bci: @6
    flags: { }
    locals: { 'org/eclipse/jetty/servlet/ServletContextHandler', 'org/eclipse/jetty/server/handler/gzip/GzipHandler' }
    stack: { 'org/eclipse/jetty/servlet/ServletContextHandler', 'org/eclipse/jetty/server/handler/gzip/GzipHandler', 'org/eclipse/jetty/server/handler/gzip/GzipHandler' }
  Bytecode:
    0000000: 2a2a b400 352b b700 762a 2bb5 0035 2ab7
    0000010: 0018 b1
    at org.jivesoftware.openfire.plugin.MonitoringPlugin.loadPublicWeb(MonitoringPlugin.java:279) ~[monitoring-2.6.1.jar:?]
    at org.jivesoftware.openfire.plugin.MonitoringPlugin.initializePlugin(MonitoringPlugin.java:186) ~[monitoring-2.6.1.jar:?]
    at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java:640) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:380) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:368) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
    at java.lang.Thread.run(Thread.java:840) [?:?]

Consider using org.eclipse.jetty.server.Handler.Wrapper (javadoc) to replace org.eclipse.jetty.server.handler.HandlerWrapper usage.

java.lang.NoClassDefFoundError: org/eclipse/jetty/webapp/WebAppContext

Error found in openfire.log
java.lang.NoClassDefFoundError: org/eclipse/jetty/webapp/WebAppContext
    at org.igniterealtime.openfire.plugin.inverse.InversePlugin.initializePlugin(InversePlugin.java:63) ~[inverse-10.1.7.1.jar:?]
    at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java:640) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:380) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:368) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
    at java.lang.Thread.run(Thread.java:840) [?:?]
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.webapp.WebAppContext
    at java.net.URLClassLoader.findClass(URLClassLoader.java:445) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
    ... 8 more

Consider using the EE8 WebAppContext from org.eclipse.jetty.ee8.webapp.WebAppContext to replace org.eclipse.jetty.webapp.WebAppContext usage.

java.lang.NoClassDefFoundError: org/eclipse/jetty/security/ConstraintSecurityHandler

Error found in openfire.log
java.lang.NoClassDefFoundError: org/eclipse/jetty/security/ConstraintSecurityHandler
    at java.lang.Class.getDeclaredConstructors0(Native Method) ~[?:?]
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:3373) ~[?:?]
    at java.lang.Class.getConstructor0(Class.java:3578) ~[?:?]
    at java.lang.Class.newInstance(Class.java:626) ~[?:?]
    at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java:587) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:380) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:368) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
    at java.lang.Thread.run(Thread.java:840) [?:?]
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.security.ConstraintSecurityHandler
    at java.net.URLClassLoader.findClass(URLClassLoader.java:445) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
    ... 11 more

Consider using the EE8 ConstraintSecurityHandler from org.eclipse.jetty.ee8.security.ConstraintSecurityHandler to replace org.eclipse.jetty.security.ConstraintSecurityHandler.

java.lang.NoClassDefFoundError: org/eclipse/jetty/websocket/server/JettyWebSocketCreator

Error found in openfire.log
java.lang.NoClassDefFoundError: org/eclipse/jetty/websocket/server/JettyWebSocketCreator
    at uk.ifsoft.openfire.plugins.pade.PadePlugin.initializePlugin(PadePlugin.java:117) ~[pade-1.8.3.jar:?]
    at org.jivesoftware.openfire.container.PluginManager.loadPlugin(PluginManager.java:640) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:380) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:368) [xmppserver-4.10.0-SNAPSHOT.jar:4.10.0-SNAPSHOT]
    at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
    at java.lang.Thread.run(Thread.java:840) [?:?]
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.websocket.server.JettyWebSocketCreator
    at java.net.URLClassLoader.findClass(URLClassLoader.java:445) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[?:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
    ... 8 more

Consider using the EE8 JettyWebSocketServlet from org.eclipse.jetty.ee8.websocket.server.JettyWebSocketServlet to replace org.eclipse.jetty.websocket.server.JettyWebSocketCreator.