Why is my maven build not finding Netty’s EventLoopGroup class when executing?

Tags: , ,



I wrote my code following Netty’s documentation, then I execute:

mvn package

It builds successfully. Then I run:

java -jar target/netty-listener-0.0.1-SNAPSHOT.jar

And it promts me with this error:

Exception in thread “main” java.lang.NoClassDefFoundError: io/netty/channel/EventLoopGroup at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: io.netty.channel.EventLoopGroup at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) … 7 more

To my understanding, the JRE is not finding Netty’s EventLoopGroup Class in execution time. In Eclipse, I see the netty-all dependency on Maven’s dependency tab and EventLoopGroup is there. I’ve tried to change Netty’s version multiple times but it does not work.

Here is my main code:

package paplistener;

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class PAPServer 
{
    
    private int port;
    
    public PAPServer(int port)
    {
        this.port = port;
    }

    public void run() throws Exception
    {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new CommandDecoder(),
                                            new PAPServerHandler());
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true);
            
            ChannelFuture f = b.bind(port).sync();
            
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception
    {
        int port = 8080;
        
        if(args.length > 0)
        {
            port = Integer.parseInt(args[0]);
        }
        
        new PAPServer(port).run();
    }
    
}

It is almost the exact code from Netty’s documentation, but it adds a decoder in the beginning of the pipeline.

Here is my pom.xml:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>neurony.listener</groupId>
  <artifactId>netty-listener</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <dependencies>
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.53.Final</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
  </dependencies>
  <build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>paplistener.PAPServer</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.5.1</version>
                <executions>
                    <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>
                          ${project.build.directory}/dependency-jars/
                        </outputDirectory>
                    </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
</project> 

What can I do to solve this problem?

EDIT1: Added maven-shade-plugin to pom.xml but the (same) problem persists.

Lines added to pom:

        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
            <execution>
            <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <manifestEntries>
                                <Main-Class>paplistener.PAPServer</Main-Class>
                                <Build-Number>1</Build-Number>
                            </manifestEntries>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
        </plugin>

EDIT2: added artifactSet to pom.xml but it didn’t work

<artifactSet>
    <includes>
            <include>io.netty:*</include>
    </includes>
</artifactSet>

I tried * : * as well, just as Yuri G. suggested.

EDIT3: Contents of unzip -l:

Archive: netty-listener-0.0.1-SNAPSHOT.jar Length Date Time Name


    0  10-29-2020 10:17   META-INF/
  266  10-29-2020 10:17   META-INF/MANIFEST.MF
    0  10-29-2020 10:17   paplistener/
 2903  10-29-2020 10:17   paplistener/PAPCommandHandler.class
 2554  10-29-2020 10:17   paplistener/PAPServer.class
 2103  10-29-2020 10:17   paplistener/CommandDecoder.class
 2834  10-29-2020 10:17   paplistener/PAPServerHandler.class
 1319  10-29-2020 10:17   paplistener/PAPServer$1.class
    0  10-29-2020 10:17   META-INF/maven/
    0  10-29-2020 10:17   META-INF/maven/neurony.listener/
    0  10-29-2020 10:17   META-INF/maven/neurony.listener/netty-listener/
 3572  10-28-2020 12:29   META-INF/maven/neurony.listener/netty-listener/pom.xml
  125  10-29-2020 10:17   META-INF/maven/neurony.listener/netty-listener/pom.properties

15676                     13 files

It seems like netty is not being copied to the jar file. But I still don’t know how to solve it. I’ll link here the generated .classpath (I guess Eclipse generated it):

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
  <classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/>
  <classpathentry kind="src" path="src/main/java" including="**/*.java"/>
  <classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
  <classpathentry kind="output" path="target/classes"/>
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Java SE 8 [1.8.0_121]"/>
  <classpathentry kind="var" path="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar" sourcepath="M2_REPO/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final-sources.jar"/>
  <classpathentry kind="var" path="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA.jar" sourcepath="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA-sources.jar"/>
</classpath>

Answer

The plugin element should not be inside build->pluginManagement->plugins, but inside build->plugins. Like this

<project>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>3.2.4</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>shade</goal>
          </goals>
          <configuration>
            <transformers>
              <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>com.mycompany.app.App</mainClass>
              </transformer>
            </transformers>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</project>


Source: stackoverflow