Description of the issue:
I made a fairly minimal configuration for this trellis-ext-db project: https://github.com/trellis-ldp/trellis-ext-db
When I run it I get a ClassCastException in the HTTP layer, where the Apache HTTP client is trying to cast a Long value into an Integer as part of the request configuration. Looks like an API mismatch. Sorry if I am missing something obvious to others.
Expected behavior:
Jib should download the 'openjdk:8-slim' baseimage from DockerHub.
Steps to reproduce:
1) Check out the trellis-ext-db project
2) Replace the build.gradle files with the content below
3) Run command: ./gradlew build
4) Run command: ./gradlew jibDockerBuild --stacktrace
Environment:
Ubuntu 16
Gradle 4.8.1
jib-gradle-plugin Configuration:
build.gradle (click the arrow to expand for details)
apply plugin: 'application'
apply plugin: 'distribution'
apply plugin: 'nebula.ospackage-application'
description = 'Trellis Database Application'
mainClassName = 'org.trellisldp.ext.app.db.TrellisApplication'
applicationName = 'trellis-db'
dependencies {
compile project(':trellis-db-app')
runtime("javax.xml.bind:jaxb-api:$jaxbVersion")
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.ajoberstar:grgit:1.1.0'
}
}
// Get commit id of HEAD.
apply plugin: 'java'
apply plugin: 'application'
ext {
git = org.ajoberstar.grgit.Grgit.open(file('../.'))
revision = git.head().id
}
ospackage {
packageName = 'trellis-db'
release = '1'
os = LINUX
license = 'ASL 2.0'
url = 'https://www.trellisldp.org'
summary = 'Trellis is a linked data server.'
packageDescription = '''\
Trellis is a linked data server that can be used for storing large volumes of content,
particularly in cases where that content is stored for years and decades.'''
user = 'trellis'
// Note: the linux installers do not depend on Java because it is too complicated to
// reliably navigate this dependency across linux distributions and supported JRE versions.
requires('systemd')
into '/opt/trellis'
from ('scripts') {
into 'bin'
fileMode = 0550
}
from ('jar.outputs.files') {
into 'lib'
}
from ('src/dist/etc') {
fileType CONFIG | NOREPLACE
into '/opt/trellis/etc'
}
from ('src/dist/data') {
fileType CONFIG | NOREPLACE
into '/opt/trellis/data'
}
}
buildRpm {
preInstall file('src/rpm/preInstall.sh')
postInstall file('src/rpm/postInstall.sh')
preUninstall file('src/rpm/preUninstall.sh')
}
buildDeb {
preInstall file('src/deb/preInstall.sh')
postInstall file('src/deb/postInstall.sh')
preUninstall file('src/deb/preUninstall.sh')
}
jib {
extraDirectory = file('src/docker')
from {
image = 'openjdk:8-jdk'
}
to {
image = 'gregjan/trellis-extdb'
credHelper = 'docker-credential-*'
}
container {
labels = ['git.url':'https://github.com/trellis-ldp/trellis-ext-db', 'git.commit':revision]
mainClass = mainClassName
args = ['server', '/config.yml']
ports = ['80']
}
}
signing {
sign buildRpm
sign buildDeb
sign distTar
sign distZip
}
test {
jacoco {
enabled = false;
}
}
task copyDistTask(type: Copy) {
from '../LICENSE'
from 'README.md'
into 'src/dist'
}
assembleDist {
dependsOn copyDistTask
dependsOn buildRpm
dependsOn buildDeb
dependsOn signBuildRpm
dependsOn signBuildDeb
}
The file above is in a sub-project called 'deployment'. The main build.gradle file looks like this:
plugins {
id 'com.github.hierynomus.license' version '0.14.0'
id 'com.github.ben-manes.versions' version '0.20.0'
id 'net.researchgate.release' version '2.7.0'
id 'com.github.kt3k.coveralls' version '2.8.2'
id 'org.sonarqube' version '2.6.2'
id 'nebula.ospackage' version '4.9.3'
id 'org.owasp.dependencycheck' version '3.2.1'
id 'com.google.cloud.tools.jib' version '0.9.10'
}
ext {
/* Dependencies */
activationVersion = '1.1.1'
jdbiVersion = '3.3.0'
commonsLangVersion = '3.7'
commonsRdfVersion = '0.5.0'
kafkaVersion = '1.1.0'
trellisVersion = '0.7.1'
mysqlVersion = '8.0.11'
javaxInjectVersion = '2.5.0-b61'
tamayaVersion = '0.3-incubating'
slf4jVersion = '1.7.25'
activeMqVersion = '5.15.4'
jmsApiVersion = '2.0.1'
dropwizardVersion = '1.3.5'
snakeyamlVersion = '1.21'
/* Databases */
mysqlVersion = '8.0.11'
postgresVersion = '42.2.3'
/* Testing */
activationVersion = '1.1.1'
apiguardianVersion = '1.0.0'
checkstyleVersion = '8.10'
commonsTextVersion = '1.4'
guavaVersion = '25.1-jre'
h2Version = '1.4.197'
jaxbVersion = '2.3.0'
jacocoVersion = '0.8.1'
junitPlatformVersion = '1.2.0'
junitVersion = '5.2.0'
liquibaseVersion = '3.6.2'
logbackVersion = '1.2.3'
mockitoVersion = '2.19.0'
otjPgVersion = '0.12.0'
/* OSGi */
projectOsgiVersion = project.version.replaceAll("-SNAPSHOT", ".SNAPSHOT")
}
allprojects { subproj ->
apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: 'checkstyle'
apply plugin: 'com.github.hierynomus.license'
apply plugin: 'jacoco'
ext {
vendor = 'Trellis LDP'
homepage = 'https://www.trellisldp.org'
docURL = 'https://trellis-ldp.github.io/trellis/apidocs/'
license = 'Apache 2'
}
jacoco.toolVersion = jacocoVersion
group = 'org.trellisldp.ext'
repositories {
mavenCentral()
jcenter()
mavenLocal()
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testImplementation("org.apiguardian:apiguardian-api:${apiguardianVersion}")
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
release {
tagTemplate = '$name-$version'
git {
requireBranch = 'master'
signTag = true
}
}
}
subprojects { subproj ->
sourceCompatibility = 1.8
targetCompatibility = 1.8
jar {
from("$rootDir/LICENSE") {
into "META-INF"
}
}
checkstyle {
configFile = rootProject.file('buildtools/src/main/resources/checkstyle/checkstyle.xml')
configProperties.checkstyleConfigDir = rootProject.file('buildtools/src/main/resources/checkstyle/')
toolVersion = checkstyleVersion
}
task javadocJar(type: Jar) {
classifier 'javadoc'
from("$rootDir/LICENSE") {
into "META-INF"
}
from javadoc
}
task sourceJar(type: Jar) {
classifier 'sources'
from("$rootDir/LICENSE") {
into "META-INF"
}
from sourceSets.main.allSource
}
task processConfig(type: Copy) {
from('src/main/cfg') {
include '**/*.cfg'
}
into 'build/cfg/main'
}
classes {
classes.dependsOn processConfig
}
artifacts {
archives javadocJar
archives sourceJar
}
license {
include "**/*.java"
header rootProject.file('buildtools/src/main/resources/license/HEADER.txt')
strictCheck true
mapping {
java = 'SLASHSTAR_STYLE'
}
}
publishing {
publications {
mavenJava(MavenPublication) {
pom {
packaging = 'jar'
name = 'Trellis Linked Data Server: database extension'
description = 'A database persistence layer for the Trellis linked data server'
url = "https://www.trellisldp.org"
inceptionYear = '2017'
organization {
name = project.vendor
url = project.homepage
}
developers {
developer {
id = 'acoburn'
name = 'Aaron Coburn'
email = 'acoburn (at) apache (dot) org'
}
}
scm {
connection = 'scm:git:git://github.com/trellis-ldp/trellis-ext-db.git'
developerConnection = 'scm:git:[email protected]/trellis-ldp/trellis-ext-db.git'
url = 'https://github.com/trellis-ldp/trellis-ext-db'
tag = 'HEAD'
}
licenses {
license {
name = 'Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0'
comments = 'Copyright (c) 2017-2018 Trellis LDP'
}
}
}
pom.withXml {
// eliminate test-scoped dependencies
asNode().dependencies.removeAll { dep -> dep.scope == "test" }
}
from components.java
artifact(sourceJar) {
classifier = 'sources'
}
artifact(javadocJar) {
classifier = 'javadoc'
}
}
}
repositories {
maven {
def sonatypeUsername = project.hasProperty('ossrhUsername') ? ossrhUsername : ""
def sonatypePassword = project.hasProperty('ossrhPassword') ? ossrhPassword : ""
if (version.endsWith("SNAPSHOT")) {
url "https://oss.sonatype.org/content/repositories/snapshots/"
} else {
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
}
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
}
tasks.withType(PublishToMavenRepository) {
onlyIf {
subproj.name != "trellis-db-deployment"
}
}
tasks.withType(PublishToMavenLocal) {
onlyIf {
subproj.name != "trellis-db-deployment"
}
}
task install(dependsOn: [assemble, publishToMavenLocal])
task upload(dependsOn: [assemble, publish])
processResources {
outputs.upToDateWhen { false }
filesMatching(['**/features.xml', '**/banner.txt']) {
expand project.properties
}
}
signing {
required {
!version.toString().endsWith('-SNAPSHOT') && tasks.withType(PublishToMavenRepository).find {
gradle.taskGraph.hasTask it
}
}
sign publishing.publications
}
task docs(type: Javadoc) {
outputs.upToDateWhen { false }
source sourceSets.main.allJava
classpath = files(sourceSets.main.compileClasspath)
destinationDir = new File(projectDir, "docs/${version}")
options {
links "https://docs.oracle.com/javase/8/docs/api/"
links 'https://docs.oracle.com/javaee/7/api/'
links 'https://trellis-ldp.github.io/trellis/apidocs/'
links 'https://commons.apache.org/proper/commons-lang/javadocs/api-3.7/'
links 'https://commons.apache.org/proper/commons-rdf/apidocs/'
links 'https://www.dropwizard.io/1.3.0/dropwizard-core/apidocs/'
}
}
sonarqube {
skipProject = JavaVersion.current().isJava10Compatible()
}
test {
useJUnitPlatform()
jacoco {
enabled = ! JavaVersion.current().isJava11Compatible()
}
}
afterReleaseBuild.dependsOn docs
afterReleaseBuild.dependsOn publish
jacoco {
toolVersion = jacocoVersion
}
jacocoTestReport {
reports {
xml.enabled = true
html.enabled = true
}
}
}
configure(rootProject) {
task apidocs(type: Javadoc, dependsOn: getTasksByName('docs', true)) {
outputs.upToDateWhen { false }
destinationDir = new File(projectDir, "docs/apidocs")
title = "Trellis Linked Data Server Documentation"
exclude '**/impl/*'
exclude '**/*Tests.java'
options {
memberLevel = JavadocMemberLevel.PUBLIC
links "https://docs.oracle.com/javase/8/docs/api/"
links 'https://docs.oracle.com/javaee/7/api/'
links 'https://trellis-ldp.github.io/trellis/apidocs/'
links 'https://commons.apache.org/proper/commons-lang/javadocs/api-3.7/'
links 'https://commons.apache.org/proper/commons-rdf/apidocs/'
links 'https://www.dropwizard.io/1.3.0/dropwizard-core/apidocs/'
}
source subprojects.collect { project -> project.sourceSets.main.allJava }
classpath = files(subprojects.collect { project -> project.sourceSets.main.compileClasspath })
}
sonarqube {
properties {
property "sonar.projectName", "Trellis Server: Database Extension"
property "sonar.projectKey", "org.trellisldp:trellis-ext-db"
property "sonar.links.homepage", "https://www.trellisldp.org"
property "sonar.links.issue", "https://github.com/trellis-ldp/trellis-ext-db/issues"
property "sonar.links.scm_dev", "scm:git:[email protected]:trellis-ldp/trellis-ext-db.git"
}
}
// Ignore alpha, beta, milestone and release candidates
dependencyUpdates.resolutionStrategy = {
componentSelection { rules ->
rules.all { ComponentSelection selection ->
boolean rejected = ['alpha', 'beta', 'rc', 'm'].any { qualifier ->
selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/
}
if (rejected) {
selection.reject("Release Candidate")
}
}
}
}
task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
dependsOn = subprojects.test
additionalSourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories = files(subprojects.sourceSets.main.output)
executionData = files(subprojects.findAll { it.name != 'trellis-db-deployment' }.jacocoTestReport.executionData)
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
}
coveralls {
sourceDirs = subprojects.sourceSets.main.allSource.srcDirs.flatten()
jacocoReportPath = "${buildDir}/reports/jacoco/jacocoRootReport/jacocoRootReport.xml"
}
tasks.coveralls {
dependsOn 'jacocoRootReport'
}
}
Log output:
Caused by: java.lang.ClassCastException: java.base/java.lang.Long cannot be cast to java.base/java.lang.Integer
at org.apache.http.params.AbstractHttpParams.getIntParameter(AbstractHttpParams.java:70)
at org.apache.http.client.params.HttpClientParamConfig.getRequestConfig(HttpClientParamConfig.java:54)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:806)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.google.api.client.http.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:65)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.google.cloud.tools.jib.http.Connection.send(Connection.java:161)
at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.call(RegistryEndpointCaller.java:227)
at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.callWithAllowInsecureRegistryHandling(RegistryEndpointCaller.java:150)
at com.google.cloud.tools.jib.registry.RegistryEndpointCaller.call(RegistryEndpointCaller.java:140)
at com.google.cloud.tools.jib.registry.RegistryClient.callRegistryEndpoint(RegistryClient.java:356)
at com.google.cloud.tools.jib.registry.RegistryClient.pullManifest(RegistryClient.java:226)
at com.google.cloud.tools.jib.registry.RegistryClient.pullManifest(RegistryClient.java:234)
at com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.pullBaseImage(PullBaseImageStep.java:197)
at com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.call(PullBaseImageStep.java:116)
at com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.call(PullBaseImageStep.java:57)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:127)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:57)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:80)
Our Jib dev environment uses Google HTTP Client 1.23.0. Checking the dependency graph on jib-core with ./gradlew dependencies --configuration compile shows that it pulls in Apache HttpClient 4.0.1:
compile - Dependencies for source set 'main' (deprecated, use 'implementation ' instead).
+--- com.google.http-client:google-http-client:1.23.0
| +--- com.google.code.findbugs:jsr305:1.3.9
| \--- org.apache.httpcomponents:httpclient:4.0.1
However, when executing Jib on @gregjan's repo, I think Jib pulls in and uses Apache HttpClient 4.3. The source files of 4.3 match the stack trace.
And it looks like Google HTTP Client 1.23.0 does not work well with Apache HttpClient 4.3. Below is a sample project that I created to reproduce the same stack trace.
First, I declare both Google HTTP Client 1.23.0 and Apache HttpClient 4.3:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>test-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
</dependency>
</dependencies>
</project>
Main just tries a connection:
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.apache.ApacheHttpTransport;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
public class Main {
public static void main(String[] args) throws ClientProtocolException, IOException {
new ApacheHttpTransport().createRequestFactory().buildGetRequest(new GenericUrl("https://google.com")).execute();
}
}
I get the same exception:
Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
at org.apache.http.params.AbstractHttpParams.getIntParameter(AbstractHttpParams.java:70)
at org.apache.http.client.params.HttpClientParamConfig.getRequestConfig(HttpClientParamConfig.java:54)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:806)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.google.api.client.http.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:65)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at Main.main(Main.java:9)
If I use Apache HttpClient 4.0.1 by updating pom.xml, it works well.
Is there a way to force using some JARs for a Gradle task execution environment (not affecting the actual dependencies of the project)?
The build script can be forced to use a certain dependency via the buildscript block. Add this to the top of build.gradle to force Gradle to use Apache HTTP client 4.0.1 with jib-gradle-plugin:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath('org.apache.httpcomponents:httpclient:4.0.1') {
force = true
}
}
}
Many thanks! That worked for me.