Gradle 'maven-publish' plugin fails with "unmappable character for encoding" error

832 views Asked by At

I've recently migrated a project from Maven to Gradle (IE: replaced the pom.xml file with a build.gradle file). Since my company still has several downstream Maven projects that depend on it we must continue to publish a pom file along with class, source, and javadoc JARs to our Nexus repository so that the downstream projects can still consume this project as a Maven dependency. This is what the 'maven-publish' plugin for Gradle is for. Here is what my build.gradle file looks like with configurations for the maven-publish plugin:

apply plugin: 'java'
apply plugin: 'maven-publish'

group = 'com.my.company'
version = 'myProduct-SNAPSHOT'

repositories {
    mavenLocal()
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/build-test-release' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/build-test-snapshot' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/central' }
    maven { url 'http://nexus.my.company.net/nexus/content/repositories/thirdparty' }
}

dependencies {
    // Stuff
}

sourceSets {
    main {
        // Stuff
    }
}

task sourcesJar (type: Jar) {
    classifier = 'sources'
    from sourceSets.main.allJava
}

task javadocJar (type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

publishing {
    publications {
        mavenJars(MavenPublication) {

            // Classes
            from components.java

            // Sources
            artifact(sourcesJar) {
                classifier = 'sources'
            }

            // Javadoc
            artifact(javadocJar) {
                classifier = 'javadoc'
            }
        }
    }
    repositories {
        maven {
            url 'http://nexus.my.company.net/nexus/content/repositories/build-test-snapshot'
            credentials {
                username 'user'
                password 'password'
            }
        }
    }
}

This generates a Gradle 'publish' task that will generate the required pom.xml file as well as the class, source, and javadoc JARs. Once that's completed it will publish the jars to the 'build-test-snapshot' Nexus repository.

This works perfectly fine on my machine as well as our build servers and most of my co-workers' boxes. However, some co-workers have been complaining because the 'gradlew publish' command (note that a Gradle 2.4 wrapper has been included with the project) is failing on them with errors like these:

C:\Users\user\Perforce\WORKSPACE\project\src\main\java\com\my\company\test\randomizati
on\RandomHelper.java:18: error: unmappable character for encoding Cp1252
    private static final String NON_ENGLISH_CHARACTERS = "1234567890─Ç─?─é─â─ä─à─å─ç─ê─ë─è─ï─î─?─Ä─?─?─æ─Æ─ô─ö─ò─û─ù─ÿ─Ö
─Ü─¢─£─?─₧─ƒ─á─í─ó─ú─ñ─Ñ─ª─º─¿─⌐─¬─½─¼─¡─«─»─░─▒─▓─│─┤─╡─╢─╖─╕─╣─║─╗─╝─╜─╛─┐┼Ç┼?┼é┼â┼ä┼à┼å┼ç┼ê┼ë┼è┼ï┼î┼?┼Ä┼?┼?┼æ┼Æ┼ô┼ö┼ò
┼û┼ù┼ÿ┼Ö┼Ü┼¢┼£┼?┼₧┼ƒ┼á┼í┼ó┼ú┼ñ┼Ñ┼ª┼º┼¿┼⌐┼¬┼½┼¼┼¡┼«┼»┼░┼▒┼▓┼│┼┤┼╡┼╢┼╖┼╕┼╣┼║┼╗┼╝┼╜┼╛┼┐╞Ç╞?╞é╞â╞ä╞à╞å╞ç╞ê╞ë╞è╞ï╞î╞?╞Ä╞?╞Æ╞á
╞í╞»╟?╟Ä╟?╟?╟æ╟Æ╟ô╟ö╟ò╟û╟ù╟ÿ╟Ö╟Ü╟¢╟£╟║╟╗╟╝╟╜╟╛╟┐├Ç├?├é├â├ä├à├å├ç├ê├ë├è├ï├î├?├Ä├?├?├æ├Æ├ô├ö├ò├û├ù├ÿ├Ö├Ü├¢├£├?├₧├ƒ├á├í├ó├ú
äåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ&-.*$";

Interestingly enough, the 'gradlew build' command (which compiles the project using javac) executes just fine on everyones' machines. It's the 'gradlew publish' command which has problems on some machines (either passing or failing on both Mac and Windows).

I can't tell what the key difference is here, but I suspect that the affected users have their Perforce clients misconfigured (no P4CHARSET specified) and have all of the project files synced to their machines with the default encoding. It's not clear to me how to check what encoding Perforce used when syncing though, so this is just a theory. As far as I understand, even if they fix their configurations they'll still need to wipe out their enlistments and download everything from the Perforce server again to get all of the files with the correct encoding (utf16le-bom).

Regardless of any Perforce issues the blame is falling back on me since I'm the one that switched us over to Gradle in the first place. If there's some way that I can configure the maven-publish plugin to work around the issue then I'd prefer to do that. If javac can compile the non-standard characters from these files into classes then there's no reason that the plugin can't read them and generate javadoc for them, right? Maybe it needs to be explicitly told what encoding to use?

I've already tried playing around with the -Dfile.encoding=x-UTF-16LE-BOM option in JAVA_OPTS and GRADLE_OPTS (this made no difference). I've also found the following snippet used for specifying the encoding for 'Compile' tasks in Gradle:

tasks.withType(Compile) {
    options.encoding = 'x-UTF-16LE-BOM'
}

Unfortunately, this is for 'Compile' tasks, and the project is already compiling successfully. I'm not sure what type of tasks the maven-publish plugin is generating, so I don't know how to apply this approach for those tasks (is this possible?).

What else can I try to make the Gradle maven-publish plugin stop tripping over file-encodings?

1

There are 1 answers

1
Alex Jansen On BEST ANSWER

After diving into the Gradle API I came up with this:

// Force character encoding in case the workspace was not set up correctly
tasks.withType(Javadoc) {
    options.encoding = 'x-UTF-16LE-BOM'
}

This has resolved the issue on machines that were previously failing with encoding errors when running 'gradlew publish'.

Note: For most use cases options.encoding should be set to UTF8 and not x-UTF-16LE-BOM.