Jump to content

[1.16.5] Cannot shadow external JAR properly (java.lang.NoClassDefFoundError)


ZigTheHedge

Recommended Posts

Hey, guys!

I'm trying to add javax.websocket in my mod. In dev environment everything is smooth, but when I build my mod and add it to modpack, I'm getting java.lang.NoClassDefFoundError.

Here's my build.gradle:

buildscript {
    repositories {
        maven { url = 'https://maven.minecraftforge.net' }
        mavenCentral()
        repositories {
            maven {
                url "https://plugins.gradle.org/m2/"

            }
        }
    }
    dependencies {
        classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true
        classpath "com.github.jengelman.gradle.plugins:shadow:4.0.4"
    }
}
apply plugin: 'net.minecraftforge.gradle'
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
apply plugin: 'com.github.johnrengelman.shadow'

version = '1.16.5-1.0.0'
group = 'com.cwelth.omd' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'omd'

java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8.

println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
minecraft {
    mappings channel: 'official', version: '1.16.5'

    runs {
        client {
            workingDirectory project.file('run')
            property 'forge.logging.markers', 'REGISTRIES'
            property 'forge.logging.console.level', 'debug'

            mods {
                examplemod {
                    source sourceSets.main
                }
            }
        }

        server {
            workingDirectory project.file('run')
            property 'forge.logging.markers', 'REGISTRIES'
            property 'forge.logging.console.level', 'debug'

            mods {
                examplemod {
                    source sourceSets.main
                }
            }
        }

        data {
            workingDirectory project.file('run')
            property 'forge.logging.markers', 'REGISTRIES'
            property 'forge.logging.console.level', 'debug'

            args '--mod', 'examplemod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')

            mods {
                examplemod {
                    source sourceSets.main
                }
            }
        }
    }
}

// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }

repositories {
    mavenLocal()
    mavenCentral()
    maven {
        url = 'https://mvnrepository.com/artifact/javax'
    }
    maven {
        url = 'https://mvnrepository.com/artifact/org.glassfish.tyrus.bundles'
    }
    flatDir {
        dirs 'libs\\'
    }
}

configurations {
    embed
    compileOnly.extendsFrom(embed)
}

shadowJar {
    configurations = [project.configurations.embed]
}
reobf {
    shadowJar {
        dependsOn tasks.createMcpToSrg
        mappings = tasks.createMcpToSrg.outputs.files.singleFile
    }
}
artifacts {
    archives tasks.shadowJar
}

dependencies {
    minecraft 'net.minecraftforge:forge:1.16.5-36.1.30'

    /*
    compile 'javax.websocket:javax.websocket-client-api:1.1'
    compile 'org.glassfish.tyrus.bundles:tyrus-standalone-client:1.9'
    */

    embed 'javax.websocket:javax.websocket-client-api:1.1'
    embed 'org.glassfish.tyrus.bundles:tyrus-standalone-client:1.9'

}

// Example for how to get properties into the manifest for reading by the runtime..
jar {
    manifest {
        attributes([
            "Specification-Title": "examplemod",
            "Specification-Vendor": "examplemodsareus",
            "Specification-Version": "1", // We are version 1 of ourselves
            "Implementation-Title": project.name,
            "Implementation-Version": "${version}",
            "Implementation-Vendor" :"examplemodsareus",
            "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
        ])
    }
}

jar.finalizedBy('reobfJar') 

publishing {
    publications {
        mavenJava(MavenPublication) {
            artifact jar
        }
    }
    repositories {
        maven {
            url "file:///${project.projectDir}/mcmodsrepo"
        }
    }
}

And I can see that needed packages are in my compiled jar:

image.thumb.png.1cb7058fce57cf914a45e26b1a94e3e6.png

Edited by ZigTheHedge
Link to comment
Share on other sites

Okay. Solved. If anyone is interested:

First of all, I had to use "relocate" in shadowJar to shadow both packages like this:

shadowJar {
    configurations = [project.configurations.embed]
    relocate 'org.glassfish', 'shaded.glassfish'
    relocate 'javax.websocket', 'shaded.websocket'
    classifier = ''
}

After that, pay close attention at your META-INF. In my case there was a direct reference to unshadowed package service called "javax.websocket.ContainerProvider", containing unshadowed path to class... So, just find a way to replace this file with one, that is referencing your shadowed configuration. In my case, file is called "shaded.websocket.ContainerProvider".

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.